1 #!/usr/bin/env python 2 # 3 # Copyright (C) 2016 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # 17 18 import inspect 19 import logging 20 import os 21 import re 22 import subprocess 23 import sys 24 25 from vts.runners.host import asserts 26 from vts.runners.host import base_test 27 from vts.runners.host import const 28 from vts.runners.host import test_runner 29 from vts.utils.python.controllers import android_device 30 31 32 class CameraITSTest(base_test.BaseTestClass): 33 """Running CameraITS tests in VTS""" 34 35 # TODO: use config file to pass in: 36 # - serial for dut and screen 37 # - camera id 38 # so that we can run other test scenes with ITS-in-a-box 39 def setUpClass(self): 40 """Setup ITS running python environment and check for required python modules 41 """ 42 self.dut = self.registerController(android_device)[0] 43 self.device_arg = "device=%s" % (self.dut.serial) 44 # data_file_path is unicode so convert it to ascii 45 self.its_path = str(os.path.abspath(os.path.join( 46 self.data_file_path, 'CameraITS'))) 47 logging.info("cwd: %s", os.getcwd()) 48 logging.info("its_path: %s", self.its_path) 49 self.out_path = logging.log_path 50 os.environ["CAMERA_ITS_TOP"] = self.its_path 51 # Below module check code assumes tradefed is running python 2.7 52 # If tradefed switches to python3, then we will be checking modules in python3 while ITS 53 # scripts should be ran in 2.7. 54 if sys.version_info[:2] != (2, 7): 55 logging.warning( 56 "Python version %s found; " 57 "CameraITSTest only tested with Python 2.7." % ( 58 str(sys.version_info[:3]))) 59 logging.info("===============================") 60 logging.info("Python path is: %s" % (sys.executable)) 61 logging.info("PYTHONPATH env is: " + os.environ["PYTHONPATH"]) 62 import PIL 63 logging.info("PIL version is " + PIL.__version__) 64 logging.info("PIL path is " + inspect.getfile(PIL)) 65 from PIL import Image 66 logging.info("Image path is " + inspect.getfile(Image)) 67 import numpy 68 logging.info("numpy version is " + numpy.__version__) 69 logging.info("numpy path is " + inspect.getfile(numpy)) 70 import scipy 71 logging.info("scipy version is " + scipy.__version__) 72 logging.info("scipy path is " + inspect.getfile(scipy)) 73 import matplotlib 74 logging.info("matplotlib version is " + matplotlib.__version__) 75 logging.info("matplotlib path is " + inspect.getfile(matplotlib)) 76 from matplotlib import pylab 77 logging.info("pylab path is " + inspect.getfile(pylab)) 78 logging.info("===============================") 79 modules = ["numpy", "PIL", "Image", "matplotlib", "pylab", 80 "scipy.stats", "scipy.spatial"] 81 for m in modules: 82 try: 83 if m == "Image": 84 # Image modules are now imported from PIL 85 exec ("from PIL import Image") 86 elif m == "pylab": 87 exec ("from matplotlib import pylab") 88 else: 89 exec ("import " + m) 90 except ImportError as e: 91 asserts.fail("Cannot import python module %s: %s" % (m, str(e))) 92 93 # Add ITS module path to path 94 its_path = os.path.join(self.its_path, "pymodules") 95 env_python_path = os.environ["PYTHONPATH"] 96 self.pythonpath = env_python_path if its_path in env_python_path else \ 97 "%s:%s" % (its_path, env_python_path) 98 os.environ["PYTHONPATH"] = self.pythonpath 99 logging.info("new PYTHONPATH: %s", self.pythonpath) 100 101 def RunTestcase(self, testpath): 102 """Runs the given testcase and asserts the result. 103 104 Args: 105 testpath: string, format tests/[scenename]/[testname].py 106 """ 107 testname = re.split("/|\.", testpath)[-2] 108 cmd = ['python', os.path.join(self.its_path, testpath), 109 self.device_arg] 110 outdir = self.out_path 111 outpath = os.path.join(outdir, testname + "_stdout.txt") 112 errpath = os.path.join(outdir, testname + "_stderr.txt") 113 logging.info("cwd: %s", os.getcwd()) 114 logging.info("cmd: %s", cmd) 115 logging.info("outpath: %s", outpath) 116 logging.info("errpath: %s", errpath) 117 with open(outpath, "w") as fout, open(errpath, "w") as ferr: 118 retcode = subprocess.call( 119 cmd, stderr=ferr, stdout=fout, cwd=outdir) 120 if retcode != 0 and retcode != 101: 121 # Dump all logs to host log if the test failed 122 with open(outpath, "r") as fout, open(errpath, "r") as ferr: 123 logging.info(fout.read()) 124 logging.error(ferr.read()) 125 126 asserts.assertTrue(retcode == 0 or retcode == 101, 127 "ITS %s retcode %d" % (testname, retcode)) 128 129 def FetchTestPaths(self, scene): 130 """Returns a list of test paths for a given test scene. 131 132 Args: 133 scnee: one of ITS test scene name. 134 """ 135 its_path = self.its_path 136 paths = [os.path.join("tests", scene, s) 137 for s in os.listdir(os.path.join(its_path, "tests", scene)) 138 if s[-3:] == ".py" and s[:4] == "test"] 139 paths.sort() 140 return paths 141 142 def generateScene0Test(self): 143 testpaths = self.FetchTestPaths("scene0") 144 self.runGeneratedTests( 145 test_func=self.RunTestcase, 146 settings=testpaths, 147 name_func=lambda path: "%s_%s" % (re.split("/|\.", path)[-3], re.split("/|\.", path)[-2])) 148 149 150 if __name__ == "__main__": 151 test_runner.main() 152