| #!/usr/bin/env python3 | |
| # Copyright 2025 The Chromium Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| import generate_code_cache | |
| import glob | |
| import json | |
| import os | |
| import shutil | |
| import sys # noqa: F401 | |
| import tempfile | |
| import unittest | |
| _HERE_DIR = os.path.dirname(__file__) | |
| _BUILD_DIR = os.environ['CHROMIUM_BUILD_DIRECTORY'] | |
| class GenerateCodeCacheTest(unittest.TestCase): | |
| def setUp(self): | |
| self._out_dir = tempfile.mkdtemp(dir=_HERE_DIR) | |
| def tearDown(self): | |
| shutil.rmtree(self._out_dir) | |
| def _read_file(self, path): | |
| with open(path, 'r', encoding='utf-8') as file: | |
| return file.read() | |
| def _run_test(self, in_files, extra_args=None, out_dir=None): | |
| out_dir = out_dir or self._out_dir | |
| manifest_path = os.path.join(out_dir, "manifest.json") | |
| util_path = os.path.join( # noqa: F841 | |
| _HERE_DIR, | |
| "tests", | |
| "generate_code_cache", | |
| "code_cache_generator_test_util.py", | |
| ) | |
| args = [ | |
| "--util_path", | |
| os.path.join(_BUILD_DIR, "code_cache_generator"), | |
| "--in_folder", | |
| os.path.join(_HERE_DIR, "tests", "generate_code_cache"), | |
| "--in_files", | |
| *in_files, | |
| "--out_folder", | |
| out_dir, | |
| "--out_manifest", | |
| manifest_path, | |
| *(extra_args or []), | |
| ] | |
| generate_code_cache.main(args) | |
| manifest_data = json.loads(self._read_file(manifest_path)) | |
| self.assertEqual(manifest_data['base_dir'], out_dir) | |
| for in_file in in_files: | |
| out_code_cache_file = f'{in_file}.code_cache' | |
| self.assertTrue( | |
| os.path.isfile(os.path.join(out_dir, out_code_cache_file)) | |
| ) | |
| self.assertTrue(out_code_cache_file in manifest_data['files']) | |
| def _get_snapshot_args(self): | |
| """Returns the flag that passes the build's own snapshot, or None.""" | |
| context_snapshots = glob.glob( | |
| os.path.join(_BUILD_DIR, 'v8_context_snapshot*.bin') | |
| ) | |
| if context_snapshots: | |
| return ['--context_snapshot', context_snapshots[0]] | |
| snapshot_blob = os.path.join(_BUILD_DIR, 'snapshot_blob.bin') | |
| if os.path.isfile(snapshot_blob): | |
| return ['--snapshot_blob', snapshot_blob] | |
| return None | |
| def testGenerateCodeCacheModuleBasic(self): | |
| self._run_test(["module_basic.js"]) | |
| def testGenerateCodeCacheModuleWithDeps(self): | |
| self._run_test(["module_with_deps.js"]) | |
| def testGenerateCodeCacheMultipleModules(self): | |
| self._run_test(["module_basic.js", "module_with_deps.js"]) | |
| def testGenerateCodeCacheWithExplicitSnapshot(self): | |
| # Cross builds pass the target's snapshot explicitly. Passing the build's | |
| # own snapshot must give the same cache as letting the generator load it, | |
| # since the cache embeds the snapshot's checksum. | |
| snapshot_args = self._get_snapshot_args() | |
| if not snapshot_args: | |
| self.skipTest('No external V8 snapshot in the build directory') | |
| in_files = ["module_basic.js", "module_with_deps.js"] | |
| self._run_test(in_files) | |
| explicit_out_dir = tempfile.mkdtemp(dir=_HERE_DIR) | |
| self.addCleanup(shutil.rmtree, explicit_out_dir) | |
| self._run_test(in_files, snapshot_args, explicit_out_dir) | |
| for in_file in in_files: | |
| out_file = f'{in_file}.code_cache' | |
| with ( | |
| open(os.path.join(self._out_dir, out_file), 'rb') as default_file, | |
| open(os.path.join(explicit_out_dir, out_file), 'rb') as explicit_file, | |
| ): | |
| self.assertEqual(default_file.read(), explicit_file.read(), out_file) | |
| def testSnapshotFlagsAreMutuallyExclusive(self): | |
| with self.assertRaises(SystemExit): | |
| self._run_test( | |
| ["module_basic.js"], | |
| [ | |
| '--snapshot_blob', | |
| 'snapshot_blob.bin', | |
| '--context_snapshot', | |
| 'v8_context_snapshot.bin', | |
| ], | |
| ) | |
| if __name__ == "__main__": | |
| unittest.main() |