123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #!/usr/bin/env python3
- # Copyright 2023 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- import os
- import sys
- import unittest
- import unittest.mock
- _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
- # The repo's root directory.
- _ROOT_DIR = os.path.abspath(os.path.join(_THIS_DIR, "..", ".."))
- # Add the repo's root directory for clearer imports.
- sys.path.insert(0, _ROOT_DIR)
- import gclient_utils
- import metadata.validate
- import metadata.validation_result
- import metadata.fields.known
- # Common paths for tests.
- _SOURCE_FILE_DIR = os.path.join(_THIS_DIR, "data")
- _VALID_METADATA_FILEPATH = os.path.join(_THIS_DIR, "data",
- "README.chromium.test.multi-valid")
- _INVALID_METADATA_FILEPATH = os.path.join(_THIS_DIR, "data",
- "README.chromium.test.multi-invalid")
- class ValidateContentTest(unittest.TestCase):
- """Tests for the validate_content function."""
- def test_empty(self):
- # Validate empty content (should result in a validation error).
- results = metadata.validate.validate_content(
- content="",
- source_file_dir=_SOURCE_FILE_DIR,
- repo_root_dir=_THIS_DIR,
- )
- self.assertEqual(len(results), 1)
- self.assertTrue(results[0].is_fatal())
- def test_valid(self):
- # Validate valid file content (no errors or warnings).
- results = metadata.validate.validate_content(
- content=gclient_utils.FileRead(_VALID_METADATA_FILEPATH),
- source_file_dir=_SOURCE_FILE_DIR,
- repo_root_dir=_THIS_DIR,
- )
- self.assertEqual(len(results), 0)
- def test_invalid(self):
- # Validate invalid file content (both errors and warnings).
- results = metadata.validate.validate_content(
- content=gclient_utils.FileRead(_INVALID_METADATA_FILEPATH),
- source_file_dir=_SOURCE_FILE_DIR,
- repo_root_dir=_THIS_DIR,
- )
- self.assertEqual(len(results), 9)
- error_count = 0
- warning_count = 0
- for result in results:
- if result.is_fatal():
- error_count += 1
- else:
- warning_count += 1
- self.assertEqual(error_count, 7)
- self.assertEqual(warning_count, 2)
- class ValidateFileTest(unittest.TestCase):
- """Tests for the validate_file function."""
- def test_missing(self):
- # Validate a file that does not exist.
- results = metadata.validate.validate_file(
- filepath=os.path.join(_THIS_DIR, "data", "MISSING.chromium"),
- repo_root_dir=_THIS_DIR,
- )
- # There should be exactly 1 error returned.
- self.assertEqual(len(results), 1)
- self.assertTrue(results[0].is_fatal())
- def test_valid(self):
- # Validate a valid file (no errors or warnings).
- results = metadata.validate.validate_file(
- filepath=_VALID_METADATA_FILEPATH,
- repo_root_dir=_THIS_DIR,
- )
- self.assertEqual(len(results), 0)
- def test_invalid(self):
- # Validate an invalid file (both errors and warnings).
- results = metadata.validate.validate_file(
- filepath=_INVALID_METADATA_FILEPATH,
- repo_root_dir=_THIS_DIR,
- )
- self.assertEqual(len(results), 9)
- error_count = 0
- warning_count = 0
- for result in results:
- if result.is_fatal():
- error_count += 1
- else:
- warning_count += 1
- self.assertEqual(error_count, 7)
- self.assertEqual(warning_count, 2)
- class CheckFileTest(unittest.TestCase):
- """Tests for the check_file function."""
- def test_missing(self):
- # Check a file that does not exist.
- errors, warnings = metadata.validate.check_file(
- filepath=os.path.join(_THIS_DIR, "data", "MISSING.chromium"),
- repo_root_dir=_THIS_DIR,
- )
- # TODO(aredulla): update this test once validation errors can be
- # returned as errors. Bug: b/285453019.
- # self.assertEqual(len(errors), 1)
- # self.assertEqual(len(warnings), 0)
- self.assertEqual(len(errors), 0)
- self.assertEqual(len(warnings), 1)
- def test_valid(self):
- # Check file with valid content (no errors or warnings).
- errors, warnings = metadata.validate.check_file(
- filepath=_VALID_METADATA_FILEPATH,
- repo_root_dir=_THIS_DIR,
- )
- self.assertEqual(len(errors), 0)
- self.assertEqual(len(warnings), 0)
- def test_invalid(self):
- # Check file with invalid content (both errors and warnings).
- errors, warnings = metadata.validate.check_file(
- filepath=_INVALID_METADATA_FILEPATH,
- repo_root_dir=_THIS_DIR,
- )
- # TODO(aredulla): update this test once validation errors can be
- # returned as errors. Bug: b/285453019.
- # self.assertEqual(len(errors), 7)
- # self.assertEqual(len(warnings), 2)
- self.assertEqual(len(errors), 0)
- self.assertEqual(len(warnings), 9)
- class ValidationResultTest(unittest.TestCase):
- """Tests ValidationResult handles strings correctly."""
- def test_ordering(self):
- ve = metadata.validation_result.ValidationError(
- "abc",
- ["message1", "message2"],
- )
- vw = metadata.validation_result.ValidationError(
- "def",
- ["message3", "message4"],
- )
- # Check errors preceeds warnings.
- self.assertLess(ve, vw)
- self.assertGreater(vw, ve)
- self.assertEqual([ve, vw], list(sorted([vw, ve])))
- def test_message_generation(self):
- ve = metadata.validation_result.ValidationError(
- "abc",
- ["message1", "message2"],
- )
- self.assertEqual(
- ("Third party metadata issue: abc message1 message2 Check "
- "//third_party/README.chromium.template for details."),
- ve.get_message())
- self.assertEqual("abc message1 message2",
- ve.get_message(prescript='', postscript=''))
- def test_getters(self):
- ve = metadata.validation_result.ValidationError(
- "abc",
- ["message1", "message2"],
- )
- self.assertEqual("abc", ve.get_reason())
- self.assertEqual(["message1", "message2"], ve.get_additional())
- class ValidationWithLineNumbers(unittest.TestCase):
- def test_reports_line_number(self):
- """Checks validate reports line number if available."""
- filepath = os.path.join(_THIS_DIR, "data",
- "README.chromium.test.validation-line-number")
- content = gclient_utils.FileRead(filepath)
- unittest.mock.patch(
- 'metadata.fields.known.LICENSE_FILE.validate_on_disk',
- return_value=metadata.validation_result.ValidationError(
- "File doesn't exist."))
- results = metadata.validate.validate_content(content,
- "chromium/src/test_dir",
- "chromium/src")
- for r in results:
- if r.get_reason() == 'License File is invalid.':
- self.assertEqual(r.get_lines(), [10])
- elif r.get_reason(
- ) == "Required field 'License Android Compatible' is missing.":
- # We can't add a line number to errors caused by missing fields.
- self.assertEqual(r.get_lines(), [])
- elif r.get_reason() == "Versioning fields are insufficient.":
- # We can't add a line number to errors caused by missing fields.
- self.assertEqual(r.get_lines(), [])
- elif r.get_reason(
- ) == "License has a license not in the allowlist.":
- self.assertEqual(r.get_lines(), [9])
- elif r.get_reason() == "URL is invalid.":
- self.assertEqual(r.get_lines(), [2, 3, 4])
- elif r.get_reason() == "Shipped in Chromium is invalid":
- self.assertEqual(r.get_lines(), [13])
- if __name__ == "__main__":
- unittest.main()
|