Home | History | Annotate | Download | only in testtype
      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 
     17 package com.android.tradefed.testtype;
     18 
     19 import com.android.ddmlib.testrunner.TestIdentifier;
     20 import com.android.tradefed.result.ITestInvocationListener;
     21 import com.android.tradefed.util.CommandResult;
     22 import com.android.tradefed.util.CommandStatus;
     23 import com.android.tradefed.util.IRunUtil;
     24 
     25 import junit.framework.TestCase;
     26 
     27 import org.easymock.EasyMock;
     28 
     29 /** Unit tests for {@link PythonUnitTestRunner}. */
     30 public class PythonUnitTestRunnerTest extends TestCase {
     31 
     32     private static final String[] TEST_PASS_STDERR = {
     33         "b (a) ... ok", "", PythonUnitTestResultParser.LINE, "Ran 1 tests in 1s", "", "OK",
     34     };
     35 
     36     private static final String[] TEST_FAIL_STDERR = {
     37         "b (a) ... ERROR",
     38         "",
     39         PythonUnitTestResultParser.EQLINE,
     40         "ERROR: b (a)",
     41         PythonUnitTestResultParser.LINE,
     42         "Traceback (most recent call last):",
     43         "  File \"test_rangelib.py\", line 129, in test_reallyfail",
     44         "    raise ValueError()",
     45         "ValueError",
     46         "",
     47         PythonUnitTestResultParser.LINE,
     48         "Ran 1 tests in 1s",
     49         "",
     50         "FAILED (errors=1)",
     51     };
     52 
     53     private static final String[] TEST_EXECUTION_FAIL_STDERR = {
     54         "Traceback (most recent call last):",
     55         "  File \"/usr/lib/python2.7/runpy.py\", line 162, in _run_module_as_main",
     56         "    \"__main__\", fname, loader, pkg_name)",
     57         "  File \"/usr/lib/python2.7/runpy.py\", line 72, in _run_code",
     58         "    exec code in run_globals",
     59         "  File \"/usr/lib/python2.7/unittest/__main__.py\", line 12, in <module>",
     60         "    main(module=None)",
     61         "  File \"/usr/lib/python2.7/unittest/main.py\", line 94, in __init__",
     62         "    self.parseArgs(argv)",
     63         "  File \"/usr/lib/python2.7/unittest/main.py\", line 149, in parseArgs",
     64         "    self.createTests()",
     65         "  File \"/usr/lib/python2.7/unittest/main.py\", line 158, in createTests",
     66         "    self.module)",
     67         "  File \"/usr/lib/python2.7/unittest/loader.py\", line 130, in loadTestsFromNames",
     68         "    suites = [self.loadTestsFromName(name, module) for name in names]",
     69         "  File \"/usr/lib/python2.7/unittest/loader.py\", line 91, in loadTestsFromName",
     70         "    module = __import__('.'.join(parts_copy))",
     71         "ImportError: No module named stub",
     72     };
     73 
     74     private enum UnitTestResult {
     75         PASS,
     76         FAIL,
     77         EXECUTION_FAIL,
     78         TIMEOUT;
     79 
     80         private String getStderr() {
     81             switch (this) {
     82                 case PASS:
     83                     return String.join("\n", TEST_PASS_STDERR);
     84                 case FAIL:
     85                     return String.join("\n", TEST_FAIL_STDERR);
     86                 case EXECUTION_FAIL:
     87                     return String.join("\n", TEST_EXECUTION_FAIL_STDERR);
     88                 case TIMEOUT:
     89                     return null;
     90             }
     91             return null;
     92         }
     93 
     94         private CommandStatus getStatus() {
     95             switch (this) {
     96                 case PASS:
     97                     return CommandStatus.SUCCESS;
     98                 case FAIL:
     99                     return CommandStatus.FAILED;
    100                 case EXECUTION_FAIL:
    101                     // UnitTest runner returns with exit code 1 if execution failed.
    102                     return CommandStatus.FAILED;
    103                 case TIMEOUT:
    104                     return CommandStatus.TIMED_OUT;
    105             }
    106             return null;
    107         }
    108 
    109         public CommandResult getCommandResult() {
    110             CommandResult cr = new CommandResult();
    111             cr.setStderr(this.getStderr());
    112             cr.setStatus(this.getStatus());
    113             return cr;
    114         }
    115     }
    116 
    117     private PythonUnitTestRunner mRunner;
    118     private ITestInvocationListener mMockListener;
    119 
    120     @Override
    121     public void setUp() throws Exception {
    122         super.setUp();
    123         mRunner = new PythonUnitTestRunner();
    124         mMockListener = EasyMock.createMock(ITestInvocationListener.class);
    125     }
    126 
    127     public void testCheckPythonVersion_276given270min() {
    128         CommandResult c = new CommandResult();
    129         c.setStderr("Python 2.7.6");
    130         mRunner.checkPythonVersion(c);
    131     }
    132 
    133     public void testCheckPythonVersion_276given331min() {
    134         CommandResult c = new CommandResult();
    135         c.setStderr("Python 2.7.6");
    136         mRunner.setMinPythonVersion("3.3.1");
    137         try {
    138             mRunner.checkPythonVersion(c);
    139             fail("Detected 2.7.6 >= 3.3.1");
    140         } catch (AssertionError e) {
    141             return;
    142         }
    143     }
    144 
    145     public void testCheckPythonVersion_300given276min() {
    146         CommandResult c = new CommandResult();
    147         c.setStderr("Python 3.0.0");
    148         mRunner.setMinPythonVersion("2.7.6");
    149         mRunner.checkPythonVersion(c);
    150     }
    151 
    152     private IRunUtil getMockRunUtil(UnitTestResult testResult) {
    153         CommandResult expectedResult = testResult.getCommandResult();
    154         IRunUtil mockRunUtil = EasyMock.createMock(IRunUtil.class);
    155         // EasyMock checks the number of arguments when verifying method call.
    156         // The actual runTimedCmd() expected here looks like:
    157         // runTimedCmd(300000, null, "-m", "unittest", "-v", "")
    158         EasyMock.expect(
    159                         mockRunUtil.runTimedCmd(
    160                                 EasyMock.anyLong(),
    161                                 (String) EasyMock.anyObject(),
    162                                 (String) EasyMock.anyObject(),
    163                                 (String) EasyMock.anyObject(),
    164                                 (String) EasyMock.anyObject(),
    165                                 (String) EasyMock.anyObject()))
    166                 .andReturn(expectedResult)
    167                 .times(1);
    168         return mockRunUtil;
    169     }
    170 
    171     private void setMockListenerExpectTestPass(boolean testPass) {
    172         mMockListener.testRunStarted((String) EasyMock.anyObject(), EasyMock.anyInt());
    173         EasyMock.expectLastCall().times(1);
    174         mMockListener.testStarted((TestIdentifier) EasyMock.anyObject());
    175         EasyMock.expectLastCall().times(1);
    176         if (!testPass) {
    177             mMockListener.testFailed(
    178                     (TestIdentifier) EasyMock.anyObject(), (String) EasyMock.anyObject());
    179             EasyMock.expectLastCall().times(1);
    180         }
    181         mMockListener.testEnded((TestIdentifier) EasyMock.anyObject(), EasyMock.anyObject());
    182         EasyMock.expectLastCall().times(1);
    183         if (!testPass) {
    184             mMockListener.testRunFailed((String) EasyMock.anyObject());
    185             EasyMock.expectLastCall().times(1);
    186         }
    187         mMockListener.testRunEnded(EasyMock.anyLong(), EasyMock.anyObject());
    188         EasyMock.expectLastCall().times(1);
    189     }
    190 
    191     /** Test execution succeeds and all test cases pass. */
    192     public void testRunPass() {
    193         IRunUtil mockRunUtil = getMockRunUtil(UnitTestResult.PASS);
    194         setMockListenerExpectTestPass(true);
    195         EasyMock.replay(mMockListener, mockRunUtil);
    196         mRunner.doRunTest(mMockListener, mockRunUtil, "");
    197         EasyMock.verify(mMockListener, mockRunUtil);
    198     }
    199 
    200     /** Test execution succeeds and some test cases fail. */
    201     public void testRunFail() {
    202         IRunUtil mockRunUtil = getMockRunUtil(UnitTestResult.FAIL);
    203         setMockListenerExpectTestPass(false);
    204         EasyMock.replay(mMockListener, mockRunUtil);
    205         mRunner.doRunTest(mMockListener, mockRunUtil, "");
    206         EasyMock.verify(mMockListener, mockRunUtil);
    207     }
    208 
    209     /** Test execution fails. */
    210     public void testRunExecutionFail() {
    211         IRunUtil mockRunUtil = getMockRunUtil(UnitTestResult.EXECUTION_FAIL);
    212         EasyMock.replay(mockRunUtil);
    213         try {
    214             mRunner.doRunTest(mMockListener, mockRunUtil, "");
    215             fail("Should not reach here.");
    216         } catch (RuntimeException e) {
    217             assertEquals("Failed to parse python-unittest", e.getMessage());
    218         }
    219         EasyMock.verify(mockRunUtil);
    220     }
    221 
    222     /** Test execution times out. */
    223     public void testRunTimeout() {
    224         IRunUtil mockRunUtil = getMockRunUtil(UnitTestResult.TIMEOUT);
    225         EasyMock.replay(mockRunUtil);
    226         try {
    227             mRunner.doRunTest(mMockListener, mockRunUtil, "");
    228             fail("Should not reach here.");
    229         } catch (RuntimeException e) {
    230             assertTrue(e.getMessage().startsWith("Python unit test timed out after"));
    231         }
    232         EasyMock.verify(mockRunUtil);
    233     }
    234 }