Skip to content

Commit f2854a9

Browse files
authored
Updated license comparison logic for sequence failures (#159)
* Refactor license comparison * Updated license comparison logic to ignore sequence failures * Update test case related to normalizeLicenseExpression function * Refactor and rename file comparison function
1 parent 6b79d27 commit f2854a9

File tree

5 files changed

+146
-7
lines changed

5 files changed

+146
-7
lines changed

tools/integration/lib/compareDefinitions.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// (c) Copyright 2024, GitHub and ClearlyDefined contributors. Licensed under the MIT license.
22
// SPDX-License-Identifier: MIT
33

4+
const SPDX = require('@clearlydefined/spdx')
45
function compareDocuments(staging, production, ignoredKeys, path = '') {
56
let differences = {}
67
let overallResults = []
@@ -215,4 +216,8 @@ function getType(value) {
215216
return typeof value
216217
}
217218

218-
module.exports = { compareDocuments }
219+
function normalizeLicenseExpression(license) {
220+
return license ? SPDX.expand(license).sort() : license
221+
}
222+
223+
module.exports = { compareDocuments, normalizeLicenseExpression }

tools/integration/package-lock.json

Lines changed: 75 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/integration/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"typescript": "^5.8.3"
3434
},
3535
"dependencies": {
36+
"@clearlydefined/spdx": "^0.1.7",
3637
"@octokit/rest": "^21.1.1",
3738
"async-retry": "^1.3.3"
3839
}

tools/integration/test/integration/e2e-test-service/definitionTest.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const { devApiBaseUrl, prodApiBaseUrl, getComponents, definition, fetchRetry } =
88
const nock = require('nock')
99
const fs = require('fs')
1010
const callFetch = createFetcherWithRetry(fetchRetry)
11+
const { normalizeLicenseExpression } = require('../../../lib/compareDefinitions')
1112

1213
;(async function () {
1314
const components = await getComponents()
@@ -89,10 +90,12 @@ function compareDefinition(recomputedDef, expectedDef) {
8990
}
9091

9192
function compareLicensed(result, expectation) {
92-
let actual = omit(result.licensed, ['facets'])
93-
let expected = omit(expectation.licensed, ['facets'])
94-
actual = { declared: undefined, ...actual }
95-
expected = { declared: undefined, ...expected }
93+
deepStrictEqual(
94+
normalizeLicenseExpression(result.licensed.declared),
95+
normalizeLicenseExpression(expectation.licensed.declared)
96+
)
97+
let actual = omit(result.licensed, ['facets', 'declared'])
98+
let expected = omit(expectation.licensed, ['facets', 'declared'])
9699
deepStrictEqualExpectedEntries(actual, expected)
97100
}
98101

@@ -107,13 +110,21 @@ function deepStrictEqualExpectedEntries(actual, expected) {
107110
deepStrictEqual(pickedActual, expected)
108111
}
109112

113+
function isFileEqual(expectedFiles, f) {
114+
const expected = expectedFiles.get(f.path)
115+
const isLicenseEqual = isEqual(normalizeLicenseExpression(f.license), normalizeLicenseExpression(expected.license))
116+
if (!isLicenseEqual) return false
117+
const normResult = omit(f, ['license'])
118+
const normExpect = omit(expected, ['license'])
119+
return isEqual(normResult, normExpect)
120+
}
121+
110122
function compareFiles(result, expectation) {
111123
const resultFiles = filesToMap(result)
112124
const expectedFiles = filesToMap(expectation)
113125
const extraInResult = result.files.filter(f => !expectedFiles.has(f.path))
114126
const missingInResult = expectation.files.filter(f => !resultFiles.has(f.path))
115-
const differentEntries = result.files.filter(f => expectedFiles.has(f.path) && !isEqual(expectedFiles.get(f.path), f))
116-
127+
const differentEntries = result.files.filter(f => expectedFiles.has(f.path) && !isFileEqual(expectedFiles, f))
117128
const differences = [...extraInResult, ...missingInResult, ...differentEntries]
118129
differences.forEach(f => logDifferences(expectedFiles.get(f.path), resultFiles.get(f.path)))
119130

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const assert = require('assert')
2+
const { normalizeLicenseExpression } = require('../../lib/compareDefinitions')
3+
4+
describe('normalizeLicenseExpression', () => {
5+
it('should treat (MIT OR Apache-2.0) and (Apache-2.0 OR MIT) as equivalent', () => {
6+
assert.deepStrictEqual(
7+
normalizeLicenseExpression('(MIT OR Apache-2.0)'),
8+
normalizeLicenseExpression('(Apache-2.0 OR MIT)')
9+
)
10+
})
11+
12+
it('should treat ( LGPL-2.1-only OR MIT) AND Apache-2.0 and ( MIT OR LGPL-2.1-only) AND Apache-2.0 as equivalent', () => {
13+
const actual1 = '( LGPL-2.1-only OR MIT) AND Apache-2.0'
14+
const expected1 = '( MIT OR LGPL-2.1-only) AND Apache-2.0'
15+
assert.deepStrictEqual(normalizeLicenseExpression(actual1), normalizeLicenseExpression(expected1))
16+
})
17+
18+
it('should treat (LGPL-2.1-only OR MIT) AND Apache-2.0 and (LGPL-2.1-only OR MIT) AND Apache-2.0 as equivalent', () => {
19+
const actual2 = '(LGPL-2.1-only OR MIT) AND Apache-2.0'
20+
const expected2 = '(LGPL-2.1-only OR MIT) AND Apache-2.0'
21+
assert.deepStrictEqual(normalizeLicenseExpression(actual2), normalizeLicenseExpression(expected2))
22+
})
23+
24+
it('should treat (LGPL-2.1-only OR MIT) OR Apache-2.0 and (MIT OR LGPL-2.1-only) OR Apache-2.0 as equivalent', () => {
25+
const actual3 = '(LGPL-2.1-only OR MIT) OR Apache-2.0'
26+
const expected3 = '(MIT OR LGPL-2.1-only) OR Apache-2.0'
27+
assert.deepStrictEqual(normalizeLicenseExpression(actual3), normalizeLicenseExpression(expected3))
28+
})
29+
30+
it('should treat (LGPL-2.1-only OR Apache-2.0) OR MIT and (MIT OR LGPL-2.1-only) OR Apache-2.0 as equivalent', () => {
31+
const actual4 = '(LGPL-2.1-only OR Apache-2.0) OR MIT'
32+
const expected4 = '(MIT OR LGPL-2.1-only) OR Apache-2.0'
33+
assert.deepStrictEqual(normalizeLicenseExpression(actual4), normalizeLicenseExpression(expected4))
34+
})
35+
36+
it('should treat ( LGPL-2.1-only OR MIT) AND Apache-2.0 and Apache-2.0 AND ( MIT OR LGPL-2.1-only) as equivalent', () => {
37+
const actual6 = '( LGPL-2.1-only OR MIT) AND Apache-2.0'
38+
const expected6 = 'Apache-2.0 AND ( MIT OR LGPL-2.1-only)'
39+
assert.deepStrictEqual(normalizeLicenseExpression(actual6), normalizeLicenseExpression(expected6))
40+
})
41+
42+
it('should NOT treat (LGPL-2.1-only OR Apache-2.0) AND MIT and (MIT OR LGPL-2.1-only) OR Apache-2.0 as equivalent', () => {
43+
const actual5 = '(LGPL-2.1-only OR Apache-2.0) AND MIT'
44+
const expected5 = '(MIT OR LGPL-2.1-only) OR Apache-2.0'
45+
assert.notDeepStrictEqual(normalizeLicenseExpression(actual5), normalizeLicenseExpression(expected5))
46+
})
47+
})

0 commit comments

Comments
 (0)