#!/usr/bin/env vpython3 # Copyright 2020 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import base64 import json import os import shutil import tempfile import unittest import merge_js_lib as merger from parameterized import parameterized class MergeJSLibTest(unittest.TestCase): def test_write_parsed_scripts(self): test_files = [{ 'url': '//a/b/c/1.js', 'location': ['a', 'b', 'c', '1.js'], 'exists': True }, { 'url': '//d/e/f/5.js', 'location': ['d', 'e', 'f', '5.js'], 'exists': True }, { 'url': '//a/b/d/7.js', 'location': ['a', 'b', 'd', '7.js'], 'exists': True }, { 'url': 'chrome://test_webui/file.js', 'exists': False }, { 'url': 'file://testing/file.js', 'exists': False }] test_script_file = """{ "text": "test\\ncontents\\n%d", "url": "%s", "sourceMapURL":"%s" }""" scripts_dir = None expected_files = [] try: scripts_dir = tempfile.mkdtemp() for i, test_script in enumerate(test_files): file_path = os.path.join(scripts_dir, '%d.js.json' % i) source_map = "" if test_script['exists']: # Create an inline sourcemap with just the required keys. source_map_data_url = base64.b64encode( json.dumps({ "sources": [os.path.join(*test_script['location'])], "sourceRoot": "" }).encode('utf-8')) source_map = 'data:application/json;base64,' + \ source_map_data_url.decode('utf-8') with open(file_path, 'w') as f: f.write(test_script_file % (i, test_script['url'], source_map)) expected_files.append(file_path) if test_script['exists']: expected_files.append( os.path.join(scripts_dir, 'parsed_scripts', *test_script['location'])) if len(expected_files) > 0: expected_files.append( os.path.join(scripts_dir, 'parsed_scripts', 'parsed_scripts.json')) merger.write_parsed_scripts(scripts_dir, source_dir='') actual_files = [] for root, _, files in os.walk(scripts_dir): for file_name in files: actual_files.append(os.path.join(root, file_name)) self.assertCountEqual(expected_files, actual_files) finally: shutil.rmtree(scripts_dir) def test_write_parsed_scripts_negative_cases(self): test_files = [{ 'url': '//a/b/c/1.js', 'contents': """{ "url": "%s" }""" }, { 'url': '//d/e/f/1.js', 'contents': """{ "text": "test\\ncontents\\n%s" }""" }] scripts_dir = None expected_files = [] try: scripts_dir = tempfile.mkdtemp() for i, test_script in enumerate(test_files): file_path = os.path.join(scripts_dir, '%d.js.json' % i) expected_files.append(file_path) with open(file_path, 'w') as f: f.write(test_script['contents'] % test_script['url']) merger.write_parsed_scripts(scripts_dir) actual_files = [] for root, _, files in os.walk(scripts_dir): for file_name in files: actual_files.append(os.path.join(root, file_name)) self.assertCountEqual(expected_files, actual_files) finally: shutil.rmtree(scripts_dir) def test_non_data_urls_are_ignored(self): test_script_file = """{ "text": "test\\ncontents", "url": "http://test_url", "sourceMapURL":"%s" }""" scripts_dir = None expected_files = [] try: scripts_dir = tempfile.mkdtemp() file_path = os.path.join(scripts_dir, 'external_map.js.json') expected_files = [file_path] # Write a script with an external URL as the sourcemap, this should # exclude it from being written to disk. with open(file_path, 'w') as f: f.write(test_script_file % 'external.map') merger.write_parsed_scripts(scripts_dir, source_dir='') actual_files = [] for root, _, files in os.walk(scripts_dir): for file_name in files: actual_files.append(os.path.join(root, file_name)) self.assertCountEqual(expected_files, actual_files) finally: shutil.rmtree(scripts_dir) def test_uninteresting_lines_are_excluded(self): """This contrived istanbul coverage file represents the coverage from the following example file: """ example_test_file = """// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import './iframe.js'; /* * function comment should be excluded. */ export const add = (a, b) => a + b; // should not be excluded /* should be excluded */ """ test_istanbul_file = """{ "%s":{ "path":"%s", "all":false, "statementMap":{ "1":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, "2":{"start":{"line":2,"column":0},"end":{"line":2,"column":73}}, "3":{"start":{"line":3,"column":0},"end":{"line":3,"column":29}}, "4":{"start":{"line":4,"column":0},"end":{"line":4,"column":0}}, "5":{"start":{"line":5,"column":0},"end":{"line":5,"column":21}}, "6":{"start":{"line":6,"column":0},"end":{"line":6,"column":0}}, "7":{"start":{"line":7,"column":0},"end":{"line":7,"column":2}}, "8":{"start":{"line":8,"column":0},"end":{"line":8,"column":39}}, "9":{"start":{"line":9,"column":0},"end":{"line":9,"column":3}}, "10":{"start":{"line":10,"column":0},"end":{"line":10,"column":61}}, "11":{"start":{"line":11,"column":0},"end":{"line":11,"column":0}}, "12":{"start":{"line":12,"column":0},"end":{"line":12,"column":24}}, "13":{"start":{"line":13,"column":0},"end":{"line":13,"column":0}} }, "s":{ "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1, "11": 1, "12": 1, "13": 1 } } }""" expected_output_file = """{ "%s": { "path": "%s", "all": false, "statementMap": { "10": { "start": { "line": 10, "column": 0 }, "end": { "line": 10, "column": 61 } } }, "s": { "10": 1 } } }""" try: test_dir = tempfile.mkdtemp() file_path = os.path.join(test_dir, 'coverage.json').replace('\\', '/') example_test_file_path = os.path.join(test_dir, 'fileA.js').replace( '\\', '/') expected_output = json.loads( expected_output_file % (example_test_file_path, example_test_file_path)) # Set up the tests files so that exclusions can be performed. with open(file_path, 'w') as f: f.write(test_istanbul_file % (example_test_file_path, example_test_file_path)) with open(example_test_file_path, 'w') as f: f.write(example_test_file) # Perform the exclusion. merger.exclude_uninteresting_lines(file_path) # Assert the final `coverage.json` file matches the expected output. with open(file_path, 'rb') as f: coverage_json = json.load(f) self.assertEqual(coverage_json, expected_output) finally: shutil.rmtree(test_dir) def test_paths_are_remapped_and_removed(self): test_file_data = """{ "/path/to/checkout/chrome/browser/fileA.js": { "path": "/path/to/checkout/chrome/browser/fileA.js" }, "/path/to/checkout/out/dir/chrome/browser/fileB.js": { "path": "/path/to/checkout/out/dir/chrome/browser/fileB.js" }, "/some/random/path/fileC.js": { "path": "/some/random/path/fileC.js" } }""" expected_after_remap = { "chrome/browser/fileA.js": { "path": "chrome/browser/fileA.js" } } try: test_dir = tempfile.mkdtemp() coverage_file_path = os.path.join(test_dir, 'coverage.json').replace( '\\', '/') with open(coverage_file_path, 'w', encoding='utf-8', newline='') as f: f.write(test_file_data) merger.remap_paths_to_relative(coverage_file_path, "/path/to/checkout", "/path/to/checkout/out/dir") with open(coverage_file_path, 'rb') as f: coverage_json = json.load(f) self.assertEqual(coverage_json, expected_after_remap) finally: shutil.rmtree(test_dir) @parameterized.expand([ ('// test', True), ('/* test', True), ('*/ test', True), (' * test', True), ('import test', True), (' x = 5 /* comment */', False), ('x = 5', False), ]) def test_should_exclude(self, line, exclude): self.assertEqual(merger.should_exclude(line), exclude) if __name__ == '__main__': unittest.main()