Skip to content

Commit 57de72c

Browse files
committed
Add a bunch of unit tests for the in-house parser
1 parent 8712a92 commit 57de72c

2 files changed

Lines changed: 137 additions & 0 deletions

File tree

src/tools/collect-license-metadata/src/spdx.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,6 @@ fn build_file_entry(
9797
.ok_or_else(|| anyhow::anyhow!("file missing FileCopyrightText"))?,
9898
})
9999
}
100+
101+
#[cfg(test)]
102+
mod tests;
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
use super::*;
2+
3+
// Clause 8.1 ("File name field") specifies that each file section begins with
4+
// a `FileName` tag whose value is a relative path prefixed with "./".
5+
// Clause 8.5 ("Concluded license") and 8.8 ("Copyright text") give the
6+
// corresponding per-file fields.
7+
// <https://spdx.github.io/spdx-spec/v2.3/file-information/>
8+
#[test]
9+
fn single_file_entry() {
10+
let input = "\
11+
FileName: ./package/foo.c
12+
LicenseConcluded: LGPL-2.0-only
13+
FileCopyrightText: Copyright 2008-2010 John Smith";
14+
15+
let files = parse_tag_value(input).unwrap();
16+
assert_eq!(files.len(), 1);
17+
assert_eq!(files[0].name, "./package/foo.c");
18+
assert_eq!(files[0].concluded_license, "LGPL-2.0-only");
19+
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith");
20+
}
21+
22+
// Clause 8.5 shows compound SPDX licence expressions as valid values for
23+
// `LicenseConcluded`, e.g. "(LGPL-2.0-only OR LicenseRef-2)".
24+
// <https://spdx.github.io/spdx-spec/v2.3/file-information/>
25+
#[test]
26+
fn compound_license_expression() {
27+
let input = "\
28+
FileName: ./src/lib.rs
29+
LicenseConcluded: (LGPL-2.0-only OR LicenseRef-2)
30+
FileCopyrightText: Copyright Example Company";
31+
32+
let files = parse_tag_value(input).unwrap();
33+
assert_eq!(files.len(), 1);
34+
assert_eq!(files[0].concluded_license, "(LGPL-2.0-only OR LicenseRef-2)");
35+
}
36+
37+
// Clause 8.8 shows the copyright text wrapped in a single-line
38+
// <text>...</text> block: e.g.
39+
// `FileCopyrightText: <text>Copyright 2008-2010 John Smith</text>`
40+
// <https://spdx.github.io/spdx-spec/v2.3/file-information/>
41+
#[test]
42+
fn single_line_text_block() {
43+
let input = "\
44+
FileName: ./package/foo.c
45+
LicenseConcluded: LGPL-2.0-only
46+
FileCopyrightText: <text>Copyright 2008-2010 John Smith</text>";
47+
48+
let files = parse_tag_value(input).unwrap();
49+
assert_eq!(files.len(), 1);
50+
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith");
51+
}
52+
53+
// Clause 6.10 ("Creator comment") demonstrates a multi-line <text>...</text> block.
54+
// <https://spdx.github.io/spdx-spec/v2.3/document-creation-information/>
55+
#[test]
56+
fn multi_line_text_block() {
57+
let input = "\
58+
FileName: ./package/foo.c
59+
LicenseConcluded: MIT
60+
FileCopyrightText: <text>Copyright 2008-2010 John Smith
61+
Copyright 2019 Jane Doe</text>";
62+
63+
let files = parse_tag_value(input).unwrap();
64+
assert_eq!(files.len(), 1);
65+
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith\nCopyright 2019 Jane Doe");
66+
}
67+
68+
// Clause 5 ("Composition of an SPDX document") states that a document may
69+
// contain zero or many File Information sections. Each `FileName` tag starts
70+
// a new section, so consecutive file blocks must be parsed independently.
71+
// <https://spdx.github.io/spdx-spec/v2.3/composition-of-an-SPDX-document/>
72+
#[test]
73+
fn multiple_file_entries() {
74+
let input = "\
75+
FileName: ./package/foo.c
76+
LicenseConcluded: LGPL-2.0-only
77+
FileCopyrightText: Copyright 2008-2010 John Smith
78+
FileName: ./package/bar.c
79+
LicenseConcluded: MIT
80+
FileCopyrightText: Copyright Example Company";
81+
82+
let files = parse_tag_value(input).unwrap();
83+
assert_eq!(files.len(), 2);
84+
85+
assert_eq!(files[0].name, "./package/foo.c");
86+
assert_eq!(files[0].concluded_license, "LGPL-2.0-only");
87+
assert_eq!(files[0].copyright_text, "Copyright 2008-2010 John Smith");
88+
89+
assert_eq!(files[1].name, "./package/bar.c");
90+
assert_eq!(files[1].concluded_license, "MIT");
91+
assert_eq!(files[1].copyright_text, "Copyright Example Company");
92+
}
93+
94+
// A file section without a `LicenseConcluded` tag is malformed.
95+
#[test]
96+
fn missing_license_is_an_error() {
97+
let input = "\
98+
FileName: ./package/foo.c
99+
FileCopyrightText: Copyright 2008-2010 John Smith";
100+
101+
assert!(parse_tag_value(input).is_err());
102+
}
103+
104+
// A file section without a `FileCopyrightText` tag is malformed.
105+
#[test]
106+
fn missing_copyright_is_an_error() {
107+
let input = "\
108+
FileName: ./package/foo.c
109+
LicenseConcluded: MIT";
110+
111+
assert!(parse_tag_value(input).is_err());
112+
}
113+
114+
// A section with an unterminated <text> block (no closing </text>) is malformed.
115+
#[test]
116+
fn unterminated_text_block_is_an_error() {
117+
let input = "\
118+
FileName: ./package/foo.c
119+
LicenseConcluded: MIT
120+
FileCopyrightText: <text>Copyright 2008-2010 John Smith";
121+
122+
assert!(parse_tag_value(input).is_err());
123+
}
124+
125+
// A document with no `FileName` tags at all should produce an empty result.
126+
#[test]
127+
fn empty_document_returns_no_entries() {
128+
let input = "\
129+
SPDXVersion: SPDX-2.3
130+
DataLicense: CC0-1.0";
131+
132+
let files = parse_tag_value(input).unwrap();
133+
assert!(files.is_empty());
134+
}

0 commit comments

Comments
 (0)