Commit efac3d1c authored by Quinten Yearsley's avatar Quinten Yearsley Committed by Commit Bot

Remove auto-rebaseline and the NeedsRebaseline keyword.

Bug: 692811
Change-Id: Ic1a061020c1dc502655646c7a6e3ae80aee14535
Reviewed-on: https://chromium-review.googlesource.com/564681Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Commit-Queue: Quinten Yearsley <qyearsley@chromium.org>
Cr-Commit-Position: refs/heads/master@{#485453}
parent 5946acdc
...@@ -285,7 +285,6 @@ class Manager(object): ...@@ -285,7 +285,6 @@ class Manager(object):
def _test_is_expected_missing(self, test_file): def _test_is_expected_missing(self, test_file):
expectations = self._expectations.model().get_expectations(test_file) expectations = self._expectations.model().get_expectations(test_file)
return (test_expectations.MISSING in expectations or return (test_expectations.MISSING in expectations or
test_expectations.NEEDS_REBASELINE in expectations or
test_expectations.NEEDS_MANUAL_REBASELINE in expectations) test_expectations.NEEDS_MANUAL_REBASELINE in expectations)
def _test_is_slow(self, test_file): def _test_is_slow(self, test_file):
......
...@@ -118,12 +118,7 @@ class LintTest(unittest.TestCase): ...@@ -118,12 +118,7 @@ class LintTest(unittest.TestCase):
logger, handler = lint_test_expectations.set_up_logging(logging_stream) logger, handler = lint_test_expectations.set_up_logging(logging_stream)
try: try:
res = lint_test_expectations.lint(host, options) res = lint_test_expectations.lint(host, options)
self.assertEqual( self.assertEqual(res, [])
res,
['/test.checkout/LayoutTests/TestExpectations: '
'/test.checkout/LayoutTests/TestExpectations:5 '
'NeedsRebaseline is deprecated; see https://crbug.com/692811 '
'failures/expected/needsrebaseline.html'])
finally: finally:
lint_test_expectations.tear_down_logging(logger, handler) lint_test_expectations.tear_down_logging(logger, handler)
......
...@@ -44,7 +44,7 @@ _log = logging.getLogger(__name__) ...@@ -44,7 +44,7 @@ _log = logging.getLogger(__name__)
# FIXME: range() starts with 0 which makes if expectation checks harder # FIXME: range() starts with 0 which makes if expectation checks harder
# as PASS is 0. # as PASS is 0.
(PASS, FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, TIMEOUT, CRASH, LEAK, SKIP, WONTFIX, (PASS, FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, TIMEOUT, CRASH, LEAK, SKIP, WONTFIX,
SLOW, REBASELINE, NEEDS_REBASELINE, NEEDS_MANUAL_REBASELINE, MISSING, FLAKY, NOW, NONE) = range(19) SLOW, REBASELINE, NEEDS_REBASELINE_UNUSED, NEEDS_MANUAL_REBASELINE, MISSING, FLAKY, NOW, NONE) = range(19)
# FIXME: Perhaps these two routines should be part of the Port instead? # FIXME: Perhaps these two routines should be part of the Port instead?
BASELINE_SUFFIX_LIST = ('png', 'wav', 'txt') BASELINE_SUFFIX_LIST = ('png', 'wav', 'txt')
...@@ -56,7 +56,6 @@ V8_BUG_PREFIX = 'code.google.com/p/v8/issues/detail?id=' ...@@ -56,7 +56,6 @@ V8_BUG_PREFIX = 'code.google.com/p/v8/issues/detail?id='
NAMED_BUG_PREFIX = 'Bug(' NAMED_BUG_PREFIX = 'Bug('
MISSING_KEYWORD = 'Missing' MISSING_KEYWORD = 'Missing'
NEEDS_REBASELINE_KEYWORD = 'NeedsRebaseline'
NEEDS_MANUAL_REBASELINE_KEYWORD = 'NeedsManualRebaseline' NEEDS_MANUAL_REBASELINE_KEYWORD = 'NeedsManualRebaseline'
...@@ -79,7 +78,6 @@ class TestExpectationParser(object): ...@@ -79,7 +78,6 @@ class TestExpectationParser(object):
# FIXME: Rename these to *_KEYWORD as in MISSING_KEYWORD above, but make # FIXME: Rename these to *_KEYWORD as in MISSING_KEYWORD above, but make
# the case studdly-caps to match the actual file contents. # the case studdly-caps to match the actual file contents.
REBASELINE_MODIFIER = 'rebaseline' REBASELINE_MODIFIER = 'rebaseline'
NEEDS_REBASELINE_MODIFIER = 'needsrebaseline'
NEEDS_MANUAL_REBASELINE_MODIFIER = 'needsmanualrebaseline' NEEDS_MANUAL_REBASELINE_MODIFIER = 'needsmanualrebaseline'
PASS_EXPECTATION = 'pass' PASS_EXPECTATION = 'pass'
SKIP_MODIFIER = 'skip' SKIP_MODIFIER = 'skip'
...@@ -170,20 +168,16 @@ class TestExpectationParser(object): ...@@ -170,20 +168,16 @@ class TestExpectationParser(object):
if self.REBASELINE_MODIFIER in expectations: if self.REBASELINE_MODIFIER in expectations:
expectation_line.warnings.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.') expectation_line.warnings.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.')
if self.NEEDS_REBASELINE_MODIFIER in expectations: if self.NEEDS_MANUAL_REBASELINE_MODIFIER in expectations:
expectation_line.warnings.append('NeedsRebaseline is deprecated; see https://crbug.com/692811')
if self.NEEDS_REBASELINE_MODIFIER in expectations or self.NEEDS_MANUAL_REBASELINE_MODIFIER in expectations:
for test in expectation_line.matching_tests: for test in expectation_line.matching_tests:
if self._port.reference_files(test): if self._port.reference_files(test):
text_expected_filename = self._port.expected_filename(test, '.txt') text_expected_filename = self._port.expected_filename(test, '.txt')
if not self._port.host.filesystem.exists(text_expected_filename): if not self._port.host.filesystem.exists(text_expected_filename):
expectation_line.warnings.append( expectation_line.warnings.append(
'A reftest without text expectation cannot be marked as NeedsRebaseline/NeedsManualRebaseline') 'A reftest without text expectation cannot be marked as NeedsManualRebaseline')
specifiers = [specifier.lower() for specifier in expectation_line.specifiers] specifiers = [specifier.lower() for specifier in expectation_line.specifiers]
if (self.REBASELINE_MODIFIER in expectations or self.NEEDS_REBASELINE_MODIFIER in expectations) and ( if self.REBASELINE_MODIFIER in expectations and ('debug' in specifiers or 'release' in specifiers):
'debug' in specifiers or 'release' in specifiers):
expectation_line.warnings.append('A test cannot be rebaselined for Debug/Release.') expectation_line.warnings.append('A test cannot be rebaselined for Debug/Release.')
def _parse_expectations(self, expectation_line): def _parse_expectations(self, expectation_line):
...@@ -303,7 +297,6 @@ class TestExpectationLine(object): ...@@ -303,7 +297,6 @@ class TestExpectationLine(object):
MISSING_KEYWORD: 'MISSING', MISSING_KEYWORD: 'MISSING',
'Pass': 'PASS', 'Pass': 'PASS',
'Rebaseline': 'REBASELINE', 'Rebaseline': 'REBASELINE',
NEEDS_REBASELINE_KEYWORD: 'NEEDSREBASELINE',
NEEDS_MANUAL_REBASELINE_KEYWORD: 'NEEDSMANUALREBASELINE', NEEDS_MANUAL_REBASELINE_KEYWORD: 'NEEDSMANUALREBASELINE',
'Skip': 'SKIP', 'Skip': 'SKIP',
'Slow': 'SLOW', 'Slow': 'SLOW',
...@@ -445,8 +438,8 @@ class TestExpectationLine(object): ...@@ -445,8 +438,8 @@ class TestExpectationLine(object):
if 'MISSING' in expectations: if 'MISSING' in expectations:
warnings.append( warnings.append(
'"Missing" expectations are not allowed; either download new baselines ' '"Missing" expectations are not allowed; download new baselines '
'(see https://goo.gl/SHVYrZ) or use "NeedsRebaseline" expectations.') '(see https://goo.gl/SHVYrZ), or as a fallback, use "NeedsManualRebaseline".')
expectation_line.bugs = bugs expectation_line.bugs = bugs
expectation_line.specifiers = specifiers expectation_line.specifiers = specifiers
...@@ -885,7 +878,6 @@ class TestExpectations(object): ...@@ -885,7 +878,6 @@ class TestExpectations(object):
'leak': LEAK, 'leak': LEAK,
'missing': MISSING, 'missing': MISSING,
TestExpectationParser.SKIP_MODIFIER: SKIP, TestExpectationParser.SKIP_MODIFIER: SKIP,
TestExpectationParser.NEEDS_REBASELINE_MODIFIER: NEEDS_REBASELINE,
TestExpectationParser.NEEDS_MANUAL_REBASELINE_MODIFIER: NEEDS_MANUAL_REBASELINE, TestExpectationParser.NEEDS_MANUAL_REBASELINE_MODIFIER: NEEDS_MANUAL_REBASELINE,
TestExpectationParser.WONTFIX_MODIFIER: WONTFIX, TestExpectationParser.WONTFIX_MODIFIER: WONTFIX,
TestExpectationParser.SLOW_MODIFIER: SLOW, TestExpectationParser.SLOW_MODIFIER: SLOW,
...@@ -943,10 +935,9 @@ class TestExpectations(object): ...@@ -943,10 +935,9 @@ class TestExpectations(object):
if result in expected_results: if result in expected_results:
return True return True
if result in (PASS, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, MISSING) and ( if result in (PASS, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, MISSING) and NEEDS_MANUAL_REBASELINE in expected_results:
NEEDS_REBASELINE in expected_results or NEEDS_MANUAL_REBASELINE in expected_results):
return True return True
if result in (TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO) and (FAIL in expected_results): if result in (TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO) and FAIL in expected_results:
return True return True
if result == MISSING and test_needs_rebaselining: if result == MISSING and test_needs_rebaselining:
return True return True
...@@ -1060,9 +1051,6 @@ class TestExpectations(object): ...@@ -1060,9 +1051,6 @@ class TestExpectations(object):
def expectations(self): def expectations(self):
return self._expectations return self._expectations
def get_needs_rebaseline_failures(self):
return self._model.get_test_set(NEEDS_REBASELINE)
def get_rebaselining_failures(self): def get_rebaselining_failures(self):
return self._model.get_test_set(REBASELINE) return self._model.get_test_set(REBASELINE)
......
...@@ -35,7 +35,7 @@ from webkitpy.layout_tests.models.test_configuration import TestConfiguration, T ...@@ -35,7 +35,7 @@ from webkitpy.layout_tests.models.test_configuration import TestConfiguration, T
from webkitpy.layout_tests.models.test_expectations import ( from webkitpy.layout_tests.models.test_expectations import (
TestExpectationLine, TestExpectations, ParseError, TestExpectationParser, TestExpectationLine, TestExpectations, ParseError, TestExpectationParser,
PASS, FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, PASS, FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO,
TIMEOUT, CRASH, LEAK, SKIP, WONTFIX, NEEDS_REBASELINE, MISSING TIMEOUT, CRASH, LEAK, SKIP, WONTFIX, NEEDS_MANUAL_REBASELINE, MISSING
) )
...@@ -53,13 +53,10 @@ class Base(unittest.TestCase): ...@@ -53,13 +53,10 @@ class Base(unittest.TestCase):
return ['failures/expected/text.html', return ['failures/expected/text.html',
'failures/expected/image_checksum.html', 'failures/expected/image_checksum.html',
'failures/expected/crash.html', 'failures/expected/crash.html',
'failures/expected/needsrebaseline.html',
'failures/expected/needsmanualrebaseline.html', 'failures/expected/needsmanualrebaseline.html',
'failures/expected/image.html', 'failures/expected/image.html',
'failures/expected/timeout.html', 'failures/expected/timeout.html',
'passes/text.html', 'passes/text.html',
'reftests/failures/expected/needsrebaseline.html',
'reftests/failures/expected/needsrebaseline_with_txt.html',
'reftests/failures/expected/needsmanualrebaseline.html', 'reftests/failures/expected/needsmanualrebaseline.html',
'reftests/failures/expected/needsmanualrebaseline_with_txt.html', 'reftests/failures/expected/needsmanualrebaseline_with_txt.html',
'reftests/failures/expected/has_unused_expectation.html'] 'reftests/failures/expected/has_unused_expectation.html']
...@@ -68,7 +65,6 @@ class Base(unittest.TestCase): ...@@ -68,7 +65,6 @@ class Base(unittest.TestCase):
return """ return """
Bug(test) failures/expected/text.html [ Failure ] Bug(test) failures/expected/text.html [ Failure ]
Bug(test) failures/expected/crash.html [ Crash ] Bug(test) failures/expected/crash.html [ Crash ]
Bug(test) failures/expected/needsrebaseline.html [ NeedsRebaseline ]
Bug(test) failures/expected/needsmanualrebaseline.html [ NeedsManualRebaseline ] Bug(test) failures/expected/needsmanualrebaseline.html [ NeedsManualRebaseline ]
Bug(test) failures/expected/image_checksum.html [ Crash ] Bug(test) failures/expected/image_checksum.html [ Crash ]
Bug(test) failures/expected/image.html [ Crash Mac ] Bug(test) failures/expected/image.html [ Crash Mac ]
...@@ -139,16 +135,24 @@ class MiscTests(Base): ...@@ -139,16 +135,24 @@ class MiscTests(Base):
self.assertEqual(TestExpectations.result_was_expected(MISSING, set([PASS]), test_needs_rebaselining=True), True) self.assertEqual(TestExpectations.result_was_expected(MISSING, set([PASS]), test_needs_rebaselining=True), True)
self.assertEqual(TestExpectations.result_was_expected(MISSING, set([PASS]), test_needs_rebaselining=False), False) self.assertEqual(TestExpectations.result_was_expected(MISSING, set([PASS]), test_needs_rebaselining=False), False)
self.assertTrue(TestExpectations.result_was_expected(PASS, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) self.assertTrue(TestExpectations.result_was_expected(
self.assertTrue(TestExpectations.result_was_expected(MISSING, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) PASS, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertTrue(TestExpectations.result_was_expected(TEXT, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) self.assertTrue(TestExpectations.result_was_expected(
self.assertTrue(TestExpectations.result_was_expected(IMAGE, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) MISSING, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertTrue(TestExpectations.result_was_expected(IMAGE_PLUS_TEXT, self.assertTrue(TestExpectations.result_was_expected(
set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) TEXT, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertTrue(TestExpectations.result_was_expected(AUDIO, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) self.assertTrue(TestExpectations.result_was_expected(
self.assertFalse(TestExpectations.result_was_expected(TIMEOUT, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) IMAGE, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertFalse(TestExpectations.result_was_expected(CRASH, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) self.assertTrue(TestExpectations.result_was_expected(
self.assertFalse(TestExpectations.result_was_expected(LEAK, set([NEEDS_REBASELINE]), test_needs_rebaselining=False)) IMAGE_PLUS_TEXT, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertTrue(TestExpectations.result_was_expected(
AUDIO, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertFalse(TestExpectations.result_was_expected(
TIMEOUT, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertFalse(TestExpectations.result_was_expected(
CRASH, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
self.assertFalse(TestExpectations.result_was_expected(
LEAK, set([NEEDS_MANUAL_REBASELINE]), test_needs_rebaselining=False))
def test_remove_pixel_failures(self): def test_remove_pixel_failures(self):
self.assertEqual(TestExpectations.remove_pixel_failures(set([FAIL])), set([FAIL])) self.assertEqual(TestExpectations.remove_pixel_failures(set([FAIL])), set([FAIL]))
...@@ -194,31 +198,6 @@ class MiscTests(Base): ...@@ -194,31 +198,6 @@ class MiscTests(Base):
def test_needs_rebaseline_reftest(self): def test_needs_rebaseline_reftest(self):
try: try:
filesystem = self._port.host.filesystem filesystem = self._port.host.filesystem
filesystem.write_text_file(
filesystem.join(
self._port.layout_tests_dir(),
'reftests/failures/expected/needsrebaseline.html'),
'content')
filesystem.write_text_file(
filesystem.join(
self._port.layout_tests_dir(),
'reftests/failures/expected/needsrebaseline-expected.html'),
'content')
filesystem.write_text_file(
filesystem.join(
self._port.layout_tests_dir(),
'reftests/failures/expected/needsrebaseline_with_txt.html'),
'content')
filesystem.write_text_file(
filesystem.join(
self._port.layout_tests_dir(),
'reftests/failures/expected/needsrebaseline_with_txt-expected.html'),
'content')
filesystem.write_text_file(
filesystem.join(
self._port.layout_tests_dir(),
'reftests/failures/expected/needsrebaseline_with_txt-expected.txt'),
'content')
filesystem.write_text_file( filesystem.write_text_file(
filesystem.join( filesystem.join(
self._port.layout_tests_dir(), self._port.layout_tests_dir(),
...@@ -249,21 +228,14 @@ class MiscTests(Base): ...@@ -249,21 +228,14 @@ class MiscTests(Base):
self._port.layout_tests_dir(), self._port.layout_tests_dir(),
'reftests/failures/expected/needsmanualrebaseline_with_txt-expected.txt'), 'reftests/failures/expected/needsmanualrebaseline_with_txt-expected.txt'),
'content') 'content')
self.parse_exp("""Bug(user) reftests/failures/expected/needsrebaseline.html [ NeedsRebaseline ] self.parse_exp(
Bug(user) reftests/failures/expected/needsrebaseline_with_txt.html [ NeedsRebaseline ] 'Bug(user) reftests/failures/expected/needsmanualrebaseline.html [ NeedsManualRebaseline ]\n'
Bug(user) reftests/failures/expected/needsmanualrebaseline.html [ NeedsManualRebaseline ] 'Bug(user) reftests/failures/expected/needsmanualrebaseline_with_txt.html [ NeedsManualRebaseline ]\n',
Bug(user) reftests/failures/expected/needsmanualrebaseline_with_txt.html [ NeedsManualRebaseline ] is_lint_mode=True)
""", is_lint_mode=True)
self.assertFalse(True, "ParseError wasn't raised") self.assertFalse(True, "ParseError wasn't raised")
except ParseError as error: except ParseError as error:
warnings = ('expectations:1 NeedsRebaseline is deprecated; see https://crbug.com/692811 ' warnings = ('expectations:1 A reftest without text expectation cannot be marked as '
'reftests/failures/expected/needsrebaseline.html\n' 'NeedsManualRebaseline reftests/failures/expected/needsmanualrebaseline.html')
'expectations:1 A reftest without text expectation cannot be marked as '
'NeedsRebaseline/NeedsManualRebaseline reftests/failures/expected/needsrebaseline.html\n'
'expectations:2 NeedsRebaseline is deprecated; see https://crbug.com/692811 '
'reftests/failures/expected/needsrebaseline_with_txt.html\n'
'expectations:3 A reftest without text expectation cannot be marked as '
'NeedsRebaseline/NeedsManualRebaseline reftests/failures/expected/needsmanualrebaseline.html')
self.assertEqual(str(error), warnings) self.assertEqual(str(error), warnings)
def test_parse_warning(self): def test_parse_warning(self):
...@@ -273,14 +245,12 @@ Bug(user) reftests/failures/expected/needsmanualrebaseline_with_txt.html [ Needs ...@@ -273,14 +245,12 @@ Bug(user) reftests/failures/expected/needsmanualrebaseline_with_txt.html [ Needs
filesystem.write_text_file(filesystem.join(self._port.layout_tests_dir(), 'test-to-rebaseline.html'), 'content') filesystem.write_text_file(filesystem.join(self._port.layout_tests_dir(), 'test-to-rebaseline.html'), 'content')
self.parse_exp('Bug(user) [ FOO ] failures/expected/text.html [ Failure ]\n' self.parse_exp('Bug(user) [ FOO ] failures/expected/text.html [ Failure ]\n'
'Bug(user) non-existent-test.html [ Failure ]\n' 'Bug(user) non-existent-test.html [ Failure ]\n'
'Bug(user) disabled-test.html-disabled [ Failure ]\n' 'Bug(user) disabled-test.html-disabled [ Failure ]\n',
'Bug(user) [ Release ] test-to-rebaseline.html [ NeedsRebaseline ]', is_lint_mode=True) is_lint_mode=True)
self.assertFalse(True, "ParseError wasn't raised") self.assertFalse(True, "ParseError wasn't raised")
except ParseError as error: except ParseError as error:
warnings = ('expectations:1 Unrecognized specifier "FOO" failures/expected/text.html\n' warnings = ('expectations:1 Unrecognized specifier "FOO" failures/expected/text.html\n'
'expectations:2 Path does not exist. non-existent-test.html\n' 'expectations:2 Path does not exist. non-existent-test.html')
'expectations:4 NeedsRebaseline is deprecated; see https://crbug.com/692811 test-to-rebaseline.html\n'
'expectations:4 A test cannot be rebaselined for Debug/Release. test-to-rebaseline.html')
self.assertEqual(str(error), warnings) self.assertEqual(str(error), warnings)
def test_parse_warnings_are_logged_if_not_in_lint_mode(self): def test_parse_warnings_are_logged_if_not_in_lint_mode(self):
...@@ -337,8 +307,6 @@ Bug(user) reftests/failures/expected/needsmanualrebaseline_with_txt.html [ Needs ...@@ -337,8 +307,6 @@ Bug(user) reftests/failures/expected/needsmanualrebaseline_with_txt.html [ Needs
self.assertFalse(match('failures/expected/image_checksum.html', PASS, True)) self.assertFalse(match('failures/expected/image_checksum.html', PASS, True))
self.assertFalse(match('failures/expected/image_checksum.html', PASS, False)) self.assertFalse(match('failures/expected/image_checksum.html', PASS, False))
self.assertFalse(match('failures/expected/crash.html', PASS, False)) self.assertFalse(match('failures/expected/crash.html', PASS, False))
self.assertTrue(match('failures/expected/needsrebaseline.html', TEXT, True))
self.assertFalse(match('failures/expected/needsrebaseline.html', CRASH, True))
self.assertTrue(match('failures/expected/needsmanualrebaseline.html', TEXT, True)) self.assertTrue(match('failures/expected/needsmanualrebaseline.html', TEXT, True))
self.assertFalse(match('failures/expected/needsmanualrebaseline.html', CRASH, True)) self.assertFalse(match('failures/expected/needsmanualrebaseline.html', CRASH, True))
self.assertTrue(match('passes/text.html', PASS, False)) self.assertTrue(match('passes/text.html', PASS, False))
...@@ -662,22 +630,24 @@ Bug(y) [ Win Mac Debug ] failures/expected/foo.html [ Crash ] ...@@ -662,22 +630,24 @@ Bug(y) [ Win Mac Debug ] failures/expected/foo.html [ Crash ]
Bug(y) [ Win Mac Debug ] failures/expected/foo.html [ Crash ] Bug(y) [ Win Mac Debug ] failures/expected/foo.html [ Crash ]
""", actual_expectations) """, actual_expectations)
def test_remove_needs_rebaseline(self): def test_remove_needs_manual_rebaseline(self):
host = MockHost() host = MockHost()
test_port = host.port_factory.get('test-win-win7', None) test_port = host.port_factory.get('test-win-win7', None)
test_port.test_exists = lambda test: True test_port.test_exists = lambda test: True
test_port.test_isfile = lambda test: True test_port.test_isfile = lambda test: True
test_config = test_port.test_configuration() test_config = test_port.test_configuration()
test_port.expectations_dict = lambda: {'expectations': """Bug(x) [ Win ] failures/expected/foo.html [ NeedsRebaseline ] test_port.expectations_dict = lambda: {
"""} 'expectations': 'Bug(x) [ Win ] failures/expected/foo.html [ NeedsManualRebaseline ]\n'
}
expectations = TestExpectations(test_port, self.get_basic_tests()) expectations = TestExpectations(test_port, self.get_basic_tests())
actual_expectations = expectations.remove_configurations([('failures/expected/foo.html', test_config)]) actual_expectations = expectations.remove_configurations([('failures/expected/foo.html', test_config)])
self.assertEqual("""Bug(x) [ Win7 Debug ] failures/expected/foo.html [ NeedsRebaseline ] self.assertEqual(
Bug(x) [ Win10 ] failures/expected/foo.html [ NeedsRebaseline ] 'Bug(x) [ Win7 Debug ] failures/expected/foo.html [ NeedsManualRebaseline ]\n'
""", actual_expectations) 'Bug(x) [ Win10 ] failures/expected/foo.html [ NeedsManualRebaseline ]\n',
actual_expectations)
def test_remove_multiple_configurations(self): def test_remove_multiple_configurations(self):
host = MockHost() host = MockHost()
......
...@@ -204,7 +204,6 @@ class SummarizedResultsTest(unittest.TestCase): ...@@ -204,7 +204,6 @@ class SummarizedResultsTest(unittest.TestCase):
'MISSING': 0, 'MISSING': 0,
'TEXT': 1, 'TEXT': 1,
'IMAGE': 1, 'IMAGE': 1,
'NEEDSREBASELINE': 0,
'NEEDSMANUALREBASELINE': 0, 'NEEDSMANUALREBASELINE': 0,
'PASS': 0, 'PASS': 0,
'REBASELINE': 0, 'REBASELINE': 0,
...@@ -226,7 +225,6 @@ class SummarizedResultsTest(unittest.TestCase): ...@@ -226,7 +225,6 @@ class SummarizedResultsTest(unittest.TestCase):
'MISSING': 0, 'MISSING': 0,
'TEXT': 0, 'TEXT': 0,
'IMAGE': 0, 'IMAGE': 0,
'NEEDSREBASELINE': 0,
'NEEDSMANUALREBASELINE': 0, 'NEEDSMANUALREBASELINE': 0,
'PASS': 1, 'PASS': 1,
'REBASELINE': 0, 'REBASELINE': 0,
...@@ -248,7 +246,6 @@ class SummarizedResultsTest(unittest.TestCase): ...@@ -248,7 +246,6 @@ class SummarizedResultsTest(unittest.TestCase):
'MISSING': 0, 'MISSING': 0,
'TEXT': 0, 'TEXT': 0,
'IMAGE': 0, 'IMAGE': 0,
'NEEDSREBASELINE': 0,
'NEEDSMANUALREBASELINE': 0, 'NEEDSMANUALREBASELINE': 0,
'PASS': 5, 'PASS': 5,
'REBASELINE': 0, 'REBASELINE': 0,
......
...@@ -110,9 +110,9 @@ class TestList(object): ...@@ -110,9 +110,9 @@ class TestList(object):
# #
# These numbers may need to be updated whenever we add or delete tests. This includes virtual tests. # These numbers may need to be updated whenever we add or delete tests. This includes virtual tests.
# #
TOTAL_TESTS = 108 TOTAL_TESTS = 106
TOTAL_WONTFIX = 3 TOTAL_WONTFIX = 3
TOTAL_SKIPS = 22 + TOTAL_WONTFIX TOTAL_SKIPS = 21 + TOTAL_WONTFIX
TOTAL_CRASHES = 76 TOTAL_CRASHES = 76
UNEXPECTED_PASSES = 1 UNEXPECTED_PASSES = 1
...@@ -126,7 +126,6 @@ def unit_test_list(): ...@@ -126,7 +126,6 @@ def unit_test_list():
tests.add('failures/expected/device_failure.html', device_failure=True) tests.add('failures/expected/device_failure.html', device_failure=True)
tests.add('failures/expected/timeout.html', timeout=True) tests.add('failures/expected/timeout.html', timeout=True)
tests.add('failures/expected/leak.html', leak=True) tests.add('failures/expected/leak.html', leak=True)
tests.add('failures/expected/needsrebaseline.html', actual_text='needsrebaseline text')
tests.add('failures/expected/needsmanualrebaseline.html', actual_text='needsmanualrebaseline text') tests.add('failures/expected/needsmanualrebaseline.html', actual_text='needsmanualrebaseline text')
tests.add('failures/expected/image.html', tests.add('failures/expected/image.html',
actual_image='image_fail-pngtEXtchecksum\x00checksum_fail', actual_image='image_fail-pngtEXtchecksum\x00checksum_fail',
...@@ -281,7 +280,6 @@ def add_unit_tests_to_mock_filesystem(filesystem): ...@@ -281,7 +280,6 @@ def add_unit_tests_to_mock_filesystem(filesystem):
Bug(test) failures/expected/crash.html [ Crash ] Bug(test) failures/expected/crash.html [ Crash ]
Bug(test) failures/expected/crash_then_text.html [ Failure ] Bug(test) failures/expected/crash_then_text.html [ Failure ]
Bug(test) failures/expected/image.html [ Failure ] Bug(test) failures/expected/image.html [ Failure ]
Bug(test) failures/expected/needsrebaseline.html [ NeedsRebaseline ]
Bug(test) failures/expected/needsmanualrebaseline.html [ NeedsManualRebaseline ] Bug(test) failures/expected/needsmanualrebaseline.html [ NeedsManualRebaseline ]
Bug(test) failures/expected/audio.html [ Failure ] Bug(test) failures/expected/audio.html [ Failure ]
Bug(test) failures/expected/image_checksum.html [ Failure ] Bug(test) failures/expected/image_checksum.html [ Failure ]
......
...@@ -95,7 +95,7 @@ class RemoveFlakesOMatic(object): ...@@ -95,7 +95,7 @@ class RemoveFlakesOMatic(object):
if len(expectations) < 2: if len(expectations) < 2:
return False return False
# Don't check lines that have expectations like NeedsRebaseline or Skip. # Don't check lines that have expectations like Skip.
if self._has_unstrippable_expectations(expectations): if self._has_unstrippable_expectations(expectations):
return False return False
...@@ -190,9 +190,12 @@ class RemoveFlakesOMatic(object): ...@@ -190,9 +190,12 @@ class RemoveFlakesOMatic(object):
True if at least one of the expectations is unstrippable. False True if at least one of the expectations is unstrippable. False
otherwise. otherwise.
""" """
unstrippable_expectations = ('REBASELINE', 'NEEDSREBASELINE', unstrippable_expectations = (
'NEEDSMANUALREBASELINE', 'SLOW', 'NEEDSMANUALREBASELINE',
'SKIP') 'REBASELINE',
'SKIP',
'SLOW',
)
return any(s in expectations for s in unstrippable_expectations) return any(s in expectations for s in unstrippable_expectations)
def _get_builder_results_by_path(self): def _get_builder_results_by_path(self):
......
...@@ -167,8 +167,7 @@ class UpdateTestExpectationsTest(LoggingTestCase): ...@@ -167,8 +167,7 @@ class UpdateTestExpectationsTest(LoggingTestCase):
Bug(test) test/b.html [ Timeout ] Bug(test) test/b.html [ Timeout ]
Bug(test) test/c.html [ Failure Timeout ] Bug(test) test/c.html [ Failure Timeout ]
Bug(test) test/d.html [ Rebaseline ] Bug(test) test/d.html [ Rebaseline ]
Bug(test) test/e.html [ NeedsManualRebaseline ] Bug(test) test/e.html [ NeedsManualRebaseline ]"""
Bug(test) test/f.html [ NeedsRebaseline ]"""
self._define_builders({ self._define_builders({
'WebKit Linux Trusty': { 'WebKit Linux Trusty': {
...@@ -265,9 +264,8 @@ class UpdateTestExpectationsTest(LoggingTestCase): ...@@ -265,9 +264,8 @@ class UpdateTestExpectationsTest(LoggingTestCase):
test_expectations_before = """ test_expectations_before = """
# Even though the results show all passing, none of the # Even though the results show all passing, none of the
# expectations are flaky so we shouldn't remove any. # expectations are flaky so we shouldn't remove any.
Bug(test) test/a.html [ Failure NeedsRebaseline Pass ] Bug(test) test/a.html [ Failure Pass Rebaseline ]
Bug(test) test/b.html [ Failure Pass Rebaseline ] Bug(test) test/b.html [ Failure NeedsManualRebaseline Pass ]"""
Bug(test) test/c.html [ Failure NeedsManualRebaseline Pass ]"""
self._define_builders({ self._define_builders({
'WebKit Linux Trusty': { 'WebKit Linux Trusty': {
...@@ -283,7 +281,6 @@ class UpdateTestExpectationsTest(LoggingTestCase): ...@@ -283,7 +281,6 @@ class UpdateTestExpectationsTest(LoggingTestCase):
'WebKit Linux Trusty': { 'WebKit Linux Trusty': {
'test/a.html': ['PASS', 'PASS'], 'test/a.html': ['PASS', 'PASS'],
'test/b.html': ['PASS', 'PASS'], 'test/b.html': ['PASS', 'PASS'],
'test/c.html': ['PASS', 'PASS']
} }
} }
updated_expectations = ( updated_expectations = (
......
# Copyright 2016 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.
"""A command to download new baselines for NeedsRebaseline tests.
This command checks the list of tests with NeedsRebaseline expectations,
and downloads the latest baselines for those tests from the results archived
by the continuous builders.
"""
import logging
import optparse
import re
import sys
import time
import traceback
import urllib2
from webkitpy.common.net.buildbot import Build, current_build_link
from webkitpy.layout_tests.models.test_expectations import TestExpectations, BASELINE_SUFFIX_LIST
from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand, TestBaselineSet
_log = logging.getLogger(__name__)
class AutoRebaseline(AbstractParallelRebaselineCommand):
name = 'auto-rebaseline'
help_text = 'Rebaselines any NeedsRebaseline lines in TestExpectations that have cycled through all the bots.'
AUTO_REBASELINE_BRANCH_NAME = 'auto-rebaseline-temporary-branch'
AUTO_REBASELINE_ALT_BRANCH_NAME = 'auto-rebaseline-alt-temporary-branch'
# Rietveld uploader stinks. Limit the number of rebaselines in a given patch to keep upload from failing.
# FIXME: http://crbug.com/263676 Obviously we should fix the uploader here.
MAX_LINES_TO_REBASELINE = 200
SECONDS_BEFORE_GIVING_UP = 300
def __init__(self):
super(AutoRebaseline, self).__init__(options=[
# FIXME: Remove this option.
self.no_optimize_option,
# FIXME: Remove this option.
self.results_directory_option,
optparse.make_option('--auth-refresh-token-json', help='Rietveld auth refresh JSON token.'),
optparse.make_option('--dry-run', action='store_true', default=False,
help='Run without creating a temporary branch, committing locally, or uploading/landing '
'changes to the remote repository.')
])
self._blame_regex = re.compile(r'''
^(\S*) # Commit hash
[^(]* \( # Whitespace and open parenthesis
< # Email address is surrounded by <>
(
[^@]+ # Username preceding @
@
[^@>]+ # Domain terminated by @ or >, some lines have an additional @ fragment after the email.
)
.*?([^ ]*) # Test file name
\ \[ # Single space followed by opening [ for expectation specifier
[^[]*$ # Prevents matching previous [ for version specifiers instead of expectation specifiers
''', re.VERBOSE)
def bot_revision_data(self, git):
revisions = []
for builder_name in self._release_builders():
result = self._tool.buildbot.fetch_results(Build(builder_name))
if result.run_was_interrupted():
_log.error("Can't rebaseline because the latest run on %s exited early.", result.builder_name())
return []
revisions.append({
'builder': result.builder_name(),
'revision': result.chromium_revision(git),
})
return revisions
@staticmethod
def _strip_comments(line):
comment_index = line.find('#')
if comment_index == -1:
comment_index = len(line)
return re.sub(r"\s+", ' ', line[:comment_index].strip())
def tests_to_rebaseline(self, tool, min_revision, print_revisions):
port = tool.port_factory.get()
expectations_file_path = port.path_to_generic_test_expectations_file()
tests = set()
revision = None
commit = None
author = None
bugs = set()
has_any_needs_rebaseline_lines = False
for line in tool.git().blame(expectations_file_path).split('\n'):
line = self._strip_comments(line)
if 'NeedsRebaseline' not in line:
continue
has_any_needs_rebaseline_lines = True
parsed_line = self._blame_regex.match(line)
if not parsed_line:
# Deal gracefully with inability to parse blame info for a line in TestExpectations.
# Parsing could fail if for example during local debugging the developer modifies
# TestExpectations and does not commit.
_log.info("Couldn't find blame info for expectations line, skipping [line=%s].", line)
continue
commit_hash = parsed_line.group(1)
commit_position = tool.git().commit_position_from_git_commit(commit_hash)
test = parsed_line.group(3)
if print_revisions:
_log.info('%s is waiting for r%s', test, commit_position)
if not commit_position or commit_position > min_revision:
continue
if revision and commit_position != revision:
continue
if not revision:
revision = commit_position
commit = commit_hash
author = parsed_line.group(2)
bugs.update(re.findall(r"crbug\.com\/(\d+)", line))
tests.add(test)
if len(tests) >= self.MAX_LINES_TO_REBASELINE:
_log.info('Too many tests to rebaseline in one patch. Doing the first %d.', self.MAX_LINES_TO_REBASELINE)
break
return tests, revision, commit, author, bugs, has_any_needs_rebaseline_lines
def commit_message(self, author, revision, commit, bugs):
message = 'Auto-rebaseline for r%s\n\n' % revision
build_link = current_build_link(self._tool)
if build_link:
message += 'Build: %s\n\n' % build_link
message += '%s\n\n' % self.link_to_patch(commit)
if bugs:
message += 'BUG=%s\n' % ','.join(bugs)
message += 'TBR=%s\n' % author
return message
@staticmethod
def link_to_patch(commit):
return 'https://chromium.googlesource.com/chromium/src/+/' + commit
def _make_test_baseline_set(self, tests):
test_baseline_set = TestBaselineSet(self._tool)
for builder_name in self._release_builders():
port_name = self._tool.builders.port_name_for_builder_name(builder_name)
port = self._tool.port_factory.get(port_name)
expectations = TestExpectations(port, include_overrides=True)
for test in expectations.get_needs_rebaseline_failures():
if test not in tests:
continue
test_baseline_set.add(test, Build(builder_name))
return test_baseline_set
def _run_git_cl_command(self, options, command):
subprocess_command = ['git', 'cl'] + command
if options.verbose:
subprocess_command.append('--verbose')
if options.auth_refresh_token_json:
subprocess_command.append('--auth-refresh-token-json')
subprocess_command.append(options.auth_refresh_token_json)
process = self._tool.executive.popen(subprocess_command, stdout=self._tool.executive.PIPE,
stderr=self._tool.executive.STDOUT)
last_output_time = time.time()
# git cl sometimes completely hangs. Bail if we haven't gotten any output to stdout/stderr in a while.
while process.poll() is None and time.time() < last_output_time + self.SECONDS_BEFORE_GIVING_UP:
# FIXME: This doesn't make any sense. readline blocks, so all this code to
# try and bail is useless. Instead, we should do the readline calls on a
# subthread. Then the rest of this code would make sense.
out = process.stdout.readline().rstrip('\n')
if out:
last_output_time = time.time()
_log.info(out)
if process.poll() is None:
_log.error('Command hung: %s', subprocess_command)
return False
return True
# FIXME: Move this somewhere more general.
@staticmethod
def tree_status():
blink_tree_status_url = 'http://chromium-status.appspot.com/status'
status = urllib2.urlopen(blink_tree_status_url).read().lower()
if 'closed' in status or status == '0':
return 'closed'
elif 'open' in status or status == '1':
return 'open'
return 'unknown'
def execute(self, options, args, tool):
self._tool = tool
if not options.dry_run and tool.git().has_working_directory_changes():
_log.error('Cannot proceed with working directory changes. Clean working directory first.')
return
revision_data = self.bot_revision_data(tool.git())
if not revision_data:
return
min_revision = int(min([item['revision'] for item in revision_data]))
tests, revision, commit, author, bugs, _ = self.tests_to_rebaseline(
tool, min_revision, print_revisions=options.verbose)
if options.verbose:
_log.info('Min revision across all bots is %s.', min_revision)
for item in revision_data:
_log.info('%s: r%s', item['builder'], item['revision'])
if not tests:
_log.debug('No tests to rebaseline.')
return
if self.tree_status() == 'closed':
_log.info('Cannot proceed. Tree is closed.')
return
_log.info('Rebaselining %s for r%s by %s.', list(tests), revision, author)
test_baseline_set = self._make_test_baseline_set(tests)
did_switch_branches = False
did_finish = False
old_branch_name_or_ref = ''
rebaseline_branch_name = self.AUTO_REBASELINE_BRANCH_NAME
try:
# Save the current branch name and check out a clean branch for the patch.
old_branch_name_or_ref = tool.git().current_branch_or_ref()
if old_branch_name_or_ref == self.AUTO_REBASELINE_BRANCH_NAME:
rebaseline_branch_name = self.AUTO_REBASELINE_ALT_BRANCH_NAME
if not options.dry_run:
tool.git().delete_branch(rebaseline_branch_name)
tool.git().create_clean_branch(rebaseline_branch_name)
did_switch_branches = True
if test_baseline_set:
self.rebaseline(options, test_baseline_set)
if options.dry_run:
return
tool.git().commit_locally_with_message(
self.commit_message(author, revision, commit, bugs))
# FIXME: It would be nice if we could dcommit the patch without uploading, but still
# go through all the precommit hooks. For rebaselines with lots of files, uploading
# takes a long time and sometimes fails, but we don't want to commit if, e.g. the
# tree is closed.
did_finish = self._run_git_cl_command(options, ['upload', '-f'])
if did_finish:
# Uploading can take a very long time. Do another pull to make sure TestExpectations is up to date,
# so the dcommit can go through.
# FIXME: Log the pull and dcommit stdout/stderr to the log-server.
tool.executive.run_command(['git', 'pull'])
self._run_git_cl_command(options, ['land', '-f', '-v'])
except OSError:
traceback.print_exc(file=sys.stderr)
finally:
if did_switch_branches:
if did_finish:
# Close the issue if dcommit failed.
issue_already_closed = tool.executive.run_command(
['git', 'config', 'branch.%s.rietveldissue' % rebaseline_branch_name],
return_exit_code=True)
if not issue_already_closed:
self._run_git_cl_command(options, ['set_close'])
tool.git().ensure_cleanly_tracking_remote_master()
if old_branch_name_or_ref:
tool.git().checkout_branch(old_branch_name_or_ref)
tool.git().delete_branch(rebaseline_branch_name)
# Copyright 2016 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
from webkitpy.common.net.buildbot import Build
from webkitpy.common.net.layout_test_results import LayoutTestResults
from webkitpy.common.system.executive_mock import MockExecutive
from webkitpy.layout_tests.builder_list import BuilderList
from webkitpy.tool.commands.auto_rebaseline import AutoRebaseline
from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
from webkitpy.tool.commands.rebaseline_unittest import MockLineRemovingExecutive
class TestAutoRebaseline(BaseTestCase):
command_constructor = AutoRebaseline
def _write_test_file(self, port, path, contents):
abs_path = self.tool.filesystem.join(port.layout_tests_dir(), path)
self.tool.filesystem.write_text_file(abs_path, contents)
def _execute_with_mock_options(self, auth_refresh_token_json=None, commit_author=None, dry_run=False):
self.command.execute(
optparse.Values({
'optimize': True,
'verbose': False,
'results_directory': False,
'auth_refresh_token_json': auth_refresh_token_json,
'commit_author': commit_author,
'dry_run': dry_run
}),
[],
self.tool)
def setUp(self):
super(TestAutoRebaseline, self).setUp()
self.tool.builders = BuilderList({
'MOCK Mac10.10': {'port_name': 'test-mac-mac10.10', 'specifiers': ['Mac10.10', 'Release']},
'MOCK Mac10.11': {'port_name': 'test-mac-mac10.11', 'specifiers': ['Mac10.11', 'Release']},
'MOCK Precise': {'port_name': 'test-linux-precise', 'specifiers': ['Precise', 'Release']},
'MOCK Trusty': {'port_name': 'test-linux-trusty', 'specifiers': ['Trusty', 'Release']},
'MOCK Win7': {'port_name': 'test-win-win7', 'specifiers': ['Win7', 'Release']},
'MOCK Win7 (dbg)': {'port_name': 'test-win-win7', 'specifiers': ['Win7', 'Debug']},
})
self.command.latest_revision_processed_on_all_bots = lambda: 9000
self.command.bot_revision_data = lambda git: [{'builder': 'MOCK Win7', 'revision': '9000'}]
def test_release_builders(self):
# Testing private method - pylint: disable=protected-access
self.tool.builders = BuilderList({
'MOCK Mac10.10': {'port_name': 'test-mac-mac10.10', 'specifiers': ['Mac10.10', 'Release']},
'MOCK Mac10.11 (dbg)': {'port_name': 'test-mac-mac10.11', 'specifiers': ['Mac10.11', 'Debug']},
})
self.assertEqual(self.command._release_builders(), ['MOCK Mac10.10'])
def test_tests_to_rebaseline(self):
def blame(_):
return """
624c3081c0 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-06-14 20:18:46 +0000 11) crbug.com/24182 [ Debug ] path/to/norebaseline.html [ Failure ]
624c3081c0 path/to/TestExpectations (<foobarbaz1@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> 2013-06-14 20:18:46 +0000 11) crbug.com/24182 [ Debug ] path/to/norebaseline-email-with-hash.html [ Failure ]
624c3081c0 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) path/to/rebaseline-without-bug-number.html [ NeedsRebaseline ]
624c3081c0 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-06-14 20:18:46 +0000 11) crbug.com/24182 [ Debug ] path/to/rebaseline-with-modifiers.html [ NeedsRebaseline ]
624c3081c0 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 crbug.com/234 path/to/rebaseline-without-modifiers.html [ NeedsRebaseline ]
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 path/to/rebaseline-new-revision.html [ NeedsRebaseline ]
624caaaaaa path/to/TestExpectations (<foo@chromium.org> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 path/to/not-cycled-through-bots.html [ NeedsRebaseline ]
0000000000 path/to/TestExpectations (<foo@chromium.org@@bbb929c8-8fbe-4397-9dbb-9b2b20218538> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 path/to/locally-changed-lined.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
min_revision = 9000
self.assertEqual(self.command.tests_to_rebaseline(self.tool, min_revision, print_revisions=False), (
set(['path/to/rebaseline-without-bug-number.html',
'path/to/rebaseline-with-modifiers.html', 'path/to/rebaseline-without-modifiers.html']),
5678,
'624c3081c0',
'foobarbaz1@chromium.org',
set(['24182', '234']),
True))
def test_tests_to_rebaseline_over_limit(self):
def blame(_):
result = ''
for i in range(0, self.command.MAX_LINES_TO_REBASELINE + 1):
result += ('624c3081c0 path/to/TestExpectations '
'(<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) '
'crbug.com/24182 path/to/rebaseline-%s.html [ NeedsRebaseline ]\n' % i)
return result
self.tool.git().blame = blame
expected_list_of_tests = []
for i in range(0, self.command.MAX_LINES_TO_REBASELINE):
expected_list_of_tests.append('path/to/rebaseline-%s.html' % i)
min_revision = 9000
self.assertEqual(self.command.tests_to_rebaseline(self.tool, min_revision, print_revisions=False), (
set(expected_list_of_tests),
5678,
'624c3081c0',
'foobarbaz1@chromium.org',
set(['24182']),
True))
def test_commit_message(self):
author = 'foo@chromium.org'
revision = 1234
commit = 'abcd567'
bugs = set()
self.assertEqual(self.command.commit_message(author, revision, commit, bugs),
'Auto-rebaseline for r1234\n\n'
'https://chromium.googlesource.com/chromium/src/+/abcd567\n\n'
'TBR=foo@chromium.org\n')
bugs = set(['234', '345'])
self.assertEqual(self.command.commit_message(author, revision, commit, bugs),
'Auto-rebaseline for r1234\n\n'
'https://chromium.googlesource.com/chromium/src/+/abcd567\n\n'
'BUG=234,345\n'
'TBR=foo@chromium.org\n')
self.tool.environ['BUILDBOT_MASTERNAME'] = 'my.master'
self.tool.environ['BUILDBOT_BUILDERNAME'] = 'b'
self.tool.environ['BUILDBOT_BUILDNUMBER'] = '123'
self.assertEqual(self.command.commit_message(author, revision, commit, bugs),
'Auto-rebaseline for r1234\n\n'
'Build: https://build.chromium.org/p/my.master/builders/b/builds/123\n\n'
'https://chromium.googlesource.com/chromium/src/+/abcd567\n\n'
'BUG=234,345\n'
'TBR=foo@chromium.org\n')
def test_no_needs_rebaseline_lines(self):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-06-14 20:18:46 +0000 11) crbug.com/24182 [ Debug ] path/to/norebaseline.html [ Failure ]
"""
self.tool.git().blame = blame
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [])
def test_execute(self):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-06-14 20:18:46 +0000 11) # Test NeedsRebaseline being in a comment doesn't bork parsing.
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-06-14 20:18:46 +0000 11) crbug.com/24182 [ Debug ] path/to/norebaseline.html [ Failure ]
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-06-14 20:18:46 +0000 11) crbug.com/24182 [ Mac10.11 ] fast/dom/prototype-strawberry.html [ NeedsRebaseline ]
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 fast/dom/prototype-chocolate.html [ NeedsRebaseline ]
624caaaaaa path/to/TestExpectations (<foo@chromium.org> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 path/to/not-cycled-through-bots.html [ NeedsRebaseline ]
0000000000 path/to/TestExpectations (<foo@chromium.org> 2013-04-28 04:52:41 +0000 12) crbug.com/24182 path/to/locally-changed-lined.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
test_port = self.tool.port_factory.get('test')
# Have prototype-chocolate only fail on "MOCK Mac10.11",
# and pass on "Mock Mac10.10".
self.tool.buildbot.set_results(Build('MOCK Mac10.11'), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'PASS',
'actual': 'PASS TEXT',
'is_unexpected': True
},
'prototype-chocolate.html': {
'expected': 'FAIL',
'actual': 'PASS'
},
'prototype-strawberry.html': {
'expected': 'PASS',
'actual': 'IMAGE PASS',
'is_unexpected': True
}
}
}
}
}))
self.tool.buildbot.set_results(Build('MOCK Mac10.10'), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'PASS',
'actual': 'PASS',
},
'prototype-chocolate.html': {
'expected': 'FAIL',
'actual': 'FAIL'
},
'prototype-strawberry.html': {
'expected': 'PASS',
'actual': 'PASS',
}
}
}
}
}))
self.tool.filesystem.write_text_file(test_port.path_to_generic_test_expectations_file(), """
crbug.com/24182 [ Debug ] path/to/norebaseline.html [ Rebaseline ]
Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
crbug.com/24182 [ Mac10.11 ] fast/dom/prototype-strawberry.html [ NeedsRebaseline ]
crbug.com/24182 fast/dom/prototype-chocolate.html [ NeedsRebaseline ]
crbug.com/24182 path/to/not-cycled-through-bots.html [ NeedsRebaseline ]
crbug.com/24182 path/to/locally-changed-lined.html [ NeedsRebaseline ]
""")
self._write_test_file(test_port, 'fast/dom/prototype-taco.html', 'Dummy test contents')
self._write_test_file(test_port, 'fast/dom/prototype-strawberry.html', 'Dummy test contents')
self._write_test_file(test_port, 'fast/dom/prototype-chocolate.html', 'Dummy test contents')
self.tool.executive = MockLineRemovingExecutive()
self.tool.builders = BuilderList({
'MOCK Mac10.10': {'port_name': 'test-mac-mac10.10', 'specifiers': ['Mac10.10', 'Release']},
'MOCK Mac10.11': {'port_name': 'test-mac-mac10.11', 'specifiers': ['Mac10.11', 'Release']},
})
self.command.tree_status = lambda: 'closed'
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [])
self.command.tree_status = lambda: 'open'
self.tool.executive.full_calls = []
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [
[
[
'python', 'echo', 'copy-existing-baselines-internal',
'--test', 'fast/dom/prototype-strawberry.html',
'--suffixes', 'png',
'--port-name', 'test-mac-mac10.11',
],
[
'python', 'echo', 'copy-existing-baselines-internal',
'--test', 'fast/dom/prototype-taco.html',
'--suffixes', 'txt',
'--port-name', 'test-mac-mac10.11',
],
],
[
[
'python', 'echo', 'rebaseline-test-internal',
'--test', 'fast/dom/prototype-strawberry.html',
'--suffixes', 'png',
'--port-name', 'test-mac-mac10.11',
'--builder', 'MOCK Mac10.11',
],
[
'python', 'echo', 'rebaseline-test-internal',
'--test', 'fast/dom/prototype-taco.html',
'--suffixes', 'txt',
'--port-name', 'test-mac-mac10.11',
'--builder', 'MOCK Mac10.11',
],
],
[
[
'python', 'echo', 'optimize-baselines',
'--suffixes', 'png',
'fast/dom/prototype-strawberry.html',
],
[
'python', 'echo', 'optimize-baselines',
'--suffixes', 'txt',
'fast/dom/prototype-taco.html',
],
],
['git', 'cl', 'upload', '-f'],
['git', 'pull'],
['git', 'cl', 'land', '-f', '-v'],
['git', 'config', 'branch.auto-rebaseline-temporary-branch.rietveldissue'],
['git', 'cl', 'set_close'],
])
# The mac ports should both be removed since they're the only ones in builders._exact_matches.
self.assertEqual(self.tool.filesystem.read_text_file(test_port.path_to_generic_test_expectations_file()), """
crbug.com/24182 [ Debug ] path/to/norebaseline.html [ Rebaseline ]
Bug(foo) [ Linux Win ] fast/dom/prototype-taco.html [ NeedsRebaseline ]
crbug.com/24182 [ Linux Win ] fast/dom/prototype-chocolate.html [ NeedsRebaseline ]
crbug.com/24182 path/to/not-cycled-through-bots.html [ NeedsRebaseline ]
crbug.com/24182 path/to/locally-changed-lined.html [ NeedsRebaseline ]
""")
def test_execute_git_cl_hangs(self):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
test_port = self.tool.port_factory.get('test')
# Have prototype-chocolate only fail on "MOCK Mac10.11".
self.tool.buildbot.set_results(Build('MOCK Mac10.11'), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'PASS',
'actual': 'PASS TEXT',
'is_unexpected': True
}
}
}
}
}))
self.tool.filesystem.write_text_file(test_port.path_to_generic_test_expectations_file(), """
Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
self._write_test_file(test_port, 'fast/dom/prototype-taco.html', 'Dummy test contents')
self.tool.builders = BuilderList({
'MOCK Mac10.11': {'port_name': 'test-mac-mac10.11', 'specifiers': ['Mac10.11', 'Release']},
})
self.command.SECONDS_BEFORE_GIVING_UP = 0
self.command.tree_status = lambda: 'open'
self.tool.executive = MockExecutive()
self.tool.executive.full_calls = []
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [
[[
'python', 'echo', 'copy-existing-baselines-internal',
'--test', 'fast/dom/prototype-taco.html',
'--suffixes', 'txt',
'--port-name', 'test-mac-mac10.11',
]],
[[
'python', 'echo', 'rebaseline-test-internal',
'--test', 'fast/dom/prototype-taco.html',
'--suffixes', 'txt',
'--port-name', 'test-mac-mac10.11',
'--builder', 'MOCK Mac10.11',
]],
[[
'python', 'echo', 'optimize-baselines',
'--suffixes', 'txt',
'fast/dom/prototype-taco.html',
]],
['git', 'cl', 'upload', '-f'],
])
def test_execute_test_passes_everywhere(self):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
test_port = self.tool.port_factory.get('test')
for builder in ['MOCK Mac10.10', 'MOCK Mac10.11']:
self.tool.buildbot.set_results(Build(builder), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'FAIL',
'actual': 'PASS',
'is_unexpected': True
}
}
}
}
}))
self.tool.filesystem.write_text_file(test_port.path_to_generic_test_expectations_file(), """
Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
self._write_test_file(test_port, 'fast/dom/prototype-taco.html', 'Dummy test contents')
self.tool.executive = MockLineRemovingExecutive()
self.tool.builders = BuilderList({
'MOCK Mac10.10': {'port_name': 'test-mac-mac10.10', 'specifiers': ['Mac10.10', 'Release']},
'MOCK Mac10.11': {'port_name': 'test-mac-mac10.11', 'specifiers': ['Mac10.11', 'Release']},
})
self.command.tree_status = lambda: 'open'
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [
['git', 'cl', 'upload', '-f'],
['git', 'pull'],
['git', 'cl', 'land', '-f', '-v'],
['git', 'config', 'branch.auto-rebaseline-temporary-branch.rietveldissue'],
['git', 'cl', 'set_close'],
])
# The mac ports should both be removed since they're the only ones in builders._exact_matches.
self.assertEqual(self.tool.filesystem.read_text_file(test_port.path_to_generic_test_expectations_file()), """
Bug(foo) [ Linux Win ] fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
def test_execute_use_alternate_rebaseline_branch(self):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
test_port = self.tool.port_factory.get('test')
self.tool.buildbot.set_results(Build('MOCK Win7'), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'FAIL',
'actual': 'PASS',
'is_unexpected': True
}
}
}
}
}))
self.tool.filesystem.write_text_file(test_port.path_to_generic_test_expectations_file(), """
Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
self._write_test_file(test_port, 'fast/dom/prototype-taco.html', 'Dummy test contents')
self.tool.executive = MockLineRemovingExecutive()
self.tool.builders = BuilderList({
'MOCK Win7': {'port_name': 'test-win-win7', 'specifiers': ['Win7', 'Release']},
})
old_branch_name = self.tool.git().current_branch_or_ref
try:
self.command.tree_status = lambda: 'open'
self.tool.git().current_branch_or_ref = lambda: 'auto-rebaseline-temporary-branch'
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [
['git', 'cl', 'upload', '-f'],
['git', 'pull'],
['git', 'cl', 'land', '-f', '-v'],
['git', 'config', 'branch.auto-rebaseline-alt-temporary-branch.rietveldissue'],
['git', 'cl', 'set_close'],
])
self.assertEqual(self.tool.filesystem.read_text_file(test_port.path_to_generic_test_expectations_file()), """
Bug(foo) [ Linux Mac Win10 ] fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
finally:
self.tool.git().current_branch_or_ref = old_branch_name
def test_execute_stuck_on_alternate_rebaseline_branch(self):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
test_port = self.tool.port_factory.get('test')
self.tool.buildbot.set_results(Build('MOCK Win7'), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'FAIL',
'actual': 'PASS',
'is_unexpected': True
}
}
}
}
}))
self.tool.filesystem.write_text_file(test_port.path_to_generic_test_expectations_file(), """
Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
self._write_test_file(test_port, 'fast/dom/prototype-taco.html', 'Dummy test contents')
self.tool.executive = MockLineRemovingExecutive()
self.tool.builders = BuilderList({
'MOCK Win7': {'port_name': 'test-win-win7', 'specifiers': ['Win7', 'Release']},
})
old_branch_name = self.tool.git().current_branch_or_ref
try:
self.command.tree_status = lambda: 'open'
self.tool.git().current_branch_or_ref = lambda: 'auto-rebaseline-alt-temporary-branch'
self._execute_with_mock_options()
self.assertEqual(self.tool.executive.calls, [
['git', 'cl', 'upload', '-f'],
['git', 'pull'],
['git', 'cl', 'land', '-f', '-v'],
['git', 'config', 'branch.auto-rebaseline-temporary-branch.rietveldissue'],
['git', 'cl', 'set_close'],
])
self.assertEqual(self.tool.filesystem.read_text_file(test_port.path_to_generic_test_expectations_file()), """
Bug(foo) [ Linux Mac Win10 ] fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
finally:
self.tool.git().current_branch_or_ref = old_branch_name
def _basic_execute_test(self, expected_executive_calls, auth_refresh_token_json=None, commit_author=None, dry_run=False):
def blame(_):
return """
6469e754a1 path/to/TestExpectations (<foobarbaz1@chromium.org> 2013-04-28 04:52:41 +0000 13) Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
"""
self.tool.git().blame = blame
test_port = self.tool.port_factory.get('test')
for builder in ['MOCK Mac10.10', 'MOCK Mac10.11']:
self.tool.buildbot.set_results(Build(builder), LayoutTestResults({
'tests': {
'fast': {
'dom': {
'prototype-taco.html': {
'expected': 'FAIL',
'actual': 'PASS',
'is_unexpected': True
}
}
}
}
}))
self.tool.filesystem.write_text_file(test_port.path_to_generic_test_expectations_file(), """
Bug(foo) fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
self._write_test_file(test_port, 'fast/dom/prototype-taco.html', 'Dummy test contents')
self.tool.executive = MockLineRemovingExecutive()
self.tool.builders = BuilderList({
'MOCK Mac10.10': {'port_name': 'test-mac-mac10.10', 'specifiers': ['Mac10.10', 'Release']},
'MOCK Mac10.11': {'port_name': 'test-mac-mac10.11', 'specifiers': ['Mac10.11', 'Release']},
})
self.command.tree_status = lambda: 'open'
self._execute_with_mock_options(auth_refresh_token_json=auth_refresh_token_json,
commit_author=commit_author, dry_run=dry_run)
self.assertEqual(self.tool.executive.calls, expected_executive_calls)
# The mac ports should both be removed since they're the only ones in builders._exact_matches.
self.assertEqual(self.tool.filesystem.read_text_file(test_port.path_to_generic_test_expectations_file()), """
Bug(foo) [ Linux Win ] fast/dom/prototype-taco.html [ NeedsRebaseline ]
""")
def test_execute_with_rietveld_auth_refresh_token(self):
rietveld_refresh_token = '/creds/refresh_tokens/test_rietveld_token'
self._basic_execute_test(
[
['git', 'cl', 'upload', '-f', '--auth-refresh-token-json', rietveld_refresh_token],
['git', 'pull'],
['git', 'cl', 'land', '-f', '-v', '--auth-refresh-token-json', rietveld_refresh_token],
['git', 'config', 'branch.auto-rebaseline-temporary-branch.rietveldissue'],
['git', 'cl', 'set_close', '--auth-refresh-token-json', rietveld_refresh_token],
],
auth_refresh_token_json=rietveld_refresh_token)
def test_execute_with_dry_run(self):
self._basic_execute_test([], dry_run=True)
self.assertEqual(self.tool.git().local_commits(), [])
def test_bot_revision_data(self):
self._setup_mock_build_data()
self.assertEqual(
self.command.bot_revision_data(self.tool.git()),
[{'builder': 'MOCK Win7', 'revision': '9000'}])
...@@ -339,9 +339,7 @@ class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand): ...@@ -339,9 +339,7 @@ class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
# This is so we remove lines for builders that skip this test, e.g. Android skips most # This is so we remove lines for builders that skip this test, e.g. Android skips most
# tests and we don't want to leave stray [ Android ] lines in TestExpectations.. # tests and we don't want to leave stray [ Android ] lines in TestExpectations..
# This is only necessary for "webkit-patch rebaseline" and for rebaselining expected # This is only necessary for "webkit-patch rebaseline".
# failures from garden-o-matic. rebaseline-expectations and auto-rebaseline will always
# pass the exact set of ports to rebaseline.
for port_name in self._tool.port_factory.all_port_names(): for port_name in self._tool.port_factory.all_port_names():
port = self._tool.port_factory.get(port_name) port = self._tool.port_factory.get(port_name)
generic_expectations = TestExpectations(port, tests=tests, include_overrides=False) generic_expectations = TestExpectations(port, tests=tests, include_overrides=False)
......
...@@ -173,7 +173,7 @@ class TestRebaseline(BaseTestCase): ...@@ -173,7 +173,7 @@ class TestRebaseline(BaseTestCase):
'tests': { 'tests': {
'userscripts': { 'userscripts': {
'first-test.html': { 'first-test.html': {
'expected': 'NEEDSREBASELINE', 'expected': 'REBASELINE',
'actual': 'PASS' 'actual': 'PASS'
} }
} }
......
...@@ -42,7 +42,6 @@ import sys ...@@ -42,7 +42,6 @@ import sys
from webkitpy.common.host import Host from webkitpy.common.host import Host
from webkitpy.tool.commands.analyze_baselines import AnalyzeBaselines from webkitpy.tool.commands.analyze_baselines import AnalyzeBaselines
from webkitpy.tool.commands.auto_rebaseline import AutoRebaseline
from webkitpy.tool.commands.command import HelpPrintingOptionParser from webkitpy.tool.commands.command import HelpPrintingOptionParser
from webkitpy.tool.commands.copy_existing_baselines import CopyExistingBaselines from webkitpy.tool.commands.copy_existing_baselines import CopyExistingBaselines
from webkitpy.tool.commands.flaky_tests import FlakyTests from webkitpy.tool.commands.flaky_tests import FlakyTests
...@@ -81,7 +80,6 @@ class WebKitPatch(Host): ...@@ -81,7 +80,6 @@ class WebKitPatch(Host):
self._path = path self._path = path
self.commands = [ self.commands = [
AnalyzeBaselines(), AnalyzeBaselines(),
AutoRebaseline(),
CopyExistingBaselines(), CopyExistingBaselines(),
CrashLog(), CrashLog(),
FlakyTests(), FlakyTests(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment