1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.tradefed.util;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 
23 import com.android.tradefed.build.BuildInfo;
24 import com.android.tradefed.build.IBuildInfo;
25 import com.android.tradefed.invoker.IInvocationContext;
26 import com.android.tradefed.invoker.InvocationContext;
27 import com.android.tradefed.log.LogUtil.CLog;
28 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
29 import com.android.tradefed.result.FailureDescription;
30 import com.android.tradefed.result.ILogSaverListener;
31 import com.android.tradefed.result.ITestInvocationListener;
32 import com.android.tradefed.result.LogDataType;
33 import com.android.tradefed.result.LogFile;
34 import com.android.tradefed.result.TestDescription;
35 
36 import org.easymock.Capture;
37 import org.easymock.EasyMock;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.junit.runners.JUnit4;
41 
42 import java.io.BufferedReader;
43 import java.io.File;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.InputStreamReader;
47 import java.io.PrintWriter;
48 import java.net.Socket;
49 import java.util.HashMap;
50 import java.util.Map;
51 import java.util.Vector;
52 
53 /** Unit Tests for {@link SubprocessTestResultsParser} */
54 @RunWith(JUnit4.class)
55 public class SubprocessTestResultsParserTest {
56 
57     private static final String TEST_TYPE_DIR = "testdata";
58     private static final String SUBPROC_OUTPUT_FILE_1 = "subprocess1.txt";
59     private static final String SUBPROC_OUTPUT_FILE_2 = "subprocess2.txt";
60 
61     /**
62      * Helper to read a file from the res/testdata directory and return its contents as a String[]
63      *
64      * @param filename the name of the file (without the extension) in the res/testdata directory
65      * @return a String[] of the
66      */
readInFile(String filename)67     private String[] readInFile(String filename) {
68         Vector<String> fileContents = new Vector<String>();
69         try {
70             InputStream gtestResultStream1 = getClass().getResourceAsStream(File.separator +
71                     TEST_TYPE_DIR + File.separator + filename);
72             BufferedReader reader = new BufferedReader(new InputStreamReader(gtestResultStream1));
73             String line = null;
74             while ((line = reader.readLine()) != null) {
75                 fileContents.add(line);
76             }
77         }
78         catch (NullPointerException e) {
79             CLog.e("Gest output file does not exist: " + filename);
80         }
81         catch (IOException e) {
82             CLog.e("Unable to read contents of gtest output file: " + filename);
83         }
84         return fileContents.toArray(new String[fileContents.size()]);
85     }
86 
87     /** Tests the parser for cases of test failed, ignored, assumption failure */
88     @Test
testParse_randomEvents()89     public void testParse_randomEvents() throws Exception {
90         String[] contents = readInFile(SUBPROC_OUTPUT_FILE_1);
91         ITestInvocationListener mockRunListener =
92                 EasyMock.createMock(ITestInvocationListener.class);
93         mockRunListener.testRunStarted(
94                 EasyMock.eq("arm64-v8a CtsGestureTestCases"),
95                 EasyMock.eq(4),
96                 EasyMock.eq(0),
97                 EasyMock.anyLong());
98         mockRunListener.testStarted((TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
99         EasyMock.expectLastCall().times(4);
100         mockRunListener.testEnded(
101                 (TestDescription) EasyMock.anyObject(),
102                 EasyMock.anyLong(),
103                 EasyMock.<HashMap<String, Metric>>anyObject());
104         EasyMock.expectLastCall().times(4);
105         mockRunListener.testRunEnded(
106                 EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
107         EasyMock.expectLastCall().times(1);
108         mockRunListener.testIgnored((TestDescription) EasyMock.anyObject());
109         EasyMock.expectLastCall();
110         mockRunListener.testFailed(
111                 (TestDescription) EasyMock.anyObject(), (String) EasyMock.anyObject());
112         EasyMock.expectLastCall();
113         mockRunListener.testAssumptionFailure(
114                 (TestDescription) EasyMock.anyObject(), (String) EasyMock.anyObject());
115         EasyMock.expectLastCall();
116         EasyMock.replay(mockRunListener);
117         File tmp = FileUtil.createTempFile("sub", "unit");
118         SubprocessTestResultsParser resultParser = null;
119         try {
120             resultParser =
121                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
122             resultParser.processNewLines(contents);
123             EasyMock.verify(mockRunListener);
124         } finally {
125             StreamUtil.close(resultParser);
126             FileUtil.deleteFile(tmp);
127         }
128     }
129 
130     /** Tests the parser for cases of test starting without closing. */
131     @Test
testParse_invalidEventOrder()132     public void testParse_invalidEventOrder() throws Exception {
133         String[] contents =  readInFile(SUBPROC_OUTPUT_FILE_2);
134         ITestInvocationListener mockRunListener =
135                 EasyMock.createMock(ITestInvocationListener.class);
136         mockRunListener.testRunStarted(
137                 EasyMock.eq("arm64-v8a CtsGestureTestCases"),
138                 EasyMock.eq(4),
139                 EasyMock.eq(0),
140                 EasyMock.anyLong());
141         mockRunListener.testStarted((TestDescription) EasyMock.anyObject(), EasyMock.anyLong());
142         EasyMock.expectLastCall().times(4);
143         mockRunListener.testEnded(
144                 (TestDescription) EasyMock.anyObject(),
145                 EasyMock.anyLong(),
146                 EasyMock.<HashMap<String, Metric>>anyObject());
147         EasyMock.expectLastCall().times(3);
148         mockRunListener.testRunFailed((FailureDescription) EasyMock.anyObject());
149         EasyMock.expectLastCall().times(1);
150         mockRunListener.testRunEnded(
151                 EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject());
152         EasyMock.expectLastCall().times(1);
153         mockRunListener.testIgnored((TestDescription) EasyMock.anyObject());
154         EasyMock.expectLastCall();
155         mockRunListener.testAssumptionFailure(
156                 (TestDescription) EasyMock.anyObject(), (String) EasyMock.anyObject());
157         EasyMock.expectLastCall();
158         EasyMock.replay(mockRunListener);
159         File tmp = FileUtil.createTempFile("sub", "unit");
160         SubprocessTestResultsParser resultParser = null;
161         try {
162             resultParser =
163                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
164             resultParser.processNewLines(contents);
165             EasyMock.verify(mockRunListener);
166         } finally {
167             StreamUtil.close(resultParser);
168             FileUtil.deleteFile(tmp);
169         }
170     }
171 
172     /** Tests the parser for cases of test starting without closing. */
173     @Test
testParse_testNotStarted()174     public void testParse_testNotStarted() throws Exception {
175         ITestInvocationListener mockRunListener =
176                 EasyMock.createMock(ITestInvocationListener.class);
177         mockRunListener.testRunStarted(
178                 EasyMock.eq("arm64-v8a CtsGestureTestCases"),
179                 EasyMock.eq(4),
180                 EasyMock.eq(0),
181                 EasyMock.anyLong());
182         mockRunListener.testEnded(
183                 (TestDescription) EasyMock.anyObject(),
184                 EasyMock.anyLong(),
185                 EasyMock.<HashMap<String, Metric>>anyObject());
186         EasyMock.expectLastCall().times(1);
187         EasyMock.replay(mockRunListener);
188         File tmp = FileUtil.createTempFile("sub", "unit");
189         SubprocessTestResultsParser resultParser = null;
190         try {
191             resultParser =
192                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
193             String startRun =
194                     "TEST_RUN_STARTED {\"testCount\":4,\"runName\":\"arm64-v8a "
195                             + "CtsGestureTestCases\"}\n";
196             FileUtil.writeToFile(startRun, tmp, true);
197             String testEnded =
198                     "03-22 14:04:02 E/SubprocessResultsReporter: TEST_ENDED "
199                             + "{\"end_time\":1489160958359,\"className\":\"android.gesture.cts."
200                             + "GestureLibraryTest\",\"testName\":\"testGetGestures\",\"extra\":\""
201                             + "data\"}\n";
202             FileUtil.writeToFile(testEnded, tmp, true);
203             resultParser.parseFile(tmp);
204             EasyMock.verify(mockRunListener);
205         } finally {
206             StreamUtil.close(resultParser);
207             FileUtil.deleteFile(tmp);
208         }
209     }
210 
211     /** Tests the parser for a cases when there is no start/end time stamp. */
212     @Test
testParse_noTimeStamp()213     public void testParse_noTimeStamp() throws Exception {
214         ITestInvocationListener mockRunListener =
215                 EasyMock.createMock(ITestInvocationListener.class);
216         mockRunListener.testRunStarted(
217                 EasyMock.eq("arm64-v8a CtsGestureTestCases"),
218                 EasyMock.eq(4),
219                 EasyMock.eq(0),
220                 EasyMock.anyLong());
221         mockRunListener.testStarted(EasyMock.anyObject());
222         mockRunListener.testEnded(
223                 (TestDescription) EasyMock.anyObject(),
224                 EasyMock.<HashMap<String, Metric>>anyObject());
225         EasyMock.expectLastCall().times(1);
226         EasyMock.replay(mockRunListener);
227         File tmp = FileUtil.createTempFile("sub", "unit");
228         SubprocessTestResultsParser resultParser = null;
229         try {
230             resultParser =
231                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
232             String startRun = "TEST_RUN_STARTED {\"testCount\":4,\"runName\":\"arm64-v8a "
233                     + "CtsGestureTestCases\"}\n";
234             FileUtil.writeToFile(startRun, tmp, true);
235             String testStarted =
236                     "03-22 14:04:02 E/SubprocessResultsReporter: TEST_STARTED "
237                             + "{\"className\":\"android.gesture.cts."
238                             + "GestureLibraryTest\",\"testName\":\"testGetGestures\"}\n";
239             FileUtil.writeToFile(testStarted, tmp, true);
240             String testEnded =
241                     "03-22 14:04:02 E/SubprocessResultsReporter: TEST_ENDED "
242                             + "{\"className\":\"android.gesture.cts."
243                             + "GestureLibraryTest\",\"testName\":\"testGetGestures\",\"extra\":\""
244                             + "data\"}\n";
245             FileUtil.writeToFile(testEnded, tmp, true);
246             resultParser.parseFile(tmp);
247             EasyMock.verify(mockRunListener);
248         } finally {
249             StreamUtil.close(resultParser);
250             FileUtil.deleteFile(tmp);
251         }
252     }
253 
254     /** Test injecting an invocation failure and verify the callback is called. */
255     @Test
testParse_invocationFailed()256     public void testParse_invocationFailed() throws Exception {
257         ITestInvocationListener mockRunListener =
258                 EasyMock.createMock(ITestInvocationListener.class);
259         Capture<Throwable> cap = new Capture<Throwable>();
260         mockRunListener.invocationFailed(EasyMock.capture(cap));
261         EasyMock.replay(mockRunListener);
262         File tmp = FileUtil.createTempFile("sub", "unit");
263         SubprocessTestResultsParser resultParser = null;
264         try {
265             resultParser =
266                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
267             String cause = "com.android.tradefed.targetprep."
268                     + "TargetSetupError: Not all target preparation steps completed\n\tat "
269                     + "com.android.compatibility.common.tradefed.targetprep."
270                     + "ApkInstrumentationPreparer.run(ApkInstrumentationPreparer.java:88)\n";
271             String startRun = "03-23 11:50:12 E/SubprocessResultsReporter: "
272                     + "INVOCATION_FAILED {\"cause\":\"com.android.tradefed.targetprep."
273                     + "TargetSetupError: Not all target preparation steps completed\\n\\tat "
274                     + "com.android.compatibility.common.tradefed.targetprep."
275                     + "ApkInstrumentationPreparer.run(ApkInstrumentationPreparer.java:88)\\n\"}\n";
276             FileUtil.writeToFile(startRun, tmp, true);
277             resultParser.parseFile(tmp);
278             EasyMock.verify(mockRunListener);
279             String expected = cap.getValue().getMessage();
280             assertEquals(cause, expected);
281         } finally {
282             StreamUtil.close(resultParser);
283             FileUtil.deleteFile(tmp);
284         }
285     }
286 
287     /** Report results when received from socket. */
288     @Test
testParser_receiveFromSocket()289     public void testParser_receiveFromSocket() throws Exception {
290         ITestInvocationListener mockRunListener =
291                 EasyMock.createMock(ITestInvocationListener.class);
292         mockRunListener.testRunStarted(
293                 EasyMock.eq("arm64-v8a CtsGestureTestCases"),
294                 EasyMock.eq(4),
295                 EasyMock.eq(0),
296                 EasyMock.anyLong());
297         mockRunListener.testEnded(
298                 (TestDescription) EasyMock.anyObject(),
299                 EasyMock.anyLong(),
300                 EasyMock.<HashMap<String, Metric>>anyObject());
301         EasyMock.expectLastCall().times(1);
302         EasyMock.replay(mockRunListener);
303         SubprocessTestResultsParser resultParser = null;
304         Socket socket = null;
305         try {
306             resultParser =
307                     new SubprocessTestResultsParser(mockRunListener, true, new InvocationContext());
308             socket = new Socket("localhost", resultParser.getSocketServerPort());
309             if (!socket.isConnected()) {
310                 fail("socket did not connect");
311             }
312             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
313             String startRun = "TEST_RUN_STARTED {\"testCount\":4,\"runName\":\"arm64-v8a "
314                     + "CtsGestureTestCases\"}\n";
315             out.print(startRun);
316             out.flush();
317             String testEnded =
318                     "03-22 14:04:02 E/SubprocessResultsReporter: TEST_ENDED "
319                             + "{\"end_time\":1489160958359,\"className\":\"android.gesture.cts."
320                             + "GestureLibraryTest\",\"testName\":\"testGetGestures\",\"extra\":\""
321                             + "data\"}\n";
322             out.print(testEnded);
323             out.flush();
324             StreamUtil.close(socket);
325             assertTrue(resultParser.joinReceiver(500));
326             EasyMock.verify(mockRunListener);
327         } finally {
328             StreamUtil.close(resultParser);
329             StreamUtil.close(socket);
330         }
331     }
332 
333     /** When the receiver thread fails to join then an exception is thrown. */
334     @Test
testParser_failToJoin()335     public void testParser_failToJoin() throws Exception {
336         ITestInvocationListener mockRunListener =
337                 EasyMock.createMock(ITestInvocationListener.class);
338         EasyMock.replay(mockRunListener);
339         SubprocessTestResultsParser resultParser = null;
340         try {
341             resultParser =
342                     new SubprocessTestResultsParser(mockRunListener, true, new InvocationContext());
343             assertFalse(resultParser.joinReceiver(50));
344             EasyMock.verify(mockRunListener);
345         } finally {
346             StreamUtil.close(resultParser);
347         }
348     }
349 
350     /** Tests that the parser can be joined immediately if no connection was established. */
351     @Test
testParser_noConnection()352     public void testParser_noConnection() throws Exception {
353         ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
354         EasyMock.replay(listener);
355         try (SubprocessTestResultsParser parser =
356                 new SubprocessTestResultsParser(listener, true, new InvocationContext())) {
357             // returns immediately as a connection was not established
358             assertTrue(parser.joinReceiver(50, false));
359             EasyMock.verify(listener);
360         }
361     }
362 
363     /** Tests the parser receiving event on updating test tag. */
364     @Test
testParse_testTag()365     public void testParse_testTag() throws Exception {
366         final String subTestTag = "test_tag_in_subprocess";
367         InvocationContext context = new InvocationContext();
368         context.setTestTag("stub");
369 
370         ITestInvocationListener mockRunListener =
371                 EasyMock.createMock(ITestInvocationListener.class);
372         EasyMock.replay(mockRunListener);
373         File tmp = FileUtil.createTempFile("sub", "unit");
374         SubprocessTestResultsParser resultParser = null;
375         try {
376             resultParser = new SubprocessTestResultsParser(mockRunListener, false, context);
377             String testTagEvent =
378                     String.format(
379                             "INVOCATION_STARTED {\"testTag\": \"%s\",\"start_time\":250}",
380                             subTestTag);
381             FileUtil.writeToFile(testTagEvent, tmp, true);
382             resultParser.parseFile(tmp);
383             EasyMock.verify(mockRunListener);
384             assertEquals(subTestTag, context.getTestTag());
385             assertEquals(250l, resultParser.getStartTime().longValue());
386         } finally {
387             StreamUtil.close(resultParser);
388             FileUtil.deleteFile(tmp);
389         }
390     }
391 
392     /** Tests the parser smoothly handling case where there is no build info. */
393     @Test
testParse_testInvocationEndedWithoutBuildInfo()394     public void testParse_testInvocationEndedWithoutBuildInfo() throws Exception {
395         InvocationContext context = new InvocationContext();
396         context.setTestTag("stub");
397 
398         ITestInvocationListener mockRunListener =
399                 EasyMock.createMock(ITestInvocationListener.class);
400         EasyMock.replay(mockRunListener);
401         File tmp = FileUtil.createTempFile("sub", "unit");
402         SubprocessTestResultsParser resultParser = null;
403         try {
404             resultParser = new SubprocessTestResultsParser(mockRunListener, false, context);
405             String event = "INVOCATION_ENDED {\"foo\": \"bar\"}";
406             FileUtil.writeToFile(event, tmp, true);
407             resultParser.parseFile(tmp);
408             EasyMock.verify(mockRunListener);
409         } finally {
410             StreamUtil.close(resultParser);
411             FileUtil.deleteFile(tmp);
412         }
413     }
414 
415     /** Tests the parser propagating up build attributes. */
416     @Test
testParse_testInvocationEnded()417     public void testParse_testInvocationEnded() throws Exception {
418         InvocationContext context = new InvocationContext();
419         IBuildInfo info = new BuildInfo();
420         context.setTestTag("stub");
421         context.addDeviceBuildInfo("device1", info);
422         info.addBuildAttribute("baz", "qux");
423 
424         ITestInvocationListener mockRunListener =
425                 EasyMock.createMock(ITestInvocationListener.class);
426         EasyMock.replay(mockRunListener);
427         File tmp = FileUtil.createTempFile("sub", "unit");
428         SubprocessTestResultsParser resultParser = null;
429         try {
430             resultParser = new SubprocessTestResultsParser(mockRunListener, false, context);
431             String event = "INVOCATION_ENDED {\"foo\": \"bar\", \"baz\": \"wrong\"}";
432             FileUtil.writeToFile(event, tmp, true);
433             resultParser.parseFile(tmp);
434             Map<String, String> attributes = info.getBuildAttributes();
435             // foo=bar is propagated up
436             assertEquals("bar", attributes.get("foo"));
437             // baz=qux is not overwritten
438             assertEquals("qux", attributes.get("baz"));
439             EasyMock.verify(mockRunListener);
440         } finally {
441             StreamUtil.close(resultParser);
442             FileUtil.deleteFile(tmp);
443         }
444     }
445 
446     /** Tests the parser should not overwrite the test tag in parent process if it's already set. */
447     @Test
testParse_testTagNotOverwrite()448     public void testParse_testTagNotOverwrite() throws Exception {
449         final String subTestTag = "test_tag_in_subprocess";
450         final String parentTestTag = "test_tag_in_parent_process";
451         InvocationContext context = new InvocationContext();
452         context.setTestTag(parentTestTag);
453 
454         ITestInvocationListener mockRunListener =
455                 EasyMock.createMock(ITestInvocationListener.class);
456         EasyMock.replay(mockRunListener);
457         File tmp = FileUtil.createTempFile("sub", "unit");
458         SubprocessTestResultsParser resultParser = null;
459         try {
460             resultParser = new SubprocessTestResultsParser(mockRunListener, false, context);
461             String testTagEvent = String.format("TEST_TAG %s", subTestTag);
462             FileUtil.writeToFile(testTagEvent, tmp, true);
463             resultParser.parseFile(tmp);
464             EasyMock.verify(mockRunListener);
465             assertEquals(parentTestTag, context.getTestTag());
466         } finally {
467             StreamUtil.close(resultParser);
468             FileUtil.deleteFile(tmp);
469         }
470     }
471 
472     /** Test that module start and end is properly parsed when reported. */
473     @Test
testParse_moduleStarted_end()474     public void testParse_moduleStarted_end() throws Exception {
475         ITestInvocationListener mockRunListener =
476                 EasyMock.createMock(ITestInvocationListener.class);
477         mockRunListener.testModuleStarted(EasyMock.anyObject());
478         mockRunListener.testModuleEnded();
479         EasyMock.replay(mockRunListener);
480         IInvocationContext fakeModuleContext = new InvocationContext();
481         File tmp = FileUtil.createTempFile("sub", "unit");
482         SubprocessTestResultsParser resultParser = null;
483         File serializedModule = null;
484         try {
485             serializedModule = SerializationUtil.serialize(fakeModuleContext);
486             resultParser =
487                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
488             String moduleStart =
489                     String.format(
490                             "TEST_MODULE_STARTED {\"moduleContextFileName\":\"%s\"}\n",
491                             serializedModule.getAbsolutePath());
492             FileUtil.writeToFile(moduleStart, tmp, true);
493             String moduleEnd = "TEST_MODULE_ENDED {}\n";
494             FileUtil.writeToFile(moduleEnd, tmp, true);
495 
496             resultParser.parseFile(tmp);
497             EasyMock.verify(mockRunListener);
498         } finally {
499             StreamUtil.close(resultParser);
500             FileUtil.deleteFile(tmp);
501             FileUtil.deleteFile(serializedModule);
502         }
503     }
504 
505     /** Test that logAssociation event is properly passed and parsed. */
506     @Test
testParse_logAssociation()507     public void testParse_logAssociation() throws Exception {
508         ILogSaverListener mockRunListener = EasyMock.createMock(ILogSaverListener.class);
509         Capture<LogFile> capture = new Capture<>();
510         mockRunListener.logAssociation(
511                 EasyMock.eq("subprocess-dataname"), EasyMock.capture(capture));
512         EasyMock.replay(mockRunListener);
513         LogFile logFile = new LogFile("path", "url", LogDataType.TEXT);
514         File serializedLogFile = null;
515         File tmp = FileUtil.createTempFile("sub", "unit");
516         SubprocessTestResultsParser resultParser = null;
517         try {
518             serializedLogFile = SerializationUtil.serialize(logFile);
519             resultParser =
520                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
521             String logAssociation =
522                     String.format(
523                             "LOG_ASSOCIATION {\"loggedFile\":\"%s\",\"dataName\":\"dataname\"}\n",
524                             serializedLogFile.getAbsolutePath());
525             FileUtil.writeToFile(logAssociation, tmp, true);
526             resultParser.parseFile(tmp);
527             EasyMock.verify(mockRunListener);
528         } finally {
529             StreamUtil.close(resultParser);
530             FileUtil.deleteFile(serializedLogFile);
531             FileUtil.deleteFile(tmp);
532         }
533         LogFile received = capture.getValue();
534         assertEquals(logFile.getPath(), received.getPath());
535         assertEquals(logFile.getUrl(), received.getUrl());
536         assertEquals(logFile.getType(), received.getType());
537     }
538 
539     /** If a log comes from subprocess but was not uploaded (no URL), we relog it. */
540     @Test
testParse_logAssociation_notUploaded()541     public void testParse_logAssociation_notUploaded() throws Exception {
542         ILogSaverListener mockRunListener = EasyMock.createMock(ILogSaverListener.class);
543         mockRunListener.testLog(
544                 EasyMock.eq("subprocess-dataname"),
545                 EasyMock.eq(LogDataType.TEXT),
546                 EasyMock.anyObject());
547         EasyMock.replay(mockRunListener);
548         File log = FileUtil.createTempFile("dataname-log-assos", ".txt");
549         LogFile logFile = new LogFile(log.getAbsolutePath(), null, LogDataType.TEXT);
550         File serializedLogFile = null;
551         File tmp = FileUtil.createTempFile("sub", "unit");
552         SubprocessTestResultsParser resultParser = null;
553         try {
554             serializedLogFile = SerializationUtil.serialize(logFile);
555             resultParser =
556                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
557             String logAssociation =
558                     String.format(
559                             "LOG_ASSOCIATION {\"loggedFile\":\"%s\",\"dataName\":\"dataname\"}\n",
560                             serializedLogFile.getAbsolutePath());
561             FileUtil.writeToFile(logAssociation, tmp, true);
562             resultParser.parseFile(tmp);
563             EasyMock.verify(mockRunListener);
564         } finally {
565             StreamUtil.close(resultParser);
566             FileUtil.deleteFile(serializedLogFile);
567             FileUtil.deleteFile(tmp);
568             FileUtil.deleteFile(log);
569         }
570     }
571 
572     @Test
testParse_logAssociation_zipped()573     public void testParse_logAssociation_zipped() throws Exception {
574         ILogSaverListener mockRunListener = EasyMock.createMock(ILogSaverListener.class);
575         mockRunListener.testLog(
576                 EasyMock.eq("subprocess-dataname"),
577                 EasyMock.eq(LogDataType.TEXT),
578                 EasyMock.anyObject());
579         EasyMock.replay(mockRunListener);
580         File logDir = FileUtil.createTempDir("log-assos-dir");
581         File log = FileUtil.createTempFile("dataname-log-assos", ".txt", logDir);
582         File zipLog = ZipUtil.createZip(logDir);
583         LogFile logFile = new LogFile(zipLog.getAbsolutePath(), null, LogDataType.TEXT);
584         File serializedLogFile = null;
585         File tmp = FileUtil.createTempFile("sub", "unit");
586         SubprocessTestResultsParser resultParser = null;
587         try {
588             serializedLogFile = SerializationUtil.serialize(logFile);
589             resultParser =
590                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
591             String logAssociation =
592                     String.format(
593                             "LOG_ASSOCIATION {\"loggedFile\":\"%s\",\"dataName\":\"dataname\"}\n",
594                             serializedLogFile.getAbsolutePath());
595             FileUtil.writeToFile(logAssociation, tmp, true);
596             resultParser.parseFile(tmp);
597             EasyMock.verify(mockRunListener);
598         } finally {
599             StreamUtil.close(resultParser);
600             FileUtil.deleteFile(serializedLogFile);
601             FileUtil.deleteFile(tmp);
602             FileUtil.deleteFile(log);
603             FileUtil.recursiveDelete(logDir);
604             FileUtil.deleteFile(zipLog);
605         }
606     }
607 
608     @Test
testParse_avoidDoubleLog()609     public void testParse_avoidDoubleLog() throws Exception {
610         ILogSaverListener mockRunListener = EasyMock.createMock(ILogSaverListener.class);
611         mockRunListener.testLog(
612                 EasyMock.eq("subprocess-dataname"),
613                 EasyMock.eq(LogDataType.TEXT),
614                 EasyMock.anyObject());
615         EasyMock.replay(mockRunListener);
616         File testLogFile = FileUtil.createTempFile("dataname", ".txt");
617         File testLogFile2 = FileUtil.createTempFile("dataname", ".txt");
618         LogFile logFile = new LogFile(testLogFile.getAbsolutePath(), "", LogDataType.TEXT);
619         File serializedLogFile = null;
620         File tmp = FileUtil.createTempFile("sub", "unit");
621         SubprocessTestResultsParser resultParser = null;
622         try {
623             serializedLogFile = SerializationUtil.serialize(logFile);
624             resultParser =
625                     new SubprocessTestResultsParser(mockRunListener, new InvocationContext());
626             resultParser.setIgnoreTestLog(false);
627             String logAssociation =
628                     String.format(
629                             "TEST_LOG {\"dataType\":\"TEXT\",\"dataName\":\"dataname\","
630                                     + "\"dataFile\":\"%s\"}'\n"
631                                     + "LOG_ASSOCIATION {\"loggedFile\":\"%s\","
632                                     + "\"dataName\":\"dataname\"}\n",
633                             testLogFile2.getAbsolutePath(), serializedLogFile.getAbsolutePath());
634             FileUtil.writeToFile(logAssociation, tmp, true);
635             resultParser.parseFile(tmp);
636             EasyMock.verify(mockRunListener);
637         } finally {
638             StreamUtil.close(resultParser);
639             FileUtil.deleteFile(serializedLogFile);
640             FileUtil.deleteFile(tmp);
641             FileUtil.deleteFile(testLogFile);
642             FileUtil.deleteFile(testLogFile2);
643         }
644     }
645 }
646