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