Skip to content

Commit 466e375

Browse files
committed
Add unit tests
Signed-off-by: akugarg <[email protected]>
1 parent a84b1ed commit 466e375

File tree

3 files changed

+81
-12
lines changed

3 files changed

+81
-12
lines changed

src/licensedcode/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,10 @@ def validate(self, licensing=None):
953953
except InvalidRule as e:
954954
yield f'Failed to parse and validate license_expression: {e}'
955955

956+
if self.referenced_filenames:
957+
if len(set(self.referenced_filenames)) != len(self.referenced_filenames):
958+
yield 'referenced_filenames cannot contain duplicates.'
959+
956960
def license_keys(self, unique=True):
957961
"""
958962
Return a list of license keys for this rule.

src/licensedcode/plugin_license.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ def process_codebase(self, codebase, **kwargs):
129129

130130
def match_reference_license(resource, codebase):
131131
"""
132-
Return the updated license matches having reference to another files
132+
Return the ``resource`` Resource updating and saving it in place, after adding new
133+
icense matches (licenses and license_expressions) following their Rule
134+
``referenced_filenames`` if any. Return None if this is not a file Resource.
133135
"""
134136
if not resource.is_file:
135137
return
@@ -141,29 +143,43 @@ def match_reference_license(resource, codebase):
141143

142144
referenced_licenses = []
143145
referenced_license_expressions = []
144-
referenced_filenames = []
145-
146-
for license in licenses:
147-
referenced_files = license['matched_rule']['referenced_filenames']
148-
for referenced_filename in referenced_files:
149-
if not referenced_filename in referenced_filenames:
150-
referenced_filenames.append(referenced_filename)
146+
referenced_filenames = get_referenced_filenames(licenses)
147+
modified = False
151148

152149
for referenced_filename in referenced_filenames:
153-
new_resource = find_reference_licenses(referenced_filename=referenced_filename, resource=resource, codebase=codebase)
150+
new_resource = find_referenced_resource(referenced_filename=referenced_filename, resource=resource, codebase=codebase)
154151
if new_resource:
152+
modified = True
155153
referenced_licenses.extend(new_resource.licenses)
156154
referenced_license_expressions.extend(new_resource.license_expressions)
157155

158156
licenses.extend(referenced_licenses)
159157
license_expressions.extend(referenced_license_expressions)
160-
codebase.save_resource(resource)
158+
159+
if modified:
160+
codebase.save_resource(resource)
161161
return resource
162162

163163

164-
def find_reference_licenses(referenced_filename, resource, codebase, **kwargs):
164+
def get_referenced_filenames(license_matches):
165+
"""
166+
Return a list of unique referenced filenames found in the rules of a list of ``license_matches``
167+
"""
168+
referenced_filenames = []
169+
for license_match in license_matches:
170+
referenced_files = license_match['matched_rule']['referenced_filenames']
171+
for referenced_filename in referenced_files:
172+
if not referenced_filename in referenced_filenames:
173+
referenced_filenames.append(referenced_filename)
174+
175+
return referenced_filenames
176+
177+
178+
def find_referenced_resource(referenced_filename, resource, codebase, **kwargs):
165179
"""
166-
Return the resource object for matching referenced-filename given a resource in codebase
180+
Return a Resource matching the ``referenced_filename`` path or filename given a ``resource`` in ``codebase``.
181+
Return None if the ``referenced_filename`` cannot be found in the same directory as the base ``resource``.
182+
``referenced_filename`` is the path or filename referenced in a LicenseMatch of ``resource``,
167183
"""
168184
parent = resource.parent(codebase)
169185

tests/licensedcode/test_plugin_license.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
import os
1111

12+
from click.testing import Result
13+
from licensedcode.plugin_license import find_referenced_resource, match_reference_license
14+
from licensedcode.plugin_license import get_referenced_filenames
15+
1216
import pytest
1317

1418
from commoncode.testcase import FileDrivenTesting
@@ -67,6 +71,7 @@ def test_license_option_reports_license_texts_diag_long_lines():
6771
test_loc = test_env.get_test_loc('plugin_license/text_long_lines/scan-diag.expected.json')
6872
check_json_scan(test_loc, result_file, regen=False)
6973

74+
7075
def test_license_match_reference():
7176
test_dir = test_env.get_test_loc('plugin_license/license_reference/scan/scan-ref', copy=True)
7277
result_file = test_env.get_temp_file('json')
@@ -75,6 +80,7 @@ def test_license_match_reference():
7580
test_loc = test_env.get_test_loc('plugin_license/license_reference/scan-ref.expected.json')
7681
check_json_scan(test_loc, result_file, regen=False)
7782

83+
7884
def test_license_match_without_reference():
7985
test_dir = test_env.get_test_loc('plugin_license/license_reference/scan/scan-without-ref', copy=True)
8086
result_file = test_env.get_temp_file('json')
@@ -83,6 +89,49 @@ def test_license_match_without_reference():
8389
test_loc = test_env.get_test_loc('plugin_license/license_reference/scan-wref.expected.json')
8490
check_json_scan(test_loc, result_file, regen=False)
8591

92+
93+
def test_get_referenced_filenames():
94+
license_matches = [
95+
{'matched_rule': {'referenced_filenames' : ['LICENSE.txt','COPYING']}},
96+
{'matched_rule': {'referenced_filenames' : ['COPYING','LICENSE.txt']}},
97+
{'matched_rule': {'referenced_filenames' : ['copying']}},
98+
{'matched_rule': {'referenced_filenames' : []}},
99+
]
100+
expected = ['LICENSE.txt','COPYING','copying']
101+
assert get_referenced_filenames(license_matches) == expected
102+
103+
104+
def test_find_referenced_resource():
105+
# Setup: Create a new scan to use for a virtual codebase
106+
test_dir = test_env.get_test_loc('plugin_license/license_reference/scan/scan-ref', copy=True)
107+
scan_loc = test_env.get_temp_file('json')
108+
args = ['--license', '--license-text', '--license-text-diagnostics', test_dir, '--json', scan_loc]
109+
run_scan_click(args)
110+
111+
# test proper
112+
from commoncode.resource import VirtualCodebase
113+
codebase = VirtualCodebase(scan_loc)
114+
resource = codebase.get_resource_from_path('scan-ref/license-notice.txt')
115+
result = find_referenced_resource(referenced_filename='LICENSE',resource=resource, codebase=codebase)
116+
assert result.path == 'scan-ref/LICENSE'
117+
118+
119+
def test_match_reference_license():
120+
# Setup: Create a new scan to use for a virtual codebase
121+
test_dir = test_env.get_test_loc('plugin_license/license_reference/scan/scan-ref', copy=True)
122+
scan_loc = test_env.get_temp_file('json')
123+
args = ['--license', '--license-text', '--license-text-diagnostics', test_dir, '--json', scan_loc]
124+
run_scan_click(args)
125+
126+
# test proper
127+
from commoncode.resource import VirtualCodebase
128+
codebase = VirtualCodebase(scan_loc)
129+
resource = codebase.get_resource_from_path('scan-ref/license-notice.txt')
130+
assert len(resource.licenses) == 2
131+
result = match_reference_license(resource=resource, codebase=codebase)
132+
assert len(result.licenses) == 3
133+
134+
86135
def test_reindex_licenses_works():
87136
args = ['--reindex-licenses']
88137
run_scan_click(args)

0 commit comments

Comments
 (0)