| #!/usr/bin/env vpython3 | |
| # Copyright 2026 The Chromium Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| """Unit tests for code_generator_frontend.py. | |
| The generator runs at import time, so the tests run it as a subprocess, the | |
| way the build does. | |
| """ | |
| import json | |
| import os | |
| import subprocess | |
| import sys | |
| import tempfile | |
| import unittest | |
| GENERATOR = os.path.join(os.path.dirname(os.path.abspath(__file__)), | |
| 'code_generator_frontend.py') | |
| PROTOCOL = { | |
| 'version': { | |
| 'major': '1', | |
| 'minor': '3' | |
| }, | |
| 'domains': [{ | |
| 'domain': | |
| 'DOM', | |
| 'types': [{ | |
| 'id': 'NodeId', | |
| 'type': 'integer' | |
| }, { | |
| 'id': 'Node', | |
| 'type': 'object', | |
| 'properties': [{ | |
| 'name': 'nodeId', | |
| '$ref': 'NodeId' | |
| }], | |
| }], | |
| 'commands': [{ | |
| 'name': | |
| 'getDocument', | |
| 'description': | |
| 'Returns the root DOM node.', | |
| 'parameters': [{ | |
| 'name': 'depth', | |
| 'type': 'integer', | |
| 'optional': True, | |
| 'description': 'The maximum depth.', | |
| }], | |
| 'returns': [{ | |
| 'name': 'root', | |
| '$ref': 'Node' | |
| }], | |
| }], | |
| 'events': [{ | |
| 'name': 'documentUpdated', | |
| 'parameters': [] | |
| }], | |
| }], | |
| } | |
| class CodeGeneratorFrontendTest(unittest.TestCase): | |
| def setUp(self): | |
| tmpdir = tempfile.TemporaryDirectory() | |
| self.addCleanup(tmpdir.cleanup) | |
| self.protocol_json = os.path.join(tmpdir.name, 'protocol.json') | |
| self.output = os.path.join(tmpdir.name, 'InspectorBackendCommands.ts') | |
| with open(self.protocol_json, 'w', encoding='utf-8') as f: | |
| json.dump(PROTOCOL, f) | |
| def run_generator(self, *args): | |
| return subprocess.run([sys.executable, GENERATOR] + list(args), | |
| capture_output=True, | |
| text=True, | |
| check=False) | |
| def generate(self): | |
| result = self.run_generator('--input', self.protocol_json, '--output', | |
| self.output) | |
| self.assertEqual(result.returncode, 0, result.stderr) | |
| with open(self.output, 'rb') as f: | |
| return f.read().decode('utf-8') | |
| def test_registers_the_protocol(self): | |
| contents = self.generate() | |
| self.assertIn( | |
| 'export function registerCommands(inspectorBackend: ' | |
| 'InspectorBackendAPI): void {', contents) | |
| self.assertIn( | |
| 'inspectorBackend.registerCommand("DOM.getDocument", ' | |
| '[{"name": "depth", "type": "number", "optional": true, ' | |
| '"description": "The maximum depth.", "typeRef": null}], ' | |
| '["root"], "Returns the root DOM node.");', contents) | |
| self.assertIn( | |
| 'inspectorBackend.registerEvent("DOM.documentUpdated", [])', | |
| contents) | |
| self.assertIn( | |
| 'inspectorBackend.registerType("DOM.Node", [{"name": "nodeId", ' | |
| '"type": "number", "optional": false, "description": "", ' | |
| '"typeRef": "DOM.NodeId"}]);', contents) | |
| def test_header_does_not_depend_on_the_checkout(self): | |
| contents = self.generate() | |
| self.assertTrue( | |
| contents.startswith( | |
| '// Copyright 2020 The Chromium Authors\n' | |
| '// Use of this source code is governed by a BSD-style license that can be\n' | |
| '// found in the LICENSE file.\n' | |
| '// File is generated by scripts/build/code_generator_frontend.py\n' | |
| ), contents[:300]) | |
| self.assertNotIn('\r', contents) | |
| def test_always_rewrites_the_output(self): | |
| # scripts/build/run_with_restat.py restores the mtime of outputs whose | |
| # bytes did not change; the generator itself must always write. | |
| first = self.generate() | |
| mtime = os.stat(self.output).st_mtime_ns | |
| os.utime(self.output, | |
| ns=(mtime - 1_000_000_000, mtime - 1_000_000_000)) | |
| second = self.generate() | |
| self.assertEqual(first, second) | |
| self.assertNotEqual( | |
| os.stat(self.output).st_mtime_ns, mtime - 1_000_000_000) | |
| def test_requires_both_paths(self): | |
| self.assertNotEqual( | |
| self.run_generator('--input', self.protocol_json).returncode, 0) | |
| self.assertNotEqual( | |
| self.run_generator('--output', self.output).returncode, 0) | |
| self.assertFalse(os.path.exists(self.output)) | |
| if __name__ == '__main__': | |
| unittest.main() |