Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 1 | # Copyright 2014 The Android Open Source Project |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
| 14 | |
| 15 | import os |
| 16 | import os.path |
| 17 | import tempfile |
| 18 | import subprocess |
| 19 | import time |
| 20 | import sys |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 21 | import textwrap |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 22 | import its.device |
| 23 | |
| 24 | def main(): |
| 25 | """Run all the automated tests, saving intermediate files, and producing |
| 26 | a summary/report of the results. |
| 27 | |
| 28 | Script should be run from the top-level CameraITS directory. |
| 29 | """ |
| 30 | |
Chien-Yu Chen | bad96ca | 2014-10-20 17:30:56 -0700 | [diff] [blame] | 31 | SKIP_RET_CODE = 101 |
| 32 | |
Yin-Chia Yeh | 665dda4 | 2014-10-20 11:23:48 -0700 | [diff] [blame] | 33 | # Not yet mandated tests |
| 34 | NOT_YET_MANDATED = { |
| 35 | "scene0":[ |
| 36 | "test_jitter" |
| 37 | ], |
| 38 | "scene1":[ |
| 39 | "test_ae_precapture_trigger", |
Yin-Chia Yeh | 665dda4 | 2014-10-20 11:23:48 -0700 | [diff] [blame] | 40 | "test_crop_region_raw", |
Zhijun He | 6137f21 | 2014-11-20 13:47:11 -0800 | [diff] [blame] | 41 | "test_ev_compensation_advanced", |
| 42 | "test_ev_compensation_basic", |
Yin-Chia Yeh | 3b1763a | 2014-10-22 10:59:13 -0700 | [diff] [blame] | 43 | "test_yuv_plus_jpeg" |
Yin-Chia Yeh | 0e0276f | 2015-06-03 15:27:06 -0700 | [diff] [blame] | 44 | ], |
Chien-Yu Chen | f07d5c2 | 2015-07-09 15:37:33 -0700 | [diff] [blame^] | 45 | "scene2":[], |
Chien-Yu Chen | 3267860 | 2015-06-25 15:10:52 -0700 | [diff] [blame] | 46 | "scene3":[] |
Yin-Chia Yeh | 665dda4 | 2014-10-20 11:23:48 -0700 | [diff] [blame] | 47 | } |
| 48 | |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 49 | # Get all the scene0 and scene1 tests, which can be run using the same |
| 50 | # physical setup. |
Chien-Yu Chen | 3267860 | 2015-06-25 15:10:52 -0700 | [diff] [blame] | 51 | scenes = ["scene0", "scene1", "scene2", "scene3"] |
Yin-Chia Yeh | 0e0276f | 2015-06-03 15:27:06 -0700 | [diff] [blame] | 52 | scene_req = { |
| 53 | "scene0" : None, |
| 54 | "scene1" : "A grey card covering at least the middle 30% of the scene", |
Chien-Yu Chen | f07d5c2 | 2015-07-09 15:37:33 -0700 | [diff] [blame^] | 55 | "scene2" : "A picture containing human faces", |
Chien-Yu Chen | 3267860 | 2015-06-25 15:10:52 -0700 | [diff] [blame] | 56 | "scene3" : "A chart containing sharp edges like ISO 12233" |
Yin-Chia Yeh | 0e0276f | 2015-06-03 15:27:06 -0700 | [diff] [blame] | 57 | } |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 58 | tests = [] |
| 59 | for d in scenes: |
| 60 | tests += [(d,s[:-3],os.path.join("tests", d, s)) |
| 61 | for s in os.listdir(os.path.join("tests",d)) |
| 62 | if s[-3:] == ".py"] |
| 63 | tests.sort() |
| 64 | |
| 65 | # Make output directories to hold the generated files. |
| 66 | topdir = tempfile.mkdtemp() |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 67 | print "Saving output files to:", topdir, "\n" |
| 68 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 69 | camera_ids = [] |
Yin-Chia Yeh | a2277d0 | 2014-10-20 15:50:23 -0700 | [diff] [blame] | 70 | for s in sys.argv[1:]: |
| 71 | if s[:7] == "camera=" and len(s) > 7: |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 72 | camera_ids.append(s[7:]) |
Yin-Chia Yeh | a2277d0 | 2014-10-20 15:50:23 -0700 | [diff] [blame] | 73 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 74 | # user doesn't specify camera id, run through all cameras |
| 75 | if not camera_ids: |
| 76 | camera_ids_path = os.path.join(topdir, "camera_ids.txt") |
| 77 | out_arg = "out=" + camera_ids_path |
| 78 | cmd = ['python', |
| 79 | os.path.join(os.getcwd(),"tools/get_camera_ids.py"), out_arg] |
| 80 | retcode = subprocess.call(cmd,cwd=topdir) |
| 81 | assert(retcode == 0) |
| 82 | with open(camera_ids_path, "r") as f: |
| 83 | for line in f: |
| 84 | camera_ids.append(line.replace('\n', '')) |
Yin-Chia Yeh | 665dda4 | 2014-10-20 11:23:48 -0700 | [diff] [blame] | 85 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 86 | print "Running ITS on the following cameras:", camera_ids |
| 87 | |
| 88 | for camera_id in camera_ids: |
| 89 | # Loop capturing images until user confirm test scene is correct |
| 90 | camera_id_arg = "camera=" + camera_id |
| 91 | print "Preparing to run ITS on camera", camera_id |
| 92 | |
| 93 | os.mkdir(os.path.join(topdir, camera_id)) |
| 94 | for d in scenes: |
| 95 | os.mkdir(os.path.join(topdir, camera_id, d)) |
| 96 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 97 | print "Start running ITS on camera: ", camera_id |
| 98 | # Run each test, capturing stdout and stderr. |
| 99 | summary = "ITS test result summary for camera " + camera_id + "\n" |
| 100 | numpass = 0 |
| 101 | numskip = 0 |
| 102 | numnotmandatedfail = 0 |
| 103 | numfail = 0 |
| 104 | |
Yin-Chia Yeh | 0e0276f | 2015-06-03 15:27:06 -0700 | [diff] [blame] | 105 | prev_scene = "" |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 106 | for (scene,testname,testpath) in tests: |
Yin-Chia Yeh | 0e0276f | 2015-06-03 15:27:06 -0700 | [diff] [blame] | 107 | if scene != prev_scene and scene_req[scene] != None: |
| 108 | out_path = os.path.join(topdir, camera_id, scene+".jpg") |
| 109 | out_arg = "out=" + out_path |
| 110 | scene_arg = "scene=" + scene_req[scene] |
| 111 | cmd = ['python', |
| 112 | os.path.join(os.getcwd(),"tools/validate_scene.py"), |
| 113 | camera_id_arg, out_arg, scene_arg] |
| 114 | retcode = subprocess.call(cmd,cwd=topdir) |
| 115 | assert(retcode == 0) |
| 116 | print "Start running tests for", scene |
| 117 | prev_scene = scene |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 118 | cmd = ['python', os.path.join(os.getcwd(),testpath)] + \ |
| 119 | sys.argv[1:] + [camera_id_arg] |
| 120 | outdir = os.path.join(topdir,camera_id,scene) |
| 121 | outpath = os.path.join(outdir,testname+"_stdout.txt") |
| 122 | errpath = os.path.join(outdir,testname+"_stderr.txt") |
| 123 | t0 = time.time() |
| 124 | with open(outpath,"w") as fout, open(errpath,"w") as ferr: |
| 125 | retcode = subprocess.call(cmd,stderr=ferr,stdout=fout,cwd=outdir) |
| 126 | t1 = time.time() |
| 127 | |
| 128 | if retcode == 0: |
| 129 | retstr = "PASS " |
| 130 | numpass += 1 |
| 131 | elif retcode == SKIP_RET_CODE: |
| 132 | retstr = "SKIP " |
| 133 | numskip += 1 |
| 134 | elif retcode != 0 and testname in NOT_YET_MANDATED[scene]: |
| 135 | retstr = "FAIL*" |
| 136 | numnotmandatedfail += 1 |
| 137 | else: |
| 138 | retstr = "FAIL " |
| 139 | numfail += 1 |
| 140 | |
| 141 | msg = "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0) |
| 142 | print msg |
| 143 | summary += msg + "\n" |
| 144 | if retcode != 0 and retcode != SKIP_RET_CODE: |
| 145 | # Dump the stderr if the test fails |
| 146 | with open (errpath, "r") as error_file: |
| 147 | errors = error_file.read() |
| 148 | summary += errors + "\n" |
| 149 | |
| 150 | if numskip > 0: |
| 151 | skipstr = ", %d test%s skipped" % (numskip, "s" if numskip > 1 else "") |
Chien-Yu Chen | bad96ca | 2014-10-20 17:30:56 -0700 | [diff] [blame] | 152 | else: |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 153 | skipstr = "" |
Yin-Chia Yeh | 665dda4 | 2014-10-20 11:23:48 -0700 | [diff] [blame] | 154 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 155 | test_result = "\n%d / %d tests passed (%.1f%%)%s" % ( |
| 156 | numpass + numnotmandatedfail, len(tests) - numskip, |
| 157 | 100.0 * float(numpass + numnotmandatedfail) / (len(tests) - numskip) |
| 158 | if len(tests) != numskip else 100.0, |
| 159 | skipstr) |
| 160 | print test_result |
| 161 | summary += test_result + "\n" |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 162 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 163 | if numnotmandatedfail > 0: |
| 164 | msg = "(*) tests are not yet mandated" |
| 165 | print msg |
| 166 | summary += msg + "\n" |
Chien-Yu Chen | bad96ca | 2014-10-20 17:30:56 -0700 | [diff] [blame] | 167 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 168 | result = numfail == 0 |
| 169 | print "Reporting ITS result to CtsVerifier" |
| 170 | summary_path = os.path.join(topdir, camera_id, "summary.txt") |
| 171 | with open(summary_path, "w") as f: |
| 172 | f.write(summary) |
| 173 | its.device.report_result(camera_id, result, summary_path) |
Chien-Yu Chen | bad96ca | 2014-10-20 17:30:56 -0700 | [diff] [blame] | 174 | |
Yin-Chia Yeh | ab98ada | 2015-03-05 13:28:53 -0800 | [diff] [blame] | 175 | print "ITS tests finished. Please go back to CtsVerifier and proceed" |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 176 | |
| 177 | if __name__ == '__main__': |
| 178 | main() |