# Copyright (C) 2010 Google Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. try: import jsonresults from jsonresults import JsonResults except ImportError: print "ERROR: Add the TestResultServer, google_appengine and yaml/lib directories to your PYTHONPATH" import unittest JSON_RESULTS_TEMPLATE = ( '{"Webkit":{' '"allFixableCount":[[TESTDATA_COUNT]],' '"buildNumbers":[[TESTDATA_BUILDNUMBERS]],' '"chromeRevision":[[TESTDATA_CHROMEREVISION]],' '"deferredCounts":[[TESTDATA_COUNTS]],' '"fixableCount":[[TESTDATA_COUNT]],' '"fixableCounts":[[TESTDATA_COUNTS]],' '"secondsSinceEpoch":[[TESTDATA_TIMES]],' '"tests":{[TESTDATA_TESTS]},' '"webkitRevision":[[TESTDATA_WEBKITREVISION]],' '"wontfixCounts":[[TESTDATA_COUNTS]]' '},' '"version":3' '}') JSON_RESULTS_COUNTS_TEMPLATE = ( '{' '"C":[TESTDATA],' '"F":[TESTDATA],' '"I":[TESTDATA],' '"O":[TESTDATA],' '"P":[TESTDATA],' '"T":[TESTDATA],' '"X":[TESTDATA],' '"Z":[TESTDATA]}') JSON_RESULTS_TESTS_TEMPLATE = ( '"[TESTDATA_TEST_NAME]":{' '"results":[[TESTDATA_TEST_RESULTS]],' '"times":[[TESTDATA_TEST_TIMES]]}') JSON_RESULTS_PREFIX = "ADD_RESULTS(" JSON_RESULTS_SUFFIX = ");" JSON_RESULTS_TEST_LIST_TEMPLATE = ( '{"Webkit":{"tests":{[TESTDATA_TESTS]}}}') class JsonResultsTest(unittest.TestCase): def setUp(self): self._builder = "Webkit" def _make_test_json(self, test_data): if not test_data: return JSON_RESULTS_PREFIX + JSON_RESULTS_SUFFIX (builds, tests) = test_data if not builds or not tests: return JSON_RESULTS_PREFIX + JSON_RESULTS_SUFFIX json = JSON_RESULTS_TEMPLATE counts = [] build_numbers = [] webkit_revision = [] chrome_revision = [] times = [] for build in builds: counts.append(JSON_RESULTS_COUNTS_TEMPLATE.replace("[TESTDATA]", build)) build_numbers.append("1000%s" % build) webkit_revision.append("2000%s" % build) chrome_revision.append("3000%s" % build) times.append("100000%s000" % build) json = json.replace("[TESTDATA_COUNTS]", ",".join(counts)) json = json.replace("[TESTDATA_COUNT]", ",".join(builds)) json = json.replace("[TESTDATA_BUILDNUMBERS]", ",".join(build_numbers)) json = json.replace("[TESTDATA_WEBKITREVISION]", ",".join(webkit_revision)) json = json.replace("[TESTDATA_CHROMEREVISION]", ",".join(chrome_revision)) json = json.replace("[TESTDATA_TIMES]", ",".join(times)) json_tests = [] for test in tests: t = JSON_RESULTS_TESTS_TEMPLATE.replace("[TESTDATA_TEST_NAME]", test[0]) t = t.replace("[TESTDATA_TEST_RESULTS]", test[1]) t = t.replace("[TESTDATA_TEST_TIMES]", test[2]) json_tests.append(t) json = json.replace("[TESTDATA_TESTS]", ",".join(json_tests)) return JSON_RESULTS_PREFIX + json + JSON_RESULTS_SUFFIX def _test_merge(self, aggregated_data, incremental_data, expected_data, max_builds=jsonresults.JSON_RESULTS_MAX_BUILDS): aggregated_results = self._make_test_json(aggregated_data) incremental_results = self._make_test_json(incremental_data) merged_results = JsonResults.merge(self._builder, aggregated_results, incremental_results, max_builds, sort_keys=True) if expected_data: expected_results = self._make_test_json(expected_data) self.assertEquals(merged_results, expected_results) else: self.assertFalse(merged_results) def _test_get_test_list(self, input_data, expected_data): input_results = self._make_test_json(input_data) json_tests = [] for test in expected_data: json_tests.append("\"" + test + "\":{}") expected_results = JSON_RESULTS_PREFIX + \ JSON_RESULTS_TEST_LIST_TEMPLATE.replace( "[TESTDATA_TESTS]", ",".join(json_tests)) + \ JSON_RESULTS_SUFFIX actual_results = JsonResults.get_test_list(self._builder, input_results) self.assertEquals(actual_results, expected_results) def test(self): # Empty incremental results json. # Nothing to merge. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results None, # Expect no merge happens. None) # No actual incremental test results (only prefix and suffix) to merge. # Nothing to merge. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results ([], []), # Expected no merge happens. None) # No existing aggregated results. # Merged results == new incremental results. self._test_merge( # Aggregated results None, # Incremental results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Expected results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]])) # Single test for single run. # Incremental results has the latest build and same test results for # that run. # Insert the incremental results at the first place and sum number # of runs for "P" (200 + 1) to get merged results. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results (["3"], [["001.html", "[1,\"F\"]", "[1,0]"]]), # Expected results (["3", "2", "1"], [["001.html", "[201,\"F\"]", "[201,0]"]])) # Single test for single run. # Incremental results has the latest build but different test results # for that run. # Insert the incremental results at the first place. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results (["3"], [["001.html", "[1, \"I\"]", "[1,1]"]]), # Expected results (["3", "2", "1"], [["001.html", "[1,\"I\"],[200,\"F\"]", "[1,1],[200,0]"]])) # Single test for single run. # Incremental results has the latest build but different test results # for that run. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"],[10,\"I\"]", "[200,0],[10,1]"]]), # Incremental results (["3"], [["001.html", "[1,\"I\"]", "[1,1]"]]), # Expected results (["3", "2", "1"], [["001.html", "[1,\"I\"],[200,\"F\"],[10,\"I\"]", "[1,1],[200,0],[10,1]"]])) # Multiple tests for single run. # All tests have incremental updates. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"], ["002.html", "[100,\"I\"]", "[100,1]"]]), # Incremental results (["3"], [["001.html", "[1,\"F\"]", "[1,0]"], ["002.html", "[1,\"I\"]", "[1,1]"]]), # Expected results (["3", "2", "1"], [["001.html", "[201,\"F\"]", "[201,0]"], ["002.html", "[101,\"I\"]", "[101,1]"]])) # Multiple tests for single run. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"], ["002.html", "[100,\"I\"]", "[100,1]"]]), # Incremental results (["3"], [["002.html", "[1,\"I\"]", "[1,1]"]]), # Expected results (["3", "2", "1"], [["001.html", "[1,\"N\"],[200,\"F\"]", "[201,0]"], ["002.html", "[101,\"I\"]", "[101,1]"]])) # Single test for multiple runs. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results (["4", "3"], [["001.html", "[2, \"I\"]", "[2,2]"]]), # Expected results (["4", "3", "2", "1"], [["001.html", "[2,\"I\"],[200,\"F\"]", "[2,2],[200,0]"]])) # Multiple tests for multiple runs. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"], ["002.html", "[10,\"Z\"]", "[10,0]"]]), # Incremental results (["4", "3"], [["001.html", "[2, \"I\"]", "[2,2]"], ["002.html", "[1,\"C\"]", "[1,1]"]]), # Expected results (["4", "3", "2", "1"], [["001.html", "[2,\"I\"],[200,\"F\"]", "[2,2],[200,0]"], ["002.html", "[1,\"C\"],[10,\"Z\"]", "[1,1],[10,0]"]])) # Test the build in incremental results is older than the most recent # build in aggregated results. # The incremental results should be dropped and no merge happens. self._test_merge( # Aggregated results (["3", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results (["2"], [["001.html", "[1, \"F\"]", "[1,0]"]]), # Expected no merge happens. None) # Test the build in incremental results is same as the build in # aggregated results. # The incremental results should be dropped and no merge happens. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"F\"]", "[200,0]"]]), # Incremental results (["3", "2"], [["001.html", "[2, \"F\"]", "[2,0]"]]), # Expected no merge happens. None) # Remove test where there is no data in all runs. self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"N\"]", "[200,0]"], ["002.html", "[10,\"F\"]", "[10,0]"]]), # Incremental results (["3"], [["001.html", "[1,\"N\"]", "[1,0]"], ["002.html", "[1,\"P\"]", "[1,0]"]]), # Expected results (["3", "2", "1"], [["002.html", "[1,\"P\"],[10,\"F\"]", "[11,0]"]])) # Remove test where all run pass and max running time < 1 seconds self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"P\"]", "[200,0]"], ["002.html", "[10,\"F\"]", "[10,0]"]]), # Incremental results (["3"], [["001.html", "[1,\"P\"]", "[1,0]"], ["002.html", "[1,\"P\"]", "[1,0]"]]), # Expected results (["3", "2", "1"], [["002.html", "[1,\"P\"],[10,\"F\"]", "[11,0]"]])) # Do not remove test where all run pass but max running time >= 1 seconds self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[200,\"P\"]", "[200,0]"], ["002.html", "[10,\"F\"]", "[10,0]"]]), # Incremental results (["3"], [["001.html", "[1,\"P\"]", "[1,1]"], ["002.html", "[1,\"P\"]", "[1,0]"]]), # Expected results (["3", "2", "1"], [["001.html", "[201,\"P\"]", "[1,1],[200,0]"], ["002.html", "[1,\"P\"],[10,\"F\"]", "[11,0]"]])) # Remove items from test results and times that exceed the max number # of builds to track. max_builds = str(jsonresults.JSON_RESULTS_MAX_BUILDS) self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[" + max_builds + ",\"F\"],[1,\"I\"]", "[" + max_builds + ",0],[1,1]"]]), # Incremental results (["3"], [["001.html", "[1,\"T\"]", "[1,1]"]]), # Expected results (["3", "2", "1"], [["001.html", "[1,\"T\"],[" + max_builds + ",\"F\"]", "[1,1],[" + max_builds + ",0]"]])) # Remove items from test results and times that exceed the max number # of builds to track, using smaller threshold. max_builds = str(jsonresults.JSON_RESULTS_MAX_BUILDS_SMALL) self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[" + max_builds + ",\"F\"],[1,\"I\"]", "[" + max_builds + ",0],[1,1]"]]), # Incremental results (["3"], [["001.html", "[1,\"T\"]", "[1,1]"]]), # Expected results (["3", "2", "1"], [["001.html", "[1,\"T\"],[" + max_builds + ",\"F\"]", "[1,1],[" + max_builds + ",0]"]]), int(max_builds)) # Test that merging in a new result of the same type as the last result # causes old results to fall off. max_builds = str(jsonresults.JSON_RESULTS_MAX_BUILDS_SMALL) self._test_merge( # Aggregated results (["2", "1"], [["001.html", "[" + max_builds + ",\"F\"],[1,\"N\"]", "[" + max_builds + ",0],[1,1]"]]), # Incremental results (["3"], [["001.html", "[1,\"F\"]", "[1,0]"]]), # Expected results (["3", "2", "1"], [["001.html", "[" + max_builds + ",\"F\"]", "[" + max_builds + ",0]"]]), int(max_builds)) # Get test name list only. Don't include non-test-list data and # of test result details. self._test_get_test_list( # Input results (["3", "2", "1"], [["001.html", "[200,\"P\"]", "[200,0]"], ["002.html", "[10,\"F\"]", "[10,0]"]]), # Expected results ["001.html", "002.html"]) if __name__ == '__main__': unittest.main()