Add presubmit for tag headers
Adds a simple script and presubmit check for ensuring that the
WebGPU CTS expectation file tag headers remain in sync.
Also drive-by updates the webgpu-cts directory presubmit file to
version 2 of the presubmit API.
Bug: 345280734
Change-Id: I5d0bde1453b6e557fa297d46a88fc1d6364693d1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/204434
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brian Sheedy <bsheedy@google.com>
diff --git a/webgpu-cts/PRESUBMIT.py b/webgpu-cts/PRESUBMIT.py
index 03f9907..4fb56c3 100644
--- a/webgpu-cts/PRESUBMIT.py
+++ b/webgpu-cts/PRESUBMIT.py
@@ -27,8 +27,10 @@
import sys
+PRESUBMIT_VERSION = '2.0.0'
-def _DoCommonChecks(input_api, output_api):
+
+def CheckCtsValidate(input_api, output_api):
sys.path += [input_api.change.RepositoryRoot()]
from go_presubmit_support import go_path
@@ -62,5 +64,14 @@
return results
-CheckChangeOnUpload = _DoCommonChecks
-CheckChangeOnCommit = _DoCommonChecks
+def CheckHeaderSync(input_api, output_api):
+ results = []
+ sync_script = input_api.os_path.join(input_api.PresubmitLocalPath(),
+ 'scripts', 'check_headers_in_sync.py')
+ try:
+ input_api.subprocess.check_call_out([sync_script],
+ stdout=input_api.subprocess.PIPE,
+ stderr=input_api.subprocess.STDOUT)
+ except input_api.subprocess.CalledProcessError as e:
+ results.append(output_api.PresubmitError(str(e)))
+ return results
diff --git a/webgpu-cts/scripts/check_headers_in_sync.py b/webgpu-cts/scripts/check_headers_in_sync.py
new file mode 100755
index 0000000..2e58678
--- /dev/null
+++ b/webgpu-cts/scripts/check_headers_in_sync.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# Copyright 2024 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Asserts that all expectation file headers are in sync."""
+
+import os
+
+TAG_HEADER_START = '# BEGIN TAG HEADER'
+TAG_HEADER_END = '# END TAG HEADER'
+
+EXPECTATION_FILES = [
+ os.path.realpath(
+ os.path.join(os.path.dirname(__file__), '..', 'expectations.txt')),
+ os.path.realpath(
+ os.path.join(os.path.dirname(__file__), '..',
+ 'compat-expectations.txt')),
+]
+
+tag_headers = {}
+for ef in EXPECTATION_FILES:
+ with open(ef, encoding='utf-8') as infile:
+ content = infile.read()
+
+ header_lines = []
+ in_header = False
+ for line in content.splitlines():
+ line = line.strip()
+ if line.startswith(TAG_HEADER_START):
+ in_header = True
+ continue
+ if not in_header:
+ continue
+ if line.startswith(TAG_HEADER_END):
+ break
+ header_lines.append(line)
+ tag_headers[ef] = '\n'.join(header_lines)
+
+for left_ef, left_header in tag_headers.items():
+ for right_ef, right_header in tag_headers.items():
+ if left_ef == right_ef:
+ continue
+ if left_header != right_header:
+ raise RuntimeError(
+ f'The tag headers in {left_ef} and {right_ef} are out of sync')