blob: cbf48a7d642ba02e0dc9e7b23cba8c95c29f88bc [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import optparse
import os
import sys
import unittest
from blinkpy.common import path_finder
from blinkpy.common.host_mock import MockHost
from blinkpy.web_tests.controllers import web_test_finder
from blinkpy.web_tests.models import test_expectations
import mock
class WebTestFinderTests(unittest.TestCase):
def test_skip_tests_expectations(self):
"""Tests that tests are skipped based on to expectations and options."""
host = MockHost()
port = host.port_factory.get('test-win-win7', None)
all_tests = [
'fast/css/passes.html',
'fast/css/fails.html',
'fast/css/times_out.html',
'fast/css/skip.html',
]
# Patch port.tests() to return our tests
port.tests = lambda paths: paths or all_tests
options = optparse.Values({
'no_expectations': False,
'enable_sanitizer': False,
'skipped': 'default',
'skip_timeouts': False,
'skip_failing_tests': False,
})
finder = web_test_finder.WebTestFinder(port, options)
expectations = test_expectations.TestExpectations(port)
expectations.merge_raw_expectations(
('# results: [ Failure Timeout Skip ]'
'\nfast/css/fails.html [ Failure ]'
'\nfast/css/times_out.html [ Timeout ]'
'\nfast/css/skip.html [ Skip ]'))
# When run with default settings, we only skip the tests marked Skip.
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(tests, set(['fast/css/skip.html']))
# Specify test on the command line; by default should not skip.
tests = finder.skip_tests(['fast/css/skip.html'], all_tests,
expectations)
self.assertEqual(tests, set())
# Specify test on the command line, but always skip.
finder._options.skipped = 'always'
tests = finder.skip_tests(['fast/css/skip.html'], all_tests,
expectations)
self.assertEqual(tests, set(['fast/css/skip.html']))
finder._options.skipped = 'default'
# Only run skip tests, aka skip all non-skipped tests.
finder._options.skipped = 'only'
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(
tests,
set([
'fast/css/passes.html', 'fast/css/fails.html',
'fast/css/times_out.html'
]))
finder._options.skipped = 'default'
# Ignore any skip entries, aka never skip anything.
finder._options.skipped = 'ignore'
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(tests, set())
finder._options.skipped = 'default'
# Skip tests that are marked TIMEOUT.
finder._options.skip_timeouts = True
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(
tests, set(['fast/css/times_out.html', 'fast/css/skip.html']))
finder._options.skip_timeouts = False
# Skip tests that are marked FAILURE
finder._options.skip_failing_tests = True
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(tests,
set(['fast/css/fails.html', 'fast/css/skip.html']))
finder._options.skip_failing_tests = False
# Disable expectations entirely; nothing should be skipped by default.
finder._options.no_expectations = True
tests = finder.skip_tests([], all_tests, None)
self.assertEqual(tests, set())
def test_skip_tests_idlharness(self):
"""Tests that idlharness tests are skipped on MSAN/ASAN runs.
See https://crbug.com/856601
"""
host = MockHost()
port = host.port_factory.get('test-win-win7', None)
non_idlharness_test = 'external/wpt/dir1/dir2/foo.html'
idlharness_test_1 = 'external/wpt/dir1/dir2/idlharness.any.html'
idlharness_test_2 = 'external/wpt/dir1/dir2/idlharness.any.worker.html'
all_tests = [
non_idlharness_test,
idlharness_test_1,
idlharness_test_2,
]
# Patch port.tests() to return our tests
port.tests = lambda paths: paths or all_tests
options = optparse.Values({
'no_expectations': False,
'enable_sanitizer': False,
'skipped': 'default',
'skip_timeouts': False,
'skip_failing_tests': False,
})
finder = web_test_finder.WebTestFinder(port, options)
# Default case; not MSAN/ASAN so should not skip anything.
expectations = test_expectations.TestExpectations(port)
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(tests, set())
for test in all_tests:
self.assertTrue(
expectations.get_expectations(test).is_default_pass)
# MSAN/ASAN, with no paths specified explicitly, so should skip both
# idlharness tests.
expectations = test_expectations.TestExpectations(port)
finder._options.enable_sanitizer = True
tests = finder.skip_tests([], all_tests, expectations)
self.assertEqual(tests, set([idlharness_test_1, idlharness_test_2]))
self.assertTrue(
expectations.get_expectations(non_idlharness_test).is_default_pass)
self.assertEquals(
expectations.get_expectations(idlharness_test_1).results, {'SKIP'})
self.assertEquals(
expectations.get_expectations(idlharness_test_2).results, {'SKIP'})
# Disable expectations entirely; we should still skip the idlharness
# tests but shouldn't touch the expectations parameter.
finder._options.no_expectations = True
tests = finder.skip_tests([], all_tests, None)
self.assertEqual(tests, set([idlharness_test_1, idlharness_test_2]))
# MSAN/ASAN, with one of the tests specified explicitly (and
# --skipped=default), so should skip only the unspecified test.
expectations = test_expectations.TestExpectations(port)
tests = finder.skip_tests([idlharness_test_1], all_tests, expectations)
self.assertEqual(tests, set([idlharness_test_2]))
# Although we will run the test because it was specified explicitly, it
# is still *expected* to Skip. This is consistent with how entries in
# TestExpectations work.
self.assertTrue(
expectations.get_expectations(non_idlharness_test).is_default_pass)
self.assertEquals(
expectations.get_expectations(idlharness_test_1).results, {'SKIP'})
self.assertEquals(
expectations.get_expectations(idlharness_test_2).results, {'SKIP'})
def test_find_fastest_tests(self):
host = MockHost()
port = host.port_factory.get('test-win-win7', None)
all_tests = [
'path/test.html',
'new/test.html',
'fast/css/1.html',
'fast/css/2.html',
'fast/css/3.html',
'fast/css/skip1.html',
'fast/css/skip2.html',
'fast/css/skip3.html',
'fast/css/skip4.html',
'fast/css/skip5.html',
]
port.tests = lambda paths: paths or all_tests
finder = web_test_finder.WebTestFinder(port, {})
finder._times_trie = lambda: {
'fast': {
'css': {
'1.html': 1,
'2.html': 2,
'3.html': 3,
'skip1.html': 0,
'skip2.html': 0,
'skip3.html': 0,
'skip4.html': 0,
'skip5.html': 0,
}
},
'path': {
'test.html': 4,
}
}
tests = finder.find_tests(fastest_percentile=50, args=[])
self.assertEqual(
set(tests[1]),
set(['fast/css/1.html', 'fast/css/2.html', 'new/test.html']))
tests = finder.find_tests(
fastest_percentile=50, args=['path/test.html'])
self.assertEqual(
set(tests[1]),
set([
'fast/css/1.html', 'fast/css/2.html', 'path/test.html',
'new/test.html'
]))
tests = finder.find_tests(args=[])
self.assertEqual(tests[1], all_tests)
tests = finder.find_tests(args=['path/test.html'])
self.assertEqual(tests[1], ['path/test.html'])
def test_find_fastest_tests_excludes_deleted_tests(self):
host = MockHost()
port = host.port_factory.get('test-win-win7', None)
all_tests = [
'fast/css/1.html',
'fast/css/2.html',
]
port.tests = lambda paths: paths or all_tests
finder = web_test_finder.WebTestFinder(port, {})
finder._times_trie = lambda: {
'fast': {
'css': {
'1.html': 1,
'2.html': 2,
'non-existant.html': 1,
}
},
}
tests = finder.find_tests(fastest_percentile=90, args=[])
self.assertEqual(set(tests[1]), set(['fast/css/1.html']))
def test_split_chunks(self):
split = web_test_finder.WebTestFinder._split_into_chunks # pylint: disable=protected-access
with mock.patch('__builtin__.hash', int):
tests = [1, 2, 3, 4]
self.assertEqual([1, 2, 3, 4], split(tests, 0, 1))
self.assertEqual([2, 4], split(tests, 0, 2))
self.assertEqual([1, 3], split(tests, 1, 2))
self.assertEqual([3], split(tests, 0, 3))
self.assertEqual([1, 4], split(tests, 1, 3))
self.assertEqual([2], split(tests, 2, 3))
tests = [1, 2, 3, 4, 5]
self.assertEqual([1, 2, 3, 4, 5], split(tests, 0, 1))
self.assertEqual([2, 4], split(tests, 0, 2))
self.assertEqual([1, 3, 5], split(tests, 1, 2))
self.assertEqual([3], split(tests, 0, 3))
self.assertEqual([1, 4], split(tests, 1, 3))
self.assertEqual([2, 5], split(tests, 2, 3))
tests = [1, 2, 3, 4, 5, 6]
self.assertEqual([1, 2, 3, 4, 5, 6], split(tests, 0, 1))
self.assertEqual([2, 4, 6], split(tests, 0, 2))
self.assertEqual([1, 3, 5], split(tests, 1, 2))
self.assertEqual([3, 6], split(tests, 0, 3))
self.assertEqual([1, 4], split(tests, 1, 3))
self.assertEqual([2, 5], split(tests, 2, 3))
class FilterTestsTests(unittest.TestCase):
simple_test_list = ['a/a1.html', 'a/a2.html', 'b/b1.html']
def check(self, tests, filters, expected_tests):
self.assertEqual(expected_tests,
web_test_finder.filter_tests(tests, filters))
def test_no_filters(self):
self.check(self.simple_test_list, [], self.simple_test_list)
def test_empty_glob_is_rejected(self):
self.assertRaises(ValueError, self.check, self.simple_test_list,
[['']], [])
self.assertRaises(ValueError, self.check, self.simple_test_list,
[['-']], [])
def test_one_all_positive_filter(self):
self.check(self.simple_test_list, [['a*']], ['a/a1.html', 'a/a2.html'])
self.check(self.simple_test_list, [['a*', 'b*']],
self.simple_test_list)
def test_one_all_negative_filter(self):
self.check(self.simple_test_list, [['-c*']], self.simple_test_list)
def test_one_mixed_filter(self):
self.check(self.simple_test_list, [['a*', '-c*']],
['a/a1.html', 'a/a2.html'])
def test_two_all_positive_filters(self):
self.check(self.simple_test_list, [['a*'], ['b*']], [])
def test_two_all_negative_filters(self):
self.check(self.simple_test_list, [['-a*'], ['-b*']], [])
self.check(self.simple_test_list, [['-a*'], ['-c*']], ['b/b1.html'])
def test_two_mixed_filters(self):
self.check(self.simple_test_list, [['a*'], ['-b*']],
['a/a1.html', 'a/a2.html'])
def test_longest_glob_wins(self):
# These test that if two matching globs are specified as
# part of the same filter expression, the longest matching
# glob wins (takes precedence). The order of the two globs
# must not matter.
self.check(self.simple_test_list, [['a/a*', '-a/a2*']], ['a/a1.html'])
self.check(self.simple_test_list, [['-a/a*', 'a/a2*']], ['a/a2.html'])
# In this test, the positive and negative globs are in
# separate filter expressions, so a2 should be filtered out
# and nothing should run (tests should only be run if they
# would be run by every filter individually).
self.check(self.simple_test_list, [['-a/a*'], ['a/a2*']], [])
def test_only_trailing_globs_work(self):
self.check(self.simple_test_list, [['a*']], ['a/a1.html', 'a/a2.html'])
# These test that if you have a glob that contains a "*" that isn't
# at the end, it is rejected; only globs at the end should work.
self.assertRaises(ValueError, self.check, self.simple_test_list,
[['*1.html']], [])
self.assertRaises(ValueError, self.check, self.simple_test_list,
[['a*.html']], [])