fields_test.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #!/usr/bin/env vpython3
  2. # Copyright (c) 2023 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. import os
  6. import sys
  7. from typing import List
  8. import unittest
  9. _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
  10. # The repo's root directory.
  11. _ROOT_DIR = os.path.abspath(os.path.join(_THIS_DIR, "..", ".."))
  12. # Add the repo's root directory for clearer imports.
  13. sys.path.insert(0, _ROOT_DIR)
  14. import metadata.fields.known as known_fields
  15. import metadata.fields.field_types as field_types
  16. import metadata.validation_result as vr
  17. class FieldValidationTest(unittest.TestCase):
  18. def _run_field_validation(self,
  19. field: field_types.MetadataField,
  20. valid_values: List[str],
  21. error_values: List[str],
  22. warning_values: List[str] = []):
  23. """Helper to run a field's validation for different values."""
  24. for value in valid_values:
  25. self.assertIsNone(field.validate(value))
  26. for value in error_values:
  27. self.assertIsInstance(field.validate(value), vr.ValidationError)
  28. for value in warning_values:
  29. self.assertIsInstance(field.validate(value), vr.ValidationWarning)
  30. def test_freeform_text_validation(self):
  31. # Check validation of a freeform text field that should be on one line.
  32. self._run_field_validation(
  33. field=field_types.FreeformTextField("Freeform single", one_liner=True),
  34. valid_values=["Text on single line", "a", "1"],
  35. error_values=["", "\n", " "],
  36. )
  37. # Check validation of a freeform text field that can span multiple lines.
  38. self._run_field_validation(
  39. field=field_types.FreeformTextField("Freeform multi", one_liner=False),
  40. valid_values=[
  41. "This is text spanning multiple lines:\n"
  42. " * with this point\n"
  43. " * and this other point",
  44. "Text on single line",
  45. "a",
  46. "1",
  47. ],
  48. error_values=["", "\n", " "],
  49. )
  50. def test_yes_no_field_validation(self):
  51. self._run_field_validation(
  52. field=field_types.YesNoField("Yes/No test"),
  53. valid_values=["yes", "no", "No", "YES"],
  54. error_values=["", "\n", "Probably yes"],
  55. warning_values=["Yes?", "not"],
  56. )
  57. def test_cpe_prefix_validation(self):
  58. self._run_field_validation(
  59. field=known_fields.CPE_PREFIX,
  60. valid_values=[
  61. "unknown",
  62. "Cpe:2.3:a:sqlite:sqlite:3.0.0",
  63. "cpe:2.3:a:sqlite:sqlite",
  64. "CPE:/a:sqlite:sqlite:3.0.0",
  65. "cpe:/a:sqlite:sqlite",
  66. ],
  67. error_values=["", "\n"],
  68. )
  69. def test_date_validation(self):
  70. self._run_field_validation(
  71. field=known_fields.DATE,
  72. valid_values=["2012-03-04"],
  73. error_values=["", "\n", "April 3, 2012", "2012/03/04"],
  74. )
  75. def test_license_validation(self):
  76. self._run_field_validation(
  77. field=known_fields.LICENSE,
  78. valid_values=[
  79. "Apache, 2.0 / MIT / MPL 2",
  80. "LGPL 2.1",
  81. "Apache, Version 2 and Public domain",
  82. ],
  83. error_values=["", "\n", ",", "Apache 2.0 / MIT / "],
  84. warning_values=[
  85. "Custom license",
  86. "Custom / MIT",
  87. "Public domain or MPL 2",
  88. "APSL 2 and the MIT license",
  89. ],
  90. )
  91. def test_license_file_validation(self):
  92. self._run_field_validation(
  93. field=known_fields.LICENSE_FILE,
  94. valid_values=[
  95. "LICENSE", "src/LICENSE.txt",
  96. "LICENSE, //third_party_test/LICENSE-TEST", "src/MISSING_LICENSE"
  97. ],
  98. error_values=["", "\n", ","],
  99. warning_values=["NOT_SHIPPED"],
  100. )
  101. # Check relative path from README directory, and multiple license files.
  102. result = known_fields.LICENSE_FILE.validate_on_disk(
  103. value="LICENSE, src/LICENSE.txt",
  104. source_file_dir=os.path.join(_THIS_DIR, "data"),
  105. repo_root_dir=_THIS_DIR,
  106. )
  107. self.assertIsNone(result)
  108. # Check relative path from Chromium src directory.
  109. result = known_fields.LICENSE_FILE.validate_on_disk(
  110. value="//data/LICENSE",
  111. source_file_dir=os.path.join(_THIS_DIR, "data"),
  112. repo_root_dir=_THIS_DIR,
  113. )
  114. self.assertIsNone(result)
  115. # Check missing file.
  116. result = known_fields.LICENSE_FILE.validate_on_disk(
  117. value="MISSING_LICENSE",
  118. source_file_dir=os.path.join(_THIS_DIR, "data"),
  119. repo_root_dir=_THIS_DIR,
  120. )
  121. self.assertIsInstance(result, vr.ValidationError)
  122. # Check deprecated NOT_SHIPPED.
  123. result = known_fields.LICENSE_FILE.validate_on_disk(
  124. value="NOT_SHIPPED",
  125. source_file_dir=os.path.join(_THIS_DIR, "data"),
  126. repo_root_dir=_THIS_DIR,
  127. )
  128. self.assertIsInstance(result, vr.ValidationWarning)
  129. def test_url_validation(self):
  130. self._run_field_validation(
  131. field=known_fields.URL,
  132. valid_values=[
  133. "https://www.example.com/a",
  134. "http://www.example.com/b",
  135. "ftp://www.example.com/c,git://www.example.com/d",
  136. "This is the canonical public repository",
  137. ],
  138. error_values=[
  139. "",
  140. "\n",
  141. "ghttps://www.example.com/e",
  142. "https://www.example.com/ f",
  143. "Https://www.example.com/g",
  144. "This is an unrecognized message for the URL",
  145. ],
  146. )
  147. def test_version_validation(self):
  148. self._run_field_validation(
  149. field=known_fields.VERSION,
  150. valid_values=["n / a", "123abc", "unknown forked version"],
  151. error_values=["", "\n"],
  152. warning_values=["0", "unknown"],
  153. )
  154. if __name__ == "__main__":
  155. unittest.main()