diff --git a/tools/test_pictures.py b/tools/test_pictures.py index b2397c4dda..7ccb3b8731 100644 --- a/tools/test_pictures.py +++ b/tools/test_pictures.py @@ -1,13 +1,15 @@ ''' -Compares the rendererings of serialized SkPictures to expected images. - -Launch with --help to see more information. - - Copyright 2012 Google Inc. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +Compares the rendererings of serialized SkPictures to expected images. + +Launch with --help to see more information. + +TODO(epoger): Combine with overlapping tools/tests/render_pictures_test.py . +See https://code.google.com/p/skia/issues/detail?id=1943#c2 ''' # common Python modules import os diff --git a/tools/test_rendering.py b/tools/test_rendering.py index 35e6d94f4b..31e848b3c3 100644 --- a/tools/test_rendering.py +++ b/tools/test_rendering.py @@ -1,10 +1,13 @@ ''' -Compares the rendererings of serialized SkPictures to expected result. - Copyright 2012 Google Inc. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +Compares the rendererings of serialized SkPictures to expected result. + +TODO(epoger): Combine with overlapping tools/tests/render_pictures_test.py . +See https://code.google.com/p/skia/issues/detail?id=1943#c2 ''' # common Python modules import os diff --git a/tools/tests/base_unittest.py b/tools/tests/base_unittest.py new file mode 100755 index 0000000000..096039915b --- /dev/null +++ b/tools/tests/base_unittest.py @@ -0,0 +1,85 @@ +#!/usr/bin/python + +""" +Copyright 2014 Google Inc. + +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. + +A wrapper around the standard Python unittest library, adding features we need +for various unittests within this directory. +""" + +import os +import subprocess +import unittest + + +class TestCase(unittest.TestCase): + + def shortDescription(self): + """Tell unittest framework to not print docstrings for test cases.""" + return None + + def run_command(self, args): + """Runs a program from the command line and returns stdout. + + Args: + args: Command line to run, as a list of string parameters. args[0] is the + binary to run. + + Returns: + stdout from the program, as a single string. + + Raises: + Exception: the program exited with a nonzero return code. + """ + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (stdout, stderr) = proc.communicate() + if proc.returncode is not 0: + raise Exception('command "%s" failed: %s' % (args, stderr)) + return stdout + + def find_path_to_program(self, program): + """Returns path to an existing program binary. + + Args: + program: Basename of the program to find (e.g., 'render_pictures'). + + Returns: + Absolute path to the program binary, as a string. + + Raises: + Exception: unable to find the program binary. + """ + trunk_path = os.path.abspath(os.path.join(os.path.dirname(__file__), + os.pardir, os.pardir)) + possible_paths = [os.path.join(trunk_path, 'out', 'Release', program), + os.path.join(trunk_path, 'out', 'Debug', program), + os.path.join(trunk_path, 'out', 'Release', + program + '.exe'), + os.path.join(trunk_path, 'out', 'Debug', + program + '.exe')] + for try_path in possible_paths: + if os.path.isfile(try_path): + return try_path + raise Exception('cannot find %s in paths %s; maybe you need to ' + 'build %s?' % (program, possible_paths, program)) + + +def main(test_case_class): + """Run the unit tests within the given class. + + Raises an Exception if any of those tests fail (in case we are running in the + context of run_all.py, which depends on that Exception to signal failures). + + TODO(epoger): Make all of our unit tests use the Python unittest framework, + so we can leverage its ability to run *all* the tests and report failures at + the end. + """ + suite = unittest.TestLoader().loadTestsFromTestCase(test_case_class) + results = unittest.TextTestRunner(verbosity=2).run(suite) + if not results.wasSuccessful(): + raise Exception('failed unittest %s' % test_case_class) diff --git a/tools/tests/render_pictures_test.py b/tools/tests/render_pictures_test.py new file mode 100755 index 0000000000..ea14b608d3 --- /dev/null +++ b/tools/tests/render_pictures_test.py @@ -0,0 +1,131 @@ +#!/usr/bin/python + +""" +Copyright 2014 Google Inc. + +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. + +Test the render_pictures binary. + +TODO(epoger): Combine with overlapping tools/test_rendering.py and +tools/test_pictures.py . +See https://code.google.com/p/skia/issues/detail?id=1943#c2 +""" + +# System-level imports +import json +import os +import shutil +import tempfile + +# Imports from within Skia +import base_unittest + + +class RenderPicturesTest(base_unittest.TestCase): + + def setUp(self): + self._temp_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self._temp_dir) + + def test_tiled_whole_image_no_comparison(self): + """Run render_pictures with tiles and --writeWholeImage flag.""" + input_skp_path = os.path.join(self._temp_dir, 'input.skp') + output_json_path = os.path.join(self._temp_dir, 'output.json') + self._run_skpmaker(['--writePath', input_skp_path]) + self._run_render_pictures(['-r', input_skp_path, + '--bbh', 'grid', '256', '256', + '--mode', 'tile', '256', '256', + '--writeJsonSummaryPath', output_json_path, + '--writeWholeImage']) + expected_summary_dict = { + "actual-results" : { + "no-comparison" : { + "input.png" : [ "bitmap-64bitMD5", 12793741875005523433 ] + } + } + } + self._assert_json_contents(output_json_path, expected_summary_dict) + + def test_tiled_no_comparison(self): + """Generate individual tiles. + + TODO(epoger): The results of this test are currently broken! + The summary should contain a list of tiles, but for some reason, it is + empty.""" + input_skp_path = os.path.join(self._temp_dir, 'input.skp') + output_json_path = os.path.join(self._temp_dir, 'output.json') + self._run_skpmaker(['--writePath', input_skp_path]) + self._run_render_pictures(['-r', input_skp_path, + '--bbh', 'grid', '256', '256', + '--mode', 'tile', '256', '256', + '--writeJsonSummaryPath', output_json_path]) + expected_summary_dict = { + "actual-results" : { + "no-comparison" : None + } + } + self._assert_json_contents(output_json_path, expected_summary_dict) + + def test_untiled_no_comparison(self): + """Run without tiles. + + TODO(epoger): The results of this test are currently broken! + The summary should contain a single image, but for some reason, it is + empty.""" + input_skp_path = os.path.join(self._temp_dir, 'input.skp') + output_json_path = os.path.join(self._temp_dir, 'output.json') + self._run_skpmaker(['--writePath', input_skp_path]) + self._run_render_pictures(['-r', input_skp_path, + '--writeJsonSummaryPath', output_json_path]) + expected_summary_dict = { + "actual-results" : { + "no-comparison" : None + } + } + self._assert_json_contents(output_json_path, expected_summary_dict) + + def _run_render_pictures(self, args): + binary = self.find_path_to_program('render_pictures') + return self.run_command([binary, + '--clone', '1', + '--config', '8888', + '--validate' + ] + args) + + def _run_skpmaker(self, args): + binary = self.find_path_to_program('skpmaker') + return self.run_command([binary, + '--red', '255', + '--green', '0', + '--blue', '0', + '--width', '640', + '--height', '400', + ] + args) + + def _assert_json_contents(self, json_path, expected_dict): + """Asserts that contents of a JSON file are identical to expected_dict. + + Args: + json_path: Path to a JSON file. + expected_dict: Dictionary indicating the expected contents of the JSON + file. + + Raises: + AssertionError: contents of the JSON file are not identical to + expected_dict. + """ + file_contents = open(json_path, 'r').read() + actual_dict = json.loads(file_contents) + self.assertEqual(actual_dict, expected_dict) + + +def main(): + base_unittest.main(RenderPicturesTest) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/run_all.py b/tools/tests/run_all.py index 6d8b44ea31..84886f758f 100755 --- a/tools/tests/run_all.py +++ b/tools/tests/run_all.py @@ -10,10 +10,12 @@ Run all self-tests that were written in Python, raising an exception if any of them fail. """ +import render_pictures_test import skimage_self_test def main(): """Run all self-tests, raising an exception if any of them fail.""" + render_pictures_test.main() skimage_self_test.main() if __name__ == '__main__':