xref: /aosp_15_r20/external/bazelbuild-rules_license/tests/license_test_utils.py (revision f578df4fd057ffe2023728444759535685631548)
1"""Utilities for writing tests of license rules."""
2
3import codecs
4import json
5
6# This is extracted out to make it easier to keep test equivalence between
7# the OSS version and Google.
8LICENSE_PACKAGE_BASE = "/"
9
10
11def load_licenses_info(info_path):
12  """Loads the licenses_info() JSON format."""
13  with codecs.open(info_path, encoding="utf-8") as licenses_file:
14    return json.loads(licenses_file.read())
15
16
17def filter_dependencies(licenses_info, target_filter=None,
18                        licenses_filter=None):
19  """Filters licenses_info to only include dependencies of interest.
20
21  Args:
22    licenses_info: (dict) licenses info.
23    target_filter: (function): function which returns true if we should include
24        the target.
25    licenses_filter: (function): function which returns true if we should
26        include the license.
27  Returns:
28    (dict) a valid licenses_info dict.
29  """
30  top_target = licenses_info[0]
31  new_top_target = dict(top_target)
32  new_deps = []
33  for dep in top_target["dependencies"]:
34    target_name = dep["target_under_license"]
35    if target_filter and not target_filter(target_name):
36      continue
37    licenses = dep["licenses"]
38    if licenses_filter:
39      licenses = [lic for lic in licenses if licenses_filter(lic)]
40    new_deps.append({
41        "target_under_license": target_name,
42        "licenses": licenses})
43  new_top_target["dependencies"] = new_deps
44  return [new_top_target]
45
46
47def check_licenses_of_dependencies(test_case, licenses_info, expected,
48                                   path_prefix=LICENSE_PACKAGE_BASE):
49  """Checks that licenses_info contains an expected set of licenses.
50
51  Args:
52    test_case: (TestCase) the test.
53    licenses_info: (dict) licenses info.
54    expected: (dict) map of target name suffixes to the licenses they are under.
55    path_prefix: (str) prefix to prepend to targets and licenses in expected.
56       This turns the relative target names to absolute ones.
57  """
58
59  # Turn the list of deps into a dict by target for easier comparison.
60  deps_to_licenses = {
61      x["target_under_license"].lstrip("@"): set(l.strip("@") for l in x["licenses"])
62      for x in licenses_info[0]["dependencies"]}
63
64  target_names = ",".join(deps_to_licenses.keys())
65  # This is n**2, but N is typically < 3 or we are doing this wrong.
66  for want_target, want_licenses in expected.items():
67    found_target = False
68    for got_target, got_licenses in deps_to_licenses.items():
69      if got_target.endswith(want_target):
70        found_target = True
71        test_case.assertEqual(len(want_licenses), len(got_licenses))
72        found_license = False
73        for want_l in want_licenses:
74          for got_l in got_licenses:
75            if got_l.endswith(want_l):
76              found_license = True
77              break
78        test_case.assertTrue(
79            found_license,
80            msg="license (%s) not a suffix in %s" % (want_l, got_licenses))
81        break
82    test_case.assertTrue(
83        found_target,
84        msg="target (%s) not a suffix in [%s]" % (want_target, target_names))
85