[web-tests] Strip negative/positive prefixes when linting filter files

`lint_test_expectations.py` removes leading `+` or `-` from filter file
terms before checking for test existence. This is needed to support
negative terms in an inverted `TestLists/headless_shell.filter`.

Bug: 40927590
Change-Id: Ia55dbc542c66cd8ac1724956d951ff00d24d5698
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020542
Reviewed-by: Weizhong Xia <weizhong@google.com>
Commit-Queue: Jonathan Lee <jonathanjlee@google.com>
Cr-Commit-Position: refs/heads/main@{#1382727}
diff --git a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
index e98188b..09c9d138 100644
--- a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
+++ b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
@@ -433,6 +433,10 @@
                 line = line[:-1]
             if not line:
                 continue
+            # A sign denoting inclusion or exclusion may prefix terms in filter
+            # files.
+            if line.startswith('+') or line.startswith('-'):
+                line = line[1:]
             if line in parsed_lines:
                 failures.append(
                     '%s:%d duplicate with line %d: %s' %
diff --git a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py
index d54e53d1..5b2d3c65 100644
--- a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations_unittest.py
@@ -464,6 +464,35 @@
         self.assertRegexpMatches(failures[0], ':2 .*Skip')
 
 
+class CheckTestListsTest(unittest.TestCase):
+
+    def test_check_existence(self):
+        options = optparse.Values({
+            'additional_expectations': [],
+            'platform': 'test'
+        })
+        host = MockHost()
+        port = host.port_factory.get(options.platform, options=options)
+        finder = PathFinder(host.filesystem)
+
+        host.filesystem.write_text_file(
+            finder.path_from_web_tests('TestLists', 'tests.filter'),
+            textwrap.dedent("""\
+                +exists/1.html
+                exists/
+                -does/not/exist/
+                does/not/exist/1.html
+                """))
+        host.filesystem.write_text_file(
+            finder.path_from_web_tests('exists', '1.html'), '')
+
+        failures = lint_test_expectations.check_test_lists(host, options)
+        self.assertEqual(failures, [
+            'tests.filter:3 Test does not exist: does/not/exist/',
+            'tests.filter:4 Test does not exist: does/not/exist/1.html',
+        ])
+
+
 class CheckVirtualSuiteTest(unittest.TestCase):
     def setUp(self):
         self.host = MockHost()
@@ -657,6 +686,7 @@
                                  'Virtual suite name "test" has no owner.')
         self.assertEqual(len(res2), 1)
 
+
 class MainTest(unittest.TestCase):
     def setUp(self):
         self.orig_lint_fn = lint_test_expectations.lint