1 package emissary.place;
2
3 import emissary.core.DataObjectFactory;
4 import emissary.core.IBaseDataObject;
5 import emissary.test.core.junit5.UnitTest;
6 import emissary.util.io.ResourceReader;
7 import emissary.util.shell.Executrix;
8
9 import org.apache.commons.io.IOUtils;
10 import org.junit.jupiter.api.AfterEach;
11 import org.junit.jupiter.api.BeforeEach;
12 import org.junit.jupiter.api.Test;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.nio.charset.StandardCharsets;
20 import java.nio.file.Files;
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import javax.annotation.Nullable;
24
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertNull;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.ArgumentMatchers.isA;
31 import static org.mockito.ArgumentMatchers.isNull;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.times;
34 import static org.mockito.Mockito.validateMockitoUsage;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
37
38 class UnixCommandPlaceTest extends UnitTest {
39 @Nullable
40 private UnixCommandPlace place;
41 private static final Logger logger = LoggerFactory.getLogger(UnixCommandPlaceTest.class);
42 private Path scriptFile;
43 private static final String W = "Президент Буш";
44 @Nullable
45 private IBaseDataObject payload;
46 private static final String FORM = "TEST";
47
48 @Override
49 @BeforeEach
50 public void setUp() throws Exception {
51 scriptFile = Paths.get(TMPDIR, "testUnixCommand.sh");
52
53 try (InputStream is = new ResourceReader().getConfigDataAsStream(this.getClass())) {
54 place = new UnixCommandPlace(is);
55 place.executrix.setTmpDir(TMPDIR);
56 place.executrix.setCommand(TMPDIR + "/testUnixCommand.sh <INPUT_NAME> <OUTPUT_NAME>");
57 } catch (Exception ex) {
58 logger.error("Cannot create UnixCommandPlace", ex);
59 }
60
61 payload = DataObjectFactory.getInstance(new Object[] {"abcdefg".getBytes(), "myPayload", FORM});
62 }
63
64 @Override
65 @AfterEach
66 public void tearDown() throws Exception {
67 super.tearDown();
68 place.shutDown();
69 place = null;
70 payload = null;
71 Files.deleteIfExists(scriptFile);
72 validateMockitoUsage();
73 }
74
75 @Test
76 void testUnixCommandPlaceStdout() throws Exception {
77 assertNotNull(place, "Place must be created");
78 createScript(Executrix.OUTPUT_TYPE.STD);
79
80 place.process(payload);
81 byte[] altView = payload.getAlternateView("TEST_VIEW");
82 assertNotNull(altView, "Alt view should have been created");
83 assertEquals(FORM, payload.currentForm(), "Payload should have same current form");
84 assertEquals(W, new String(altView).trim(), "Clean UTF-8 coming from the script must be maintained");
85 }
86
87 @Test
88 void testUnixCommandPlaceFile() throws Exception {
89 assertNotNull(place, "Place must be created");
90 place.setFileOutputCommand();
91 createScript(Executrix.OUTPUT_TYPE.FILE);
92
93 place.process(payload);
94 byte[] altView = payload.getAlternateView("TEST_VIEW");
95 assertNotNull(altView, "Alt view should have been created");
96 assertEquals(FORM, payload.currentForm(), "Payload should have same current form");
97 assertEquals(W, new String(altView).trim(), "Clean UTF-8 coming from the script must be maintained");
98 }
99
100 @Test
101 void testUnixCommandPlaceLogging() throws Exception {
102 assertNotNull(place, "Place must be created");
103 Logger mockLogger = mock(Logger.class);
104 place.setLogger(mockLogger);
105 createLogScript();
106 place.process(payload);
107 verify(mockLogger, times(LOG_MSGS.length)).info(anyString());
108 }
109
110 @Test
111 void testFileProcess() throws Exception {
112 Executrix e = mock(Executrix.class);
113
114
115 when(e.execute(eq(new String[] {"negative"}), (StringBuilder) isNull(), isA(StringBuilder.class))).thenReturn(-1);
116 when(e.execute(eq(new String[] {"zero"}), (StringBuilder) isNull(), isA(StringBuilder.class))).thenReturn(0);
117 when(e.execute(eq(new String[] {"positive"}), (StringBuilder) isNull(), isA(StringBuilder.class))).thenReturn(1);
118
119 place.setExecutrix(e);
120
121
122 String DATA = "test-test";
123 Path outputFile = Paths.get(TMPDIR, "output.out");
124
125 try {
126 IOUtils.write(DATA, Files.newOutputStream(outputFile), StandardCharsets.UTF_8);
127
128
129 assertNull(place.fileProcess(new String[] {"negative"}, outputFile.toAbsolutePath().toString()));
130 assertNull(place.fileProcess(new String[] {"positive"}, outputFile.toAbsolutePath().toString()));
131
132
133 assertEquals(DATA, new String(place.fileProcess(new String[] {"zero"}, outputFile.toAbsolutePath().toString())));
134 } finally {
135 Files.deleteIfExists(outputFile);
136 }
137 }
138
139 @Test
140 void testStdOutProcess() {
141 Executrix e = mock(Executrix.class);
142
143
144 when(e.execute(eq(new String[] {"negative"}), isA(StringBuilder.class), isA(StringBuilder.class), eq(place.charset))).thenReturn(-1);
145 when(e.execute(eq(new String[] {"zero"}), isA(StringBuilder.class), isA(StringBuilder.class), eq(place.charset))).thenReturn(0);
146 when(e.execute(eq(new String[] {"positive"}), isA(StringBuilder.class), isA(StringBuilder.class), eq(place.charset))).thenReturn(1);
147
148 place.setExecutrix(e);
149
150
151 assertNull(place.stdOutProcess(new String[] {"negative"}, false));
152 assertNull(place.stdOutProcess(new String[] {"positive"}, false));
153
154
155 assertEquals("", new String(place.stdOutProcess(new String[] {"zero"}, false)));
156 }
157
158 private static final String[] LOG_MSGS = {"ERROR script error message", "WARN script warn message", "INFO script info message",
159 "DEBUG script debug message"};
160
161 private void createLogScript() throws IOException {
162 try (OutputStream fos = startScript()) {
163
164
165 for (String msg : LOG_MSGS) {
166 fos.write(("echo '" + msg + "' >> UCP.log\n").getBytes());
167 }
168
169
170 fos.write("cat ${1} > ${2}\n".getBytes());
171 scriptFile.toFile().setExecutable(true);
172 }
173 }
174
175 private OutputStream startScript() throws IOException {
176 Files.deleteIfExists(scriptFile);
177 OutputStream fos = Files.newOutputStream(scriptFile);
178 fos.write("#!/bin/bash\n".getBytes());
179 return fos;
180 }
181
182 private void createScript(Executrix.OUTPUT_TYPE ot) throws IOException {
183 try (OutputStream fos = startScript()) {
184 fos.write(("echo '" + W + "'").getBytes());
185 if (ot == Executrix.OUTPUT_TYPE.FILE) {
186 fos.write(" > ${2}".getBytes());
187 }
188 fos.write('\n');
189 scriptFile.toFile().setExecutable(true);
190 }
191 }
192
193 }