View Javadoc
1   package io.guixer.logs;
2   
3   import static com.google.common.base.Preconditions.checkNotNull;
4   import static com.google.common.base.Preconditions.checkState;
5   import static io.guixer.logs.Utils.tokenize;
6   import static io.guixer.logs.lines.LogLine.Type.ERROR;
7   import static java.nio.charset.StandardCharsets.UTF_8;
8   import static net.avcompris.commons3.databeans.DataBeans.instantiate;
9   import static org.apache.commons.lang3.StringUtils.isBlank;
10  import static org.apache.commons.lang3.StringUtils.substringAfter;
11  import static org.apache.commons.lang3.StringUtils.substringBefore;
12  
13  import java.io.File;
14  import java.io.FileNotFoundException;
15  import java.io.IOException;
16  
17  import org.apache.commons.io.FileUtils;
18  import org.apache.commons.lang3.NotImplementedException;
19  import org.joda.time.DateTime;
20  
21  import io.guixer.logs.lines.AssertAbsentLogLine;
22  import io.guixer.logs.lines.AssertFalseLogLine;
23  import io.guixer.logs.lines.AssertPresentLogLine;
24  import io.guixer.logs.lines.AssertTrueLogLine;
25  import io.guixer.logs.lines.AttributeLogLine;
26  import io.guixer.logs.lines.BeginGroupLogLine;
27  import io.guixer.logs.lines.CallLogLine;
28  import io.guixer.logs.lines.ClearLogLine;
29  import io.guixer.logs.lines.ClickLogLine;
30  import io.guixer.logs.lines.DoneLogLine;
31  import io.guixer.logs.lines.EndGroupLogLine;
32  import io.guixer.logs.lines.ErrorLogLine;
33  import io.guixer.logs.lines.ExecuteScriptLogLine;
34  import io.guixer.logs.lines.ExtLogLine;
35  import io.guixer.logs.lines.FailureLogLine;
36  import io.guixer.logs.lines.GetLogLine;
37  import io.guixer.logs.lines.IntentLogLine;
38  import io.guixer.logs.lines.LogLine;
39  import io.guixer.logs.lines.MessageLogLine;
40  import io.guixer.logs.lines.SendKeysLogLine;
41  import io.guixer.logs.lines.SetLaneLogLine;
42  import io.guixer.logs.lines.SetMaskedVariableLogLine;
43  import io.guixer.logs.lines.SetVariableLogLine;
44  import io.guixer.logs.lines.SleepLogLine;
45  import io.guixer.logs.lines.StatusLogLine;
46  import io.guixer.logs.lines.SuccessLogLine;
47  import io.guixer.logs.lines.TagLogLine;
48  import io.guixer.logs.lines.TakeScreenshotLogLine;
49  import io.guixer.logs.lines.WaitForLogLine;
50  import io.guixer.logs.lines.WaitForNotLogLine;
51  import io.guixer.types.AttributeScope;
52  
53  public class LogLoader {
54  
55  	private final Log log;
56  
57  	public LogLoader(
58  		final File logDirOrFile
59  	) throws IOException {
60  
61  		checkNotNull(logDirOrFile, "logDirOrFile");
62  
63  		final File testLogFile;
64  
65  		if (logDirOrFile.isDirectory()) {
66  
67  			testLogFile = new File(logDirOrFile, "test.log");
68  
69  		} else {
70  
71  			testLogFile = logDirOrFile;
72  		}
73  
74  		this.log = loadLog(testLogFile);
75  	}
76  
77  	private static Log loadLog(
78  		final File testLogFile
79  	) throws IOException {
80  
81  		if (!testLogFile.isFile()) {
82  
83  			throw new FileNotFoundException("test.log should exist and be a file: " + testLogFile.getCanonicalPath());
84  		}
85  
86  		final byte[] bytes = FileUtils.readFileToByteArray(testLogFile);
87  
88  		final MutableLog log = instantiate(MutableLog.class) //
89  				.setSuccessCount(0) //
90  				.setFailureCount(0) //
91  				.setInError(false) //
92  				.setRawBytes(bytes);
93  
94  		ErrorLogLine currentError = null;
95  
96  		for (final String line : FileUtils.readLines(testLogFile, UTF_8)) {
97  
98  			if (isBlank(line)) {
99  
100 				currentError = null;
101 
102 				continue;
103 			}
104 
105 			if (currentError != null) {
106 
107 				currentError.addLine(line);
108 
109 				continue;
110 			}
111 
112 			if (line.startsWith("guixerVersion: ") //
113 					|| line.startsWith("gxVersion: ")) {
114 
115 				log.setGuixerVersion(substringAfter(line, ": "));
116 
117 			} else if (line.startsWith("date: ")) {
118 
119 				final String dateAsString = substringAfter(line, ": ");
120 
121 				log.setDateAsString(dateAsString);
122 
123 				final DateTime date = DateTime.parse(dateAsString);
124 
125 				log.setDate(date);
126 
127 			} else if (line.startsWith("testClassName: ")) {
128 
129 				log.setTestClassName(substringAfter(line, ": "));
130 
131 			} else if (line.startsWith("testClassSimpleName: ")) {
132 
133 				final String testClassSimpleName = substringAfter(line, ": ");
134 
135 				final String testClassName = log.getTestClassName();
136 
137 				checkState(testClassName.endsWith("." + testClassSimpleName), //
138 						"testClassName should end with: ." + testClassSimpleName + ", but was: " + testClassName);
139 
140 				log.setTestClassSimpleName(testClassSimpleName);
141 
142 			} else if (line.startsWith("testMethodName: ")) {
143 
144 				log.setTestMethodName(substringAfter(line, ": "));
145 
146 			} else if (line.startsWith("timeMillis: ")) {
147 
148 				final String timeMillisAsString = substringAfter(line, ": ");
149 
150 				final long timeMillis;
151 
152 				try {
153 
154 					timeMillis = Long.parseLong(timeMillisAsString);
155 
156 				} catch (final NumberFormatException e) {
157 
158 					throw new RuntimeException("Unable to parse timeMillis: " + timeMillisAsString);
159 				}
160 
161 				log.setTimeMillis(timeMillis);
162 
163 			} else if (line.startsWith("suite: ")) {
164 
165 				// do nothing
166 
167 			} else if (line.startsWith("scenario: ") //
168 					|| line.startsWith("test: ")) {
169 
170 				log.setScenario(substringAfter(line, ": "));
171 
172 			} else if (line.startsWith("successCount: ")) {
173 
174 				final String successCountAsString = substringAfter(line, ": ");
175 
176 				final int successCount;
177 
178 				try {
179 
180 					successCount = Integer.parseInt(successCountAsString);
181 
182 				} catch (final NumberFormatException e) {
183 
184 					throw new RuntimeException("Unable to parse successCount: " + successCountAsString, e);
185 				}
186 
187 				log.setSuccessCount(successCount);
188 
189 			} else if (line.startsWith("failureCount: ")) {
190 
191 				final String failureCountAsString = substringAfter(line, ": ");
192 
193 				final int failureCount;
194 
195 				try {
196 
197 					failureCount = Integer.parseInt(failureCountAsString);
198 
199 				} catch (final NumberFormatException e) {
200 
201 					throw new RuntimeException("Unable to parse failureCount: " + failureCountAsString, e);
202 				}
203 
204 				log.setFailureCount(failureCount);
205 
206 			} else if (line.startsWith("attribute: ")) {
207 
208 				// e.g. attribute: UPLOAD "yyy" "456"
209 
210 				final String[] tokens = tokenize(substringAfter(line, ": "));
211 
212 				log.addToAttributes(new AttributeLogLine( //
213 						log.getDate().getMillis(), //
214 						line, //
215 						AttributeScope.valueOf(tokens[0]), tokens[1], tokens[2]));
216 
217 			} else if (line.startsWith("tag: ")) {
218 
219 				// e.g. tag: RUN "yyy"
220 
221 				final String[] tokens = tokenize(substringAfter(line, ": "));
222 
223 				log.addToAttributes(new TagLogLine( //
224 						log.getDate().getMillis(), //
225 						line, //
226 						AttributeScope.valueOf(tokens[0]), tokens[1]));
227 
228 			} else {
229 
230 				final LogLine logLine = parseLogLine(line);
231 
232 				log.addToLogLines(logLine);
233 
234 				if (logLine.getType() == ERROR) {
235 
236 					log.setInError(true);
237 
238 					currentError = (ErrorLogLine) logLine;
239 				}
240 			}
241 		}
242 
243 		return log;
244 	}
245 
246 	private static LogLine parseLogLine(
247 		final String line
248 	) {
249 
250 		checkNotNull(line, "line");
251 
252 		final String timeMillisAsString = substringBefore(line, " ");
253 
254 		final long timeMillis;
255 
256 		try {
257 
258 			timeMillis = Long.parseLong(timeMillisAsString);
259 
260 		} catch (final NumberFormatException e) {
261 
262 			throw new RuntimeException("Unable to parse timeMillis: " + timeMillisAsString);
263 		}
264 
265 		final String rawText = substringAfter(line, " ");
266 
267 		if ("Done.".equals(rawText)) {
268 			return new DoneLogLine(timeMillis, rawText);
269 		}
270 
271 		final String command = substringBefore(rawText, ": ");
272 		final String args = substringAfter(rawText, ": ");
273 
274 		if ("beginGroup".equals(command)) {
275 
276 			return new BeginGroupLogLine(timeMillis, rawText, args);
277 
278 		} else if ("endGroup".equals(command)) {
279 
280 			return new EndGroupLogLine(timeMillis, rawText, args);
281 
282 		} else if ("status".equals(command)) {
283 
284 			return new StatusLogLine(timeMillis, rawText, args);
285 
286 		} else if ("intent".equals(command)) {
287 
288 			return new IntentLogLine(timeMillis, rawText, args);
289 
290 		} else if ("setLane".equals(command)) {
291 
292 			return new SetLaneLogLine(timeMillis, rawText, args);
293 
294 		} else if ("get".equals(command) //
295 				|| "goTo".equals(command)) {
296 
297 			return new GetLogLine(timeMillis, rawText, args);
298 
299 		} else if ("sendKeys".equals(command) //
300 				|| "type".equals(command)) {
301 
302 			final String locator;
303 			final String value;
304 
305 			if (line.endsWith("'")) {
306 
307 				final int index = args.lastIndexOf("'", args.length() - 2);
308 
309 				locator = args.substring(0, index - 1); // skip " " white space
310 				value = args.substring(index + 1, args.length() - 1);
311 
312 			} else if (line.endsWith(" ***")) {
313 
314 				final int index = args.lastIndexOf(" ", args.length());
315 
316 				locator = args.substring(0, index);
317 				value = args.substring(index + 1);
318 
319 			} else {
320 
321 				throw new NotImplementedException("line: " + line);
322 			}
323 
324 			return new SendKeysLogLine(timeMillis, rawText, LoggedBy.parse(locator), value);
325 
326 		} else if ("clear".equals(command)) {
327 
328 			return new ClearLogLine(timeMillis, rawText, LoggedBy.parse(args));
329 
330 		} else if ("click".equals(command)) {
331 
332 			return new ClickLogLine(timeMillis, rawText, LoggedBy.parse(args));
333 
334 		} else if ("executeScript".equals(command)) {
335 
336 			return new ExecuteScriptLogLine(timeMillis, rawText, args);
337 
338 		} else if ("call".equals(command)) {
339 
340 			return new CallLogLine(timeMillis, rawText, args);
341 
342 		} else if ("setVariable".equals(command)) {
343 
344 			final String name;
345 			final String value;
346 
347 			if (line.endsWith("'")) {
348 
349 				final int index = args.lastIndexOf("'", args.length() - 2);
350 
351 				name = args.substring(0, index - 1); // skip " " white space
352 				value = args.substring(index + 1, args.length() - 1);
353 
354 			} else {
355 
356 				name = substringBefore(args, " ");
357 				value = substringAfter(args, " ");
358 			}
359 
360 			return new SetVariableLogLine(timeMillis, rawText, name, value);
361 
362 		} else if ("setMaskedVariable".equals(command)) {
363 
364 			final String name;
365 			final String value;
366 
367 			if (line.endsWith("'")) {
368 
369 				final int index = args.lastIndexOf("'", args.length() - 2);
370 
371 				name = args.substring(0, index - 1); // skip " " white space
372 				value = args.substring(index + 1, args.length() - 1);
373 
374 			} else {
375 
376 				name = substringBefore(args, " ");
377 				value = substringAfter(args, " ");
378 			}
379 
380 			return new SetMaskedVariableLogLine(timeMillis, rawText, name, value);
381 
382 		} else if ("sleep".equals(command)) {
383 
384 			return new SleepLogLine(timeMillis, rawText, args);
385 
386 		} else if ("waitFor".equals(command)) {
387 
388 			return new WaitForLogLine(timeMillis, rawText, LoggedBy.parse(args));
389 
390 		} else if ("waitForNot".equals(command)) {
391 
392 			return new WaitForNotLogLine(timeMillis, rawText, LoggedBy.parse(args));
393 
394 		} else if ("takeScreenshot".equals(command)) {
395 
396 			return new TakeScreenshotLogLine(timeMillis, rawText, args);
397 
398 		} else if ("failure".equals(command)) {
399 
400 			if (!args.endsWith(" -> FAILURE")) {
401 
402 				throw new NotImplementedException("args: " + args);
403 			}
404 
405 			final int end = args.lastIndexOf(" -> ");
406 
407 			final String message = args.substring(0, end);
408 
409 			return new FailureLogLine(timeMillis, rawText, message);
410 
411 		} else if ("success".equals(command)) {
412 
413 			if (!args.endsWith(" -> SUCCESS")) {
414 
415 				throw new NotImplementedException("args: " + args);
416 			}
417 
418 			final int end = args.lastIndexOf(" -> ");
419 
420 			final String message = args.substring(0, end);
421 
422 			return new SuccessLogLine(timeMillis, rawText, message);
423 
424 		} else if ("message".equals(command)) {
425 
426 			return new MessageLogLine(timeMillis, rawText, args);
427 
428 		} else if ("assertTrue".equals(command)) {
429 
430 			final boolean success;
431 
432 			if (args.endsWith(" -> SUCCESS")) {
433 
434 				success = true;
435 
436 			} else if (args.endsWith(" -> FAILURE")) {
437 
438 				success = false;
439 
440 			} else {
441 
442 				throw new NotImplementedException("args: " + args);
443 			}
444 
445 			final int end = args.lastIndexOf(" -> ");
446 			final int index = args.lastIndexOf(" ", end - 1);
447 
448 			final String locator = args.substring(0, index);
449 
450 			final String attribute = args.substring(index + 1, end);
451 
452 			return new AssertTrueLogLine(timeMillis, rawText, LoggedBy.parse(locator), attribute, success);
453 
454 		} else if ("assertFalse".equals(command)) {
455 
456 			final boolean success;
457 
458 			if (args.endsWith(" -> SUCCESS")) {
459 
460 				success = true;
461 
462 			} else if (args.endsWith(" -> FAILURE")) {
463 
464 				success = false;
465 
466 			} else {
467 
468 				throw new NotImplementedException("args: " + args);
469 			}
470 
471 			final int end = args.lastIndexOf(" -> ");
472 			final int index = args.lastIndexOf(" ", end - 1);
473 
474 			final String locator = args.substring(0, index);
475 
476 			final String attribute = args.substring(index + 1, end);
477 
478 			return new AssertFalseLogLine(timeMillis, rawText, LoggedBy.parse(locator), attribute, success);
479 
480 		} else if ("assertPresent".equals(command)) {
481 
482 			final boolean success;
483 
484 			if (args.endsWith(" -> SUCCESS")) {
485 
486 				success = true;
487 
488 			} else if (args.endsWith(" -> FAILURE")) {
489 
490 				success = false;
491 
492 			} else {
493 
494 				throw new NotImplementedException("args: " + args);
495 			}
496 
497 			final int end = args.lastIndexOf(" -> ");
498 
499 			final String locator = args.substring(0, end);
500 
501 			return new AssertPresentLogLine(timeMillis, rawText, LoggedBy.parse(locator), success);
502 
503 		} else if ("assertAbsent".equals(command)) {
504 
505 			final boolean success;
506 
507 			if (args.endsWith(" -> SUCCESS")) {
508 
509 				success = true;
510 
511 			} else if (args.endsWith(" -> FAILURE")) {
512 
513 				success = false;
514 
515 			} else {
516 
517 				throw new NotImplementedException("args: " + args);
518 			}
519 
520 			final int end = args.lastIndexOf(" -> ");
521 
522 			final String locator = args.substring(0, end);
523 
524 			return new AssertAbsentLogLine(timeMillis, rawText, LoggedBy.parse(locator), success);
525 
526 		} else if ("attribute".equals(command)) {
527 
528 			// e.g. attribute: UPLOAD "yyy" "456"
529 
530 			final String[] tokens = tokenize(args);
531 
532 			return new AttributeLogLine(timeMillis, rawText, AttributeScope.valueOf(tokens[0]), tokens[1], tokens[2]);
533 
534 		} else if ("tag".equals(command)) {
535 
536 			// e.g. tag: STEP "yyy"
537 
538 			final String[] tokens = tokenize(args);
539 
540 			return new TagLogLine(timeMillis, rawText, AttributeScope.valueOf(tokens[0]), tokens[1]);
541 
542 		} else if ("ext".equals(command)) {
543 
544 			final String[] tokens = tokenize(args);
545 
546 			return new ExtLogLine(timeMillis, rawText, tokens[0], tokens[1]);
547 
548 		} else if ("error".equals(command)) {
549 
550 			return new ErrorLogLine(timeMillis, rawText, args);
551 		}
552 
553 		throw new NotImplementedException("line: " + line);
554 	}
555 
556 	public Log getLog() {
557 
558 		return log;
559 	}
560 
561 	private interface MutableLog extends Log {
562 
563 		MutableLog setGuixerVersion(
564 			String guixerVersion
565 		);
566 
567 		MutableLog setDateAsString(
568 			String dateAsString
569 		);
570 
571 		MutableLog setDate(
572 			DateTime date
573 		);
574 
575 		MutableLog setTestClassName(
576 			String testClassName
577 		);
578 
579 		MutableLog setTestClassSimpleName(
580 			String testClassSimpleName
581 		);
582 
583 		MutableLog setTestMethodName(
584 			String testMethodName
585 		);
586 
587 		MutableLog setTimeMillis(
588 			long timeMillis
589 		);
590 
591 		MutableLog setScenario(
592 			String scenario
593 		);
594 
595 		MutableLog setSuccessCount(
596 			int successCount
597 		);
598 
599 		MutableLog setFailureCount(
600 			int failureCount
601 		);
602 
603 		MutableLog addToAttributes(
604 			LogLine logLine
605 		);
606 
607 		MutableLog addToLogLines(
608 			LogLine logLine
609 		);
610 
611 		MutableLog setInError(
612 			boolean inError
613 		);
614 
615 		MutableLog setRawBytes(
616 			byte[] bytes
617 		);
618 	}
619 }