15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2010 Google Inc. All rights reserved.
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions are
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# met:
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     * Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     * Redistributions in binary form must reproduce the above
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# copyright notice, this list of conditions and the following disclaimer
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# in the documentation and/or other materials provided with the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     * Neither the name of Google Inc. nor the names of its
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# contributors may be used to endorse or promote products derived from
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# this software without specific prior written permission.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochimport webkitpy.thirdparty.unittest2 as unittest
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import json
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import optparse
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import random
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from webkitpy.common.host_mock import MockHost
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from webkitpy.layout_tests.layout_package import json_results_generator
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from webkitpy.layout_tests.models import test_expectations
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from webkitpy.layout_tests.port import test
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)from webkitpy.thirdparty.mock import Mock
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class JSONGeneratorTest(unittest.TestCase):
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def setUp(self):
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.builder_name = 'DUMMY_BUILDER_NAME'
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.build_name = 'DUMMY_BUILD_NAME'
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.build_number = 'DUMMY_BUILDER_NUMBER'
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # For archived results.
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._json = None
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._num_runs = 0
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._tests_set = set([])
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_timings = {}
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._failed_count_map = {}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._PASS_count = 0
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._DISABLED_count = 0
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._FLAKY_count = 0
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._FAILS_count = 0
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._fixable_count = 0
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def test_strip_json_wrapper(self):
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        json = "['contents']"
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.assertEqual(json_results_generator.strip_json_wrapper(json_results_generator._JSON_PREFIX + json + json_results_generator._JSON_SUFFIX), json)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.assertEqual(json_results_generator.strip_json_wrapper(json), json)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _test_json_generation(self, passed_tests_list, failed_tests_list):
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        tests_set = set(passed_tests_list) | set(failed_tests_list)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        DISABLED_tests = set([t for t in tests_set
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                             if t.startswith('DISABLED_')])
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FLAKY_tests = set([t for t in tests_set
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                           if t.startswith('FLAKY_')])
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FAILS_tests = set([t for t in tests_set
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                           if t.startswith('FAILS_')])
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        PASS_tests = tests_set - (DISABLED_tests | FLAKY_tests | FAILS_tests)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        failed_tests = set(failed_tests_list) - DISABLED_tests
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        failed_count_map = dict([(t, 1) for t in failed_tests])
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        test_timings = {}
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        i = 0
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for test in tests_set:
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            test_timings[test] = float(self._num_runs * 100 + i)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            i += 1
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        test_results_map = dict()
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for test in tests_set:
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            test_results_map[test] = json_results_generator.TestResult(test,
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                failed=(test in failed_tests),
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                elapsed_time=test_timings[test])
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        host = MockHost()
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        port = Mock()
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        port._filesystem = host.filesystem
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        generator = json_results_generator.JSONResultsGeneratorBase(port,
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            self.builder_name, self.build_name, self.build_number,
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            '',
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            None,   # don't fetch past json results archive
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            test_results_map)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        failed_count_map = dict([(t, 1) for t in failed_tests])
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # Test incremental json results
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        incremental_json = generator.get_json()
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._verify_json_results(
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            tests_set,
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            test_timings,
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            failed_count_map,
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            len(PASS_tests),
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            len(DISABLED_tests),
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            len(FLAKY_tests),
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            len(DISABLED_tests | failed_tests),
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            incremental_json,
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            1)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # We don't verify the results here, but at least we make sure the code runs without errors.
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        generator.generate_json_output()
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        generator.generate_times_ms_file()
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _verify_json_results(self, tests_set, test_timings, failed_count_map,
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                             PASS_count, DISABLED_count, FLAKY_count,
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                             fixable_count,
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                             json, num_runs):
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # Aliasing to a short name for better access to its constants.
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        JRG = json_results_generator.JSONResultsGeneratorBase
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        self.assertIn(JRG.VERSION_KEY, json)
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        self.assertIn(self.builder_name, json)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        buildinfo = json[self.builder_name]
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        self.assertIn(JRG.FIXABLE, buildinfo)
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        self.assertIn(JRG.TESTS, buildinfo)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.assertEqual(len(buildinfo[JRG.BUILD_NUMBERS]), num_runs)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.assertEqual(buildinfo[JRG.BUILD_NUMBERS][0], self.build_number)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if tests_set or DISABLED_count:
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fixable = {}
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for fixable_items in buildinfo[JRG.FIXABLE]:
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (type, count) in fixable_items.iteritems():
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if type in fixable:
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        fixable[type] = fixable[type] + count
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    else:
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        fixable[type] = count
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if PASS_count:
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertEqual(fixable[JRG.PASS_RESULT], PASS_count)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else:
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertTrue(JRG.PASS_RESULT not in fixable or
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                fixable[JRG.PASS_RESULT] == 0)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if DISABLED_count:
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertEqual(fixable[JRG.SKIP_RESULT], DISABLED_count)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else:
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertTrue(JRG.SKIP_RESULT not in fixable or
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                fixable[JRG.SKIP_RESULT] == 0)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if FLAKY_count:
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertEqual(fixable[JRG.FLAKY_RESULT], FLAKY_count)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else:
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertTrue(JRG.FLAKY_RESULT not in fixable or
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                fixable[JRG.FLAKY_RESULT] == 0)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if failed_count_map:
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            tests = buildinfo[JRG.TESTS]
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for test_name in failed_count_map.iterkeys():
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                test = self._find_test_in_trie(test_name, tests)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                failed = 0
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for result in test[JRG.RESULTS]:
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if result[1] == JRG.FAIL_RESULT:
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        failed += result[0]
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertEqual(failed_count_map[test_name], failed)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                timing_count = 0
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for timings in test[JRG.TIMES]:
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if timings[1] == test_timings[test_name]:
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        timing_count = timings[0]
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self.assertEqual(1, timing_count)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if fixable_count:
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            self.assertEqual(sum(buildinfo[JRG.FIXABLE_COUNT]), fixable_count)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _find_test_in_trie(self, path, trie):
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nodes = path.split("/")
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sub_trie = trie
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for node in nodes:
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            self.assertIn(node, sub_trie)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sub_trie = sub_trie[node]
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return sub_trie
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def test_json_generation(self):
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation([], [])
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(['A1', 'B1'], [])
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation([], ['FAILS_A2', 'FAILS_B2'])
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(['DISABLED_A3', 'DISABLED_B3'], [])
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(['A4'], ['B4', 'FAILS_C4'])
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(['DISABLED_C5', 'DISABLED_D5'], ['A5', 'B5'])
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['A6', 'B6', 'FAILS_C6', 'DISABLED_E6', 'DISABLED_F6'],
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['FAILS_D6'])
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # Generate JSON with the same test sets. (Both incremental results and
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # archived results must be updated appropriately.)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['A', 'FLAKY_B', 'DISABLED_C'],
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['FAILS_D', 'FLAKY_E'])
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['A', 'DISABLED_C', 'FLAKY_E'],
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['FLAKY_B', 'FAILS_D'])
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['FLAKY_B', 'DISABLED_C', 'FAILS_D'],
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ['A', 'FLAKY_E'])
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def test_hierarchical_json_generation(self):
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # FIXME: Re-work tests to be more comprehensible and comprehensive.
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._test_json_generation(['foo/A'], ['foo/B', 'bar/C'])
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def test_test_timings_trie(self):
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        test_port = test.TestPort(MockHost())
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        individual_test_timings = []
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        individual_test_timings.append(json_results_generator.TestResult('foo/bar/baz.html', elapsed_time=1.2))
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        individual_test_timings.append(json_results_generator.TestResult('bar.html', elapsed_time=0.0001))
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        trie = json_results_generator.test_timings_trie(test_port, individual_test_timings)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        expected_trie = {
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          'bar.html': 0,
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          'foo': {
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              'bar': {
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                  'baz.html': 1200,
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              }
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          }
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self.assertEqual(json.dumps(trie), json.dumps(expected_trie))
232