1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package compiler.compilercontrol.share.processors; 25 26 import compiler.compilercontrol.share.method.MethodDescriptor; 27 import compiler.compilercontrol.share.method.MethodGenerator; 28 import compiler.compilercontrol.share.pool.PoolHelper; 29 import compiler.compilercontrol.share.scenario.State; 30 import jdk.test.lib.Asserts; 31 import jdk.test.lib.process.OutputAnalyzer; 32 33 import java.io.File; 34 import java.io.FileNotFoundException; 35 import java.lang.reflect.Executable; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Scanner; 39 import java.util.function.Consumer; 40 import java.util.regex.Matcher; 41 import java.util.regex.Pattern; 42 import java.util.stream.Collectors; 43 44 /** 45 * Log compilation file processor 46 */ 47 public class LogProcessor implements Consumer<OutputAnalyzer> { 48 public static final String LOG_FILE = "compilation.log"; 49 private static final String TASK_ELEMENT = "<task [^>]*>"; 50 private static final String TASK_DONE_ELEMENT = "<task_done [^>]*>"; 51 private static final String TASK_END_ELEMENT = "</task>"; 52 private static final String ANY_ELEMENT = "<[^>]*>"; 53 private static final Pattern METHOD_PATTERN = Pattern.compile( 54 "method='([^']+)'"); 55 private final List<String> loggedMethods; 56 private final List<String> testMethods; 57 LogProcessor(Map<Executable, State> states)58 public LogProcessor(Map<Executable, State> states) { 59 loggedMethods = states.keySet().stream() 60 .filter(x -> states.get(x).isLog()) 61 .map(MethodGenerator::commandDescriptor) 62 .map(MethodDescriptor::getString) 63 .collect(Collectors.toList()); 64 testMethods = new PoolHelper().getAllMethods() 65 .stream() 66 .map(pair -> pair.first) 67 .map(MethodGenerator::commandDescriptor) 68 .map(MethodDescriptor::getString) 69 .collect(Collectors.toList()); 70 } 71 72 @Override accept(OutputAnalyzer outputAnalyzer)73 public void accept(OutputAnalyzer outputAnalyzer) { 74 if (loggedMethods.isEmpty()) { 75 return; 76 } 77 matchTasks(); 78 } 79 80 /* 81 * Gets scanner for log file of the test case 82 */ getScanner()83 private Scanner getScanner() { 84 File logFile = new File(LOG_FILE); 85 Scanner scanner; 86 try { 87 scanner = new Scanner(logFile); 88 } catch (FileNotFoundException e) { 89 throw new Error("TESTBUG: file not found: " + logFile, e); 90 } 91 return scanner; 92 } 93 94 /* 95 * Parses for <task method='java.lang.String indexOf (I)I' > 96 * and finds if there is a compilation log for this task 97 */ matchTasks()98 private void matchTasks() { 99 try (Scanner scanner = getScanner()) { 100 String task = scanner.findWithinHorizon(TASK_ELEMENT, 0); 101 while (task != null) { 102 String element = scanner.findWithinHorizon(ANY_ELEMENT, 0); 103 if (Pattern.matches(TASK_DONE_ELEMENT, element) 104 || Pattern.matches(TASK_END_ELEMENT, element)) { 105 /* If there is nothing between <task> and </task> 106 except <task done /> then compilation log is empty. 107 Check the method in this task should not be logged */ 108 Asserts.assertFalse(matchMethod(task), "Compilation log " 109 + "expected. Met: " + element); 110 } 111 task = scanner.findWithinHorizon(TASK_ELEMENT, 0); 112 } 113 } 114 } 115 116 // Check that input method should be logged matchMethod(String input)117 private boolean matchMethod(String input) { 118 Matcher matcher = METHOD_PATTERN.matcher(input); 119 Asserts.assertTrue(matcher.find(), "Wrong matcher or input"); 120 // Get method and normalize it 121 String method = normalize(matcher.group(1)); 122 if (loggedMethods.contains(method)) { 123 return true; 124 } 125 if (!testMethods.contains(method)) { 126 return false; 127 } 128 return false; 129 } 130 131 // Normalize given signature to conform regular expression used in tests normalize(String method)132 private String normalize(String method) { 133 return method.replaceAll("\\.", "/") // replace dots in a class string 134 .replaceFirst(" ", ".") // replace space between class and method 135 .replaceFirst(" ", "") // remove space between method and signature 136 .replace("<", "<") 137 .replace(">", ">"); 138 } 139 } 140