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.testtype; 17 18 import com.android.ddmlib.MultiLineReceiver; 19 import com.android.ddmlib.testrunner.ITestRunListener; 20 import com.android.ddmlib.testrunner.TestIdentifier; 21 import com.android.tradefed.log.LogUtil.CLog; 22 23 import java.util.ArrayList; 24 import java.util.Collections; 25 import java.util.List; 26 import java.util.Map; 27 import java.util.regex.Matcher; 28 import java.util.regex.Pattern; 29 /** 30 * A result parser for gtest dry run mode with "--gtest_list_tests" parameter. 31 * 32 */ 33 public class GTestListTestParser extends MultiLineReceiver { 34 35 private String mLastTestClassName = null; 36 private String mTestRunName = null; 37 private ITestRunListener mTestRunListener = null; 38 /** Whether or not to prepend filename to classname. */ 39 private boolean mPrependFileName = false; 40 41 // test class name should start without leading spaces, and end with a "." 42 // example: <line start>RecordingCanvas.<line end> 43 private static final Pattern TEST_CLASS = Pattern.compile("^([a-zA-Z]+.*)\\.$"); 44 // test method name should start with leading spaces, named as however valid as a C function 45 // example: <line start> emptyPlayback<line end> 46 private static final Pattern TEST_METHOD = Pattern.compile("\\s+(\\w+)$"); 47 48 // exposed for unit testing 49 protected List<TestIdentifier> mTests = new ArrayList<>(); 50 51 /** 52 * Creates the GTestListTestParser for a single listener. 53 * 54 * @param testRunName the test run name to provide to 55 * {@link ITestRunListener#testRunStarted(String, int)} 56 * @param listener informed of test results as the tests are executing 57 */ 58 public GTestListTestParser(String testRunName, ITestRunListener listener) { 59 mTestRunName = testRunName; 60 mTestRunListener = listener; 61 // don't trim, since we need the leading whitespace 62 setTrimLine(false); 63 } 64 65 /** 66 * {@inheritDoc} 67 */ 68 @Override 69 public boolean isCancelled() { 70 return false; 71 } 72 73 /** 74 * {@inheritDoc} 75 */ 76 @Override 77 public void processNewLines(String[] lines) { 78 for (String line : lines) { 79 parse(line); 80 } 81 } 82 83 private String getTestClass(String name) { 84 if (mPrependFileName) { 85 StringBuilder sb = new StringBuilder(); 86 sb.append(mTestRunName); 87 sb.append("."); 88 sb.append(name); 89 return sb.toString(); 90 } 91 return name; 92 } 93 94 private void parse(String line) { 95 Matcher classMatcher = TEST_CLASS.matcher(line); 96 Matcher methodMatcher = TEST_METHOD.matcher(line); 97 if (classMatcher.matches()) { 98 // New test class name found 99 mLastTestClassName = classMatcher.group(1); 100 } else if (methodMatcher.matches()) { 101 if (mLastTestClassName == null) { 102 throw new IllegalStateException(String.format( 103 "parsed new test case name %s but no test class name has been set", line)); 104 } 105 // Test method name found 106 mTests.add(new TestIdentifier( 107 getTestClass(mLastTestClassName), methodMatcher.group(1))); 108 } else { 109 CLog.v("line ignored: %s", line); 110 } 111 } 112 113 public void setPrependFileName(boolean prepend) { 114 mPrependFileName = prepend; 115 } 116 117 public boolean getPrependFileName() { 118 return mPrependFileName; 119 } 120 121 /** 122 * {@inheritDoc} 123 */ 124 @Override 125 public void done() { 126 // now we send out all the test callbacks 127 final Map<String, String> empty = Collections.<String, String>emptyMap(); 128 mTestRunListener.testRunStarted(mTestRunName, mTests.size()); 129 for (TestIdentifier id : mTests) { 130 mTestRunListener.testStarted(id); 131 mTestRunListener.testEnded(id, empty); 132 } 133 mTestRunListener.testRunEnded(0, empty); 134 super.done(); 135 } 136 } 137