• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2package parser2v2
3
4import (
5	"testing"
6
7	"github.com/spdx/tools-golang/spdx/v2_2"
8)
9
10// ===== Parser creation info state change tests =====
11func TestParser2_2CIMovesToPackageAfterParsingPackageNameTag(t *testing.T) {
12	parser := tvParser2_2{
13		doc: &v2_2.Document{},
14		st:  psCreationInfo2_2,
15	}
16	pkgName := "testPkg"
17	err := parser.parsePair2_2("PackageName", pkgName)
18	if err != nil {
19		t.Errorf("got error when calling parsePair2_2: %v", err)
20	}
21	// state should be correct
22	if parser.st != psPackage2_2 {
23		t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_2)
24	}
25	// and a package should be created
26	if parser.pkg == nil {
27		t.Fatalf("parser didn't create new package")
28	}
29	// and the package name should be as expected
30	if parser.pkg.PackageName != pkgName {
31		t.Errorf("expected package name %s, got %s", pkgName, parser.pkg.PackageName)
32	}
33	// and the package should default to true for FilesAnalyzed
34	if parser.pkg.FilesAnalyzed != true {
35		t.Errorf("expected FilesAnalyzed to default to true, got false")
36	}
37	if parser.pkg.IsFilesAnalyzedTagPresent != false {
38		t.Errorf("expected IsFilesAnalyzedTagPresent to default to false, got true")
39	}
40	// and the package should NOT be in the SPDX Document's map of packages,
41	// because it doesn't have an SPDX identifier yet
42	if len(parser.doc.Packages) != 0 {
43		t.Errorf("expected 0 packages, got %d", len(parser.doc.Packages))
44	}
45}
46
47func TestParser2_2CIMovesToFileAfterParsingFileNameTagWithNoPackages(t *testing.T) {
48	parser := tvParser2_2{
49		doc: &v2_2.Document{},
50		st:  psCreationInfo2_2,
51	}
52	err := parser.parsePair2_2("FileName", "testFile")
53	if err != nil {
54		t.Errorf("got error when calling parsePair2_2: %v", err)
55	}
56	// state should be correct
57	if parser.st != psFile2_2 {
58		t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_2)
59	}
60	// and current package should be nil, meaning Files are placed in the
61	// Files map instead of in a Package
62	if parser.pkg != nil {
63		t.Fatalf("expected pkg to be nil, got non-nil pkg")
64	}
65}
66
67func TestParser2_2CIMovesToOtherLicenseAfterParsingLicenseIDTag(t *testing.T) {
68	parser := tvParser2_2{
69		doc: &v2_2.Document{},
70		st:  psCreationInfo2_2,
71	}
72	err := parser.parsePair2_2("LicenseID", "LicenseRef-TestLic")
73	if err != nil {
74		t.Errorf("got error when calling parsePair2_2: %v", err)
75	}
76	if parser.st != psOtherLicense2_2 {
77		t.Errorf("parser is in state %v, expected %v", parser.st, psOtherLicense2_2)
78	}
79}
80
81func TestParser2_2CIMovesToReviewAfterParsingReviewerTag(t *testing.T) {
82	parser := tvParser2_2{
83		doc: &v2_2.Document{},
84		st:  psCreationInfo2_2,
85	}
86	err := parser.parsePair2_2("Reviewer", "Person: John Doe")
87	if err != nil {
88		t.Errorf("got error when calling parsePair2_2: %v", err)
89	}
90	if parser.st != psReview2_2 {
91		t.Errorf("parser is in state %v, expected %v", parser.st, psReview2_2)
92	}
93}
94
95func TestParser2_2CIStaysAfterParsingRelationshipTags(t *testing.T) {
96	parser := tvParser2_2{
97		doc: &v2_2.Document{},
98		st:  psCreationInfo2_2,
99	}
100
101	err := parser.parsePair2_2("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-else")
102	if err != nil {
103		t.Errorf("got error when calling parsePair2_2: %v", err)
104	}
105	if parser.st != psCreationInfo2_2 {
106		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
107	}
108
109	err = parser.parsePair2_2("RelationshipComment", "blah")
110	if err != nil {
111		t.Errorf("got error when calling parsePair2_2: %v", err)
112	}
113	if parser.st != psCreationInfo2_2 {
114		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
115	}
116}
117
118func TestParser2_2CIStaysAfterParsingAnnotationTags(t *testing.T) {
119	parser := tvParser2_2{
120		doc: &v2_2.Document{},
121		st:  psCreationInfo2_2,
122	}
123
124	err := parser.parsePair2_2("Annotator", "Person: John Doe ()")
125	if err != nil {
126		t.Errorf("got error when calling parsePair2_2: %v", err)
127	}
128	if parser.st != psCreationInfo2_2 {
129		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
130	}
131
132	err = parser.parsePair2_2("AnnotationDate", "2018-09-15T00:36:00Z")
133	if err != nil {
134		t.Errorf("got error when calling parsePair2_2: %v", err)
135	}
136	if parser.st != psCreationInfo2_2 {
137		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
138	}
139
140	err = parser.parsePair2_2("AnnotationType", "REVIEW")
141	if err != nil {
142		t.Errorf("got error when calling parsePair2_2: %v", err)
143	}
144	if parser.st != psCreationInfo2_2 {
145		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
146	}
147
148	err = parser.parsePair2_2("SPDXREF", "SPDXRef-45")
149	if err != nil {
150		t.Errorf("got error when calling parsePair2_2: %v", err)
151	}
152	if parser.st != psCreationInfo2_2 {
153		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
154	}
155
156	err = parser.parsePair2_2("AnnotationComment", "i guess i had something to say about this spdx file")
157	if err != nil {
158		t.Errorf("got error when calling parsePair2_2: %v", err)
159	}
160	if parser.st != psCreationInfo2_2 {
161		t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_2)
162	}
163}
164
165func TestParser2_2FailsParsingCreationInfoWithInvalidState(t *testing.T) {
166	parser := tvParser2_2{
167		doc: &v2_2.Document{},
168		st:  psPackage2_2,
169	}
170	err := parser.parsePairFromCreationInfo2_2("SPDXVersion", "SPDX-2.2")
171	if err == nil {
172		t.Errorf("expected non-nil error, got nil")
173	}
174}
175
176// ===== Creation Info section tests =====
177func TestParser2_2HasCreationInfoAfterCallToParseFirstTag(t *testing.T) {
178	parser := tvParser2_2{
179		doc: &v2_2.Document{},
180		st:  psCreationInfo2_2,
181	}
182	err := parser.parsePairFromCreationInfo2_2("LicenseListVersion", "3.9")
183	if err != nil {
184		t.Errorf("got error when calling parsePairFromCreationInfo2_2: %v", err)
185	}
186	if parser.doc.CreationInfo == nil {
187		t.Errorf("doc.CreationInfo is still nil after parsing first pair")
188	}
189}
190
191func TestParser2_2CanParseCreationInfoTags(t *testing.T) {
192	parser := tvParser2_2{
193		doc: &v2_2.Document{},
194		st:  psCreationInfo2_2,
195	}
196
197	// License List Version
198	err := parser.parsePairFromCreationInfo2_2("LicenseListVersion", "2.2")
199	if err != nil {
200		t.Errorf("expected nil error, got %v", err)
201	}
202	if parser.doc.CreationInfo.LicenseListVersion != "2.2" {
203		t.Errorf("got %v for LicenseListVersion", parser.doc.CreationInfo.LicenseListVersion)
204	}
205
206	// Creators: Persons
207	refPersons := []string{
208		"Person: Person A",
209		"Person: Person B",
210	}
211	err = parser.parsePairFromCreationInfo2_2("Creator", refPersons[0])
212	if err != nil {
213		t.Errorf("expected nil error, got %v", err)
214	}
215	err = parser.parsePairFromCreationInfo2_2("Creator", refPersons[1])
216	if err != nil {
217		t.Errorf("expected nil error, got %v", err)
218	}
219	if len(parser.doc.CreationInfo.Creators) != 2 ||
220		parser.doc.CreationInfo.Creators[0].Creator != "Person A" ||
221		parser.doc.CreationInfo.Creators[1].Creator != "Person B" {
222		t.Errorf("got %v for CreatorPersons", parser.doc.CreationInfo.Creators)
223	}
224
225	// Creators: Organizations
226	refOrgs := []string{
227		"Organization: Organization A",
228		"Organization: Organization B",
229	}
230	err = parser.parsePairFromCreationInfo2_2("Creator", refOrgs[0])
231	if err != nil {
232		t.Errorf("expected nil error, got %v", err)
233	}
234	err = parser.parsePairFromCreationInfo2_2("Creator", refOrgs[1])
235	if err != nil {
236		t.Errorf("expected nil error, got %v", err)
237	}
238	if len(parser.doc.CreationInfo.Creators) != 4 ||
239		parser.doc.CreationInfo.Creators[2].Creator != "Organization A" ||
240		parser.doc.CreationInfo.Creators[3].Creator != "Organization B" {
241		t.Errorf("got %v for CreatorOrganizations", parser.doc.CreationInfo.Creators)
242	}
243
244	// Creators: Tools
245	refTools := []string{
246		"Tool: Tool A",
247		"Tool: Tool B",
248	}
249	err = parser.parsePairFromCreationInfo2_2("Creator", refTools[0])
250	if err != nil {
251		t.Errorf("expected nil error, got %v", err)
252	}
253	err = parser.parsePairFromCreationInfo2_2("Creator", refTools[1])
254	if err != nil {
255		t.Errorf("expected nil error, got %v", err)
256	}
257	if len(parser.doc.CreationInfo.Creators) != 6 ||
258		parser.doc.CreationInfo.Creators[4].Creator != "Tool A" ||
259		parser.doc.CreationInfo.Creators[5].Creator != "Tool B" {
260		t.Errorf("got %v for CreatorTools", parser.doc.CreationInfo.Creators)
261	}
262
263	// Created date
264	err = parser.parsePairFromCreationInfo2_2("Created", "2018-09-10T11:46:00Z")
265	if err != nil {
266		t.Errorf("expected nil error, got %v", err)
267	}
268	if parser.doc.CreationInfo.Created != "2018-09-10T11:46:00Z" {
269		t.Errorf("got %v for Created", parser.doc.CreationInfo.Created)
270	}
271
272	// Creator Comment
273	err = parser.parsePairFromCreationInfo2_2("CreatorComment", "Blah whatever")
274	if err != nil {
275		t.Errorf("expected nil error, got %v", err)
276	}
277	if parser.doc.CreationInfo.CreatorComment != "Blah whatever" {
278		t.Errorf("got %v for CreatorComment", parser.doc.CreationInfo.CreatorComment)
279	}
280}
281
282func TestParser2_2InvalidCreatorTagsFail(t *testing.T) {
283	parser := tvParser2_2{
284		doc: &v2_2.Document{},
285		st:  psCreationInfo2_2,
286	}
287
288	err := parser.parsePairFromCreationInfo2_2("Creator", "blah: somebody")
289	if err == nil {
290		t.Errorf("expected error from parsing invalid Creator format, got nil")
291	}
292
293	err = parser.parsePairFromCreationInfo2_2("Creator", "Tool with no colons")
294	if err == nil {
295		t.Errorf("expected error from parsing invalid Creator format, got nil")
296	}
297}
298
299func TestParser2_2CreatorTagWithMultipleColonsPasses(t *testing.T) {
300	parser := tvParser2_2{
301		doc: &v2_2.Document{},
302		st:  psCreationInfo2_2,
303	}
304
305	err := parser.parsePairFromCreationInfo2_2("Creator", "Tool: tool1:2:3")
306	if err != nil {
307		t.Errorf("unexpected error from parsing valid Creator format")
308	}
309}
310
311func TestParser2_2CIUnknownTagFails(t *testing.T) {
312	parser := tvParser2_2{
313		doc: &v2_2.Document{},
314		st:  psCreationInfo2_2,
315	}
316
317	err := parser.parsePairFromCreationInfo2_2("blah", "something")
318	if err == nil {
319		t.Errorf("expected error from parsing unknown tag")
320	}
321}
322
323func TestParser2_2CICreatesRelationship(t *testing.T) {
324	parser := tvParser2_2{
325		doc: &v2_2.Document{},
326		st:  psCreationInfo2_2,
327	}
328
329	err := parser.parsePair2_2("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-whatever")
330	if err != nil {
331		t.Errorf("got error when calling parsePair2_2: %v", err)
332	}
333	if parser.rln == nil {
334		t.Fatalf("parser didn't create and point to Relationship struct")
335	}
336	if parser.rln != parser.doc.Relationships[0] {
337		t.Errorf("pointer to new Relationship doesn't match idx 0 for doc.Relationships[]")
338	}
339}
340
341func TestParser2_2CICreatesAnnotation(t *testing.T) {
342	parser := tvParser2_2{
343		doc: &v2_2.Document{},
344		st:  psCreationInfo2_2,
345	}
346
347	err := parser.parsePair2_2("Annotator", "Person: John Doe ()")
348	if err != nil {
349		t.Errorf("got error when calling parsePair2_2: %v", err)
350	}
351	if parser.ann == nil {
352		t.Fatalf("parser didn't create and point to Annotation struct")
353	}
354	if parser.ann != parser.doc.Annotations[0] {
355		t.Errorf("pointer to new Annotation doesn't match idx 0 for doc.Annotations[]")
356	}
357}
358
359// ===== Helper function tests =====
360
361func TestCanExtractExternalDocumentReference(t *testing.T) {
362	refstring := "DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1:d6a770ba38583ed4bb4525bd96e50461655d2759"
363	wantDocumentRefID := "spdx-tool-1.2"
364	wantURI := "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301"
365	wantAlg := "SHA1"
366	wantChecksum := "d6a770ba38583ed4bb4525bd96e50461655d2759"
367
368	gotDocumentRefID, gotURI, gotAlg, gotChecksum, err := extractExternalDocumentReference(refstring)
369	if err != nil {
370		t.Errorf("got non-nil error: %v", err)
371	}
372	if wantDocumentRefID != gotDocumentRefID {
373		t.Errorf("wanted document ref ID %s, got %s", wantDocumentRefID, gotDocumentRefID)
374	}
375	if wantURI != gotURI {
376		t.Errorf("wanted URI %s, got %s", wantURI, gotURI)
377	}
378	if wantAlg != gotAlg {
379		t.Errorf("wanted alg %s, got %s", wantAlg, gotAlg)
380	}
381	if wantChecksum != gotChecksum {
382		t.Errorf("wanted checksum %s, got %s", wantChecksum, gotChecksum)
383	}
384}
385
386func TestCanExtractExternalDocumentReferenceWithExtraWhitespace(t *testing.T) {
387	refstring := "   DocumentRef-spdx-tool-1.2    \t http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 \t SHA1:  \t   d6a770ba38583ed4bb4525bd96e50461655d2759"
388	wantDocumentRefID := "spdx-tool-1.2"
389	wantURI := "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301"
390	wantAlg := "SHA1"
391	wantChecksum := "d6a770ba38583ed4bb4525bd96e50461655d2759"
392
393	gotDocumentRefID, gotURI, gotAlg, gotChecksum, err := extractExternalDocumentReference(refstring)
394	if err != nil {
395		t.Errorf("got non-nil error: %v", err)
396	}
397	if wantDocumentRefID != gotDocumentRefID {
398		t.Errorf("wanted document ref ID %s, got %s", wantDocumentRefID, gotDocumentRefID)
399	}
400	if wantURI != gotURI {
401		t.Errorf("wanted URI %s, got %s", wantURI, gotURI)
402	}
403	if wantAlg != gotAlg {
404		t.Errorf("wanted alg %s, got %s", wantAlg, gotAlg)
405	}
406	if wantChecksum != gotChecksum {
407		t.Errorf("wanted checksum %s, got %s", wantChecksum, gotChecksum)
408	}
409}
410
411func TestFailsExternalDocumentReferenceWithInvalidFormats(t *testing.T) {
412	invalidRefs := []string{
413		"whoops",
414		"DocumentRef-",
415		"DocumentRef-   ",
416		"DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301",
417		"DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 d6a770ba38583ed4bb4525bd96e50461655d2759",
418		"DocumentRef-spdx-tool-1.2",
419		"spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1:d6a770ba38583ed4bb4525bd96e50461655d2759",
420	}
421	for _, refstring := range invalidRefs {
422		_, _, _, _, err := extractExternalDocumentReference(refstring)
423		if err == nil {
424			t.Errorf("expected non-nil error for %s, got nil", refstring)
425		}
426	}
427}
428