xref: /aosp_15_r20/external/spdx-tools/tvloader/parser2v1/parse_file_test.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2package parser2v1
3
4import (
5	"testing"
6
7	"github.com/spdx/tools-golang/spdx/common"
8	"github.com/spdx/tools-golang/spdx/v2_1"
9)
10
11// ===== Parser file section state change tests =====
12func TestParser2_1FileStartsNewFileAfterParsingFileNameTag(t *testing.T) {
13	// create the first file
14	fileOldName := "f1.txt"
15
16	parser := tvParser2_1{
17		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
18		st:   psFile2_1,
19		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
20		file: &v2_1.File{FileName: fileOldName, FileSPDXIdentifier: "f1"},
21	}
22	fileOld := parser.file
23	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
24	parser.pkg.Files = append(parser.pkg.Files, fileOld)
25	// the Package's Files should have this one only
26	if len(parser.pkg.Files) != 1 {
27		t.Fatalf("expected 1 file, got %d", len(parser.pkg.Files))
28	}
29	if parser.pkg.Files[0] != fileOld {
30		t.Errorf("expected file %v in Files[f1], got %v", fileOld, parser.pkg.Files[0])
31	}
32	if parser.pkg.Files[0].FileName != fileOldName {
33		t.Errorf("expected file name %s in Files[f1], got %s", fileOldName, parser.pkg.Files[0].FileName)
34	}
35
36	// now add a new file
37	fileName := "f2.txt"
38	err := parser.parsePair2_1("FileName", fileName)
39	if err != nil {
40		t.Errorf("got error when calling parsePair2_1: %v", err)
41	}
42	// state should be correct
43	if parser.st != psFile2_1 {
44		t.Errorf("expected state to be %v, got %v", psFile2_1, parser.st)
45	}
46	// and a file should be created
47	if parser.file == nil {
48		t.Fatalf("parser didn't create new file")
49	}
50	// and the file name should be as expected
51	if parser.file.FileName != fileName {
52		t.Errorf("expected file name %s, got %s", fileName, parser.file.FileName)
53	}
54	// and the Package's Files should still be of size 1 and not have this new
55	// one yet, since it hasn't seen an SPDX identifier
56	if len(parser.pkg.Files) != 1 {
57		t.Fatalf("expected 1 file, got %d", len(parser.pkg.Files))
58	}
59	if parser.pkg.Files[0] != fileOld {
60		t.Errorf("expected file %v in Files[f1], got %v", fileOld, parser.pkg.Files[0])
61	}
62	if parser.pkg.Files[0].FileName != fileOldName {
63		t.Errorf("expected file name %s in Files[f1], got %s", fileOldName, parser.pkg.Files[0].FileName)
64	}
65
66	// now parse an SPDX identifier tag
67	err = parser.parsePair2_1("SPDXID", "SPDXRef-f2ID")
68	if err != nil {
69		t.Errorf("got error when calling parsePair2_1: %v", err)
70	}
71	// and the Package's Files should now be of size 2 and have this new one
72	if len(parser.pkg.Files) != 2 {
73		t.Fatalf("expected 2 files, got %d", len(parser.pkg.Files))
74	}
75	if parser.pkg.Files[0] != fileOld {
76		t.Errorf("expected file %v in Files[f1], got %v", fileOld, parser.pkg.Files[0])
77	}
78	if parser.pkg.Files[0].FileName != fileOldName {
79		t.Errorf("expected file name %s in Files[f1], got %s", fileOldName, parser.pkg.Files[0].FileName)
80	}
81	if parser.pkg.Files[1] != parser.file {
82		t.Errorf("expected file %v in Files[f2ID], got %v", parser.file, parser.pkg.Files[1])
83	}
84	if parser.pkg.Files[1].FileName != fileName {
85		t.Errorf("expected file name %s in Files[f2ID], got %s", fileName, parser.pkg.Files[1].FileName)
86	}
87}
88
89func TestParser2_1FileAddsToPackageOrUnpackagedFiles(t *testing.T) {
90	// start with no packages
91	parser := tvParser2_1{
92		doc: &v2_1.Document{},
93		st:  psCreationInfo2_1,
94	}
95
96	// add a file and SPDX identifier
97	fileName := "f2.txt"
98	err := parser.parsePair2_1("FileName", fileName)
99	if err != nil {
100		t.Errorf("got error when calling parsePair2_1: %v", err)
101	}
102	err = parser.parsePair2_1("SPDXID", "SPDXRef-f2ID")
103	if err != nil {
104		t.Errorf("got error when calling parsePair2_1: %v", err)
105	}
106	fileOld := parser.file
107	// should have been added to Files
108	if len(parser.doc.Files) != 1 {
109		t.Fatalf("expected 1 file in Files, got %d", len(parser.doc.Files))
110	}
111	if parser.doc.Files[0] != fileOld {
112		t.Errorf("expected file %v in Files[f2ID], got %v", fileOld, parser.doc.Files[0])
113	}
114	// now create a package and a new file
115	err = parser.parsePair2_1("PackageName", "package1")
116	if err != nil {
117		t.Errorf("got error when calling parsePair2_1: %v", err)
118	}
119	err = parser.parsePair2_1("SPDXID", "SPDXRef-pkg1")
120	if err != nil {
121		t.Errorf("got error when calling parsePair2_1: %v", err)
122	}
123	err = parser.parsePair2_1("FileName", "f3.txt")
124	if err != nil {
125		t.Errorf("got error when calling parsePair2_1: %v", err)
126	}
127	err = parser.parsePair2_1("SPDXID", "SPDXRef-f3ID")
128	if err != nil {
129		t.Errorf("got error when calling parsePair2_1: %v", err)
130	}
131	// Files should still be size 1 and have old file only
132	if len(parser.doc.Files) != 1 {
133		t.Fatalf("expected 1 file in Files, got %d", len(parser.doc.Files))
134	}
135	if parser.doc.Files[0] != fileOld {
136		t.Errorf("expected file %v in Files[f2ID], got %v", fileOld, parser.doc.Files[0])
137	}
138	// and new package should have gotten the new file
139	if len(parser.pkg.Files) != 1 {
140		t.Fatalf("expected 1 file in Files, got %d", len(parser.pkg.Files))
141	}
142	if parser.pkg.Files[0] != parser.file {
143		t.Errorf("expected file %v in Files[f3ID], got %v", parser.file, parser.pkg.Files[0])
144	}
145}
146
147func TestParser2_1FileStartsNewPackageAfterParsingPackageNameTag(t *testing.T) {
148	// create the first file and package
149	p1Name := "package1"
150	f1Name := "f1.txt"
151
152	parser := tvParser2_1{
153		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
154		st:   psFile2_1,
155		pkg:  &v2_1.Package{PackageName: p1Name, PackageSPDXIdentifier: "package1", Files: []*v2_1.File{}},
156		file: &v2_1.File{FileName: f1Name, FileSPDXIdentifier: "f1"},
157	}
158	p1 := parser.pkg
159	f1 := parser.file
160	parser.doc.Packages = append(parser.doc.Packages, p1)
161	parser.pkg.Files = append(parser.pkg.Files, f1)
162
163	// now add a new package
164	p2Name := "package2"
165	err := parser.parsePair2_1("PackageName", p2Name)
166	if err != nil {
167		t.Errorf("got error when calling parsePair2_1: %v", err)
168	}
169	// state should go back to Package
170	if parser.st != psPackage2_1 {
171		t.Errorf("expected state to be %v, got %v", psPackage2_1, parser.st)
172	}
173	// and a package should be created
174	if parser.pkg == nil {
175		t.Fatalf("parser didn't create new pkg")
176	}
177	// and the package name should be as expected
178	if parser.pkg.PackageName != p2Name {
179		t.Errorf("expected package name %s, got %s", p2Name, parser.pkg.PackageName)
180	}
181	// and the package should default to true for FilesAnalyzed
182	if parser.pkg.FilesAnalyzed != true {
183		t.Errorf("expected FilesAnalyzed to default to true, got false")
184	}
185	if parser.pkg.IsFilesAnalyzedTagPresent != false {
186		t.Errorf("expected IsFilesAnalyzedTagPresent to default to false, got true")
187	}
188	// and the new Package should have no files
189	if len(parser.pkg.Files) != 0 {
190		t.Errorf("Expected no files in pkg.Files, got %d", len(parser.pkg.Files))
191	}
192	// and the Document's Packages should still be of size 1 and not have this
193	// new one, because no SPDX identifier has been seen yet
194	if len(parser.doc.Packages) != 1 {
195		t.Fatalf("expected 1 package, got %d", len(parser.doc.Packages))
196	}
197	if parser.doc.Packages[0] != p1 {
198		t.Errorf("Expected package %v in Packages[package1], got %v", p1, parser.doc.Packages[0])
199	}
200	if parser.doc.Packages[0].PackageName != p1Name {
201		t.Errorf("expected package name %s in Packages[package1], got %s", p1Name, parser.doc.Packages[0].PackageName)
202	}
203	// and the first Package's Files should be of size 1 and have f1 only
204	if len(parser.doc.Packages[0].Files) != 1 {
205		t.Errorf("Expected 1 file in Packages[package1].Files, got %d", len(parser.doc.Packages[0].Files))
206	}
207	if parser.doc.Packages[0].Files[0] != f1 {
208		t.Errorf("Expected file %v in Files[f1], got %v", f1, parser.doc.Packages[0].Files[0])
209	}
210	if parser.doc.Packages[0].Files[0].FileName != f1Name {
211		t.Errorf("expected file name %s in Files[f1], got %s", f1Name, parser.doc.Packages[0].Files[0].FileName)
212	}
213	// and the current file should be nil
214	if parser.file != nil {
215		t.Errorf("Expected nil for parser.file, got %v", parser.file)
216	}
217}
218
219func TestParser2_1FileMovesToSnippetAfterParsingSnippetSPDXIDTag(t *testing.T) {
220	parser := tvParser2_1{
221		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
222		st:   psFile2_1,
223		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
224		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
225	}
226	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
227	parser.pkg.Files = append(parser.pkg.Files, parser.file)
228	fileCurrent := parser.file
229
230	err := parser.parsePair2_1("SnippetSPDXID", "SPDXRef-Test1")
231	if err != nil {
232		t.Errorf("got error when calling parsePair2_1: %v", err)
233	}
234	// state should be correct
235	if parser.st != psSnippet2_1 {
236		t.Errorf("expected state to be %v, got %v", psSnippet2_1, parser.st)
237	}
238	// and current file should remain what it was
239	if parser.file != fileCurrent {
240		t.Fatalf("expected file to remain %v, got %v", fileCurrent, parser.file)
241	}
242}
243
244func TestParser2_1FileMovesToOtherLicenseAfterParsingLicenseIDTag(t *testing.T) {
245	parser := tvParser2_1{
246		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
247		st:   psFile2_1,
248		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
249		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
250	}
251	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
252	parser.pkg.Files = append(parser.pkg.Files, parser.file)
253
254	err := parser.parsePair2_1("LicenseID", "LicenseRef-TestLic")
255	if err != nil {
256		t.Errorf("got error when calling parsePair2_1: %v", err)
257	}
258	if parser.st != psOtherLicense2_1 {
259		t.Errorf("expected state to be %v, got %v", psOtherLicense2_1, parser.st)
260	}
261}
262
263func TestParser2_1FileMovesToReviewAfterParsingReviewerTag(t *testing.T) {
264	parser := tvParser2_1{
265		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
266		st:   psFile2_1,
267		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
268		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
269	}
270	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
271	parser.pkg.Files = append(parser.pkg.Files, parser.file)
272
273	err := parser.parsePair2_1("Reviewer", "Person: John Doe")
274	if err != nil {
275		t.Errorf("got error when calling parsePair2_1: %v", err)
276	}
277	if parser.st != psReview2_1 {
278		t.Errorf("expected state to be %v, got %v", psReview2_1, parser.st)
279	}
280}
281
282func TestParser2_1FileStaysAfterParsingRelationshipTags(t *testing.T) {
283	parser := tvParser2_1{
284		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
285		st:   psFile2_1,
286		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
287		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
288	}
289	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
290	parser.pkg.Files = append(parser.pkg.Files, parser.file)
291
292	err := parser.parsePair2_1("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-else")
293	if err != nil {
294		t.Errorf("got error when calling parsePair2_1: %v", err)
295	}
296	// state should remain unchanged
297	if parser.st != psFile2_1 {
298		t.Errorf("expected state to be %v, got %v", psFile2_1, parser.st)
299	}
300
301	err = parser.parsePair2_1("RelationshipComment", "blah")
302	if err != nil {
303		t.Errorf("got error when calling parsePair2_1: %v", err)
304	}
305	// state should still remain unchanged
306	if parser.st != psFile2_1 {
307		t.Errorf("expected state to be %v, got %v", psFile2_1, parser.st)
308	}
309}
310
311func TestParser2_1FileStaysAfterParsingAnnotationTags(t *testing.T) {
312	parser := tvParser2_1{
313		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
314		st:   psFile2_1,
315		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
316		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
317	}
318	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
319	parser.pkg.Files = append(parser.pkg.Files, parser.file)
320
321	err := parser.parsePair2_1("Annotator", "Person: John Doe ()")
322	if err != nil {
323		t.Errorf("got error when calling parsePair2_1: %v", err)
324	}
325	if parser.st != psFile2_1 {
326		t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_1)
327	}
328
329	err = parser.parsePair2_1("AnnotationDate", "2018-09-15T00:36:00Z")
330	if err != nil {
331		t.Errorf("got error when calling parsePair2_1: %v", err)
332	}
333	if parser.st != psFile2_1 {
334		t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_1)
335	}
336
337	err = parser.parsePair2_1("AnnotationType", "REVIEW")
338	if err != nil {
339		t.Errorf("got error when calling parsePair2_1: %v", err)
340	}
341	if parser.st != psFile2_1 {
342		t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_1)
343	}
344
345	err = parser.parsePair2_1("SPDXREF", "SPDXRef-45")
346	if err != nil {
347		t.Errorf("got error when calling parsePair2_1: %v", err)
348	}
349	if parser.st != psFile2_1 {
350		t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_1)
351	}
352
353	err = parser.parsePair2_1("AnnotationComment", "i guess i had something to say about this particular file")
354	if err != nil {
355		t.Errorf("got error when calling parsePair2_1: %v", err)
356	}
357	if parser.st != psFile2_1 {
358		t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_1)
359	}
360}
361
362// ===== File data section tests =====
363func TestParser2_1CanParseFileTags(t *testing.T) {
364	parser := tvParser2_1{
365		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
366		st:  psFile2_1,
367		pkg: &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
368	}
369	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
370
371	// File Name
372	err := parser.parsePairFromFile2_1("FileName", "f1.txt")
373	if err != nil {
374		t.Errorf("expected nil error, got %v", err)
375	}
376	if parser.file.FileName != "f1.txt" {
377		t.Errorf("got %v for FileName", parser.file.FileName)
378	}
379	// should not yet be added to the Packages file list, because we haven't
380	// seen an SPDX identifier yet
381	if len(parser.pkg.Files) != 0 {
382		t.Errorf("expected 0 files, got %d", len(parser.pkg.Files))
383	}
384
385	// File SPDX Identifier
386	err = parser.parsePairFromFile2_1("SPDXID", "SPDXRef-f1")
387	if err != nil {
388		t.Errorf("expected nil error, got %v", err)
389	}
390	if parser.file.FileSPDXIdentifier != "f1" {
391		t.Errorf("got %v for FileSPDXIdentifier", parser.file.FileSPDXIdentifier)
392	}
393	// should now be added to the Packages file list
394	if len(parser.pkg.Files) != 1 {
395		t.Errorf("expected 1 file, got %d", len(parser.pkg.Files))
396	}
397	if parser.pkg.Files[0] != parser.file {
398		t.Errorf("expected Files[f1] to be %v, got %v", parser.file, parser.pkg.Files[0])
399	}
400
401	// File Type
402	fileTypes := []string{
403		"TEXT",
404		"DOCUMENTATION",
405	}
406	for _, ty := range fileTypes {
407		err = parser.parsePairFromFile2_1("FileType", ty)
408		if err != nil {
409			t.Errorf("expected nil error, got %v", err)
410		}
411	}
412	for _, typeWant := range fileTypes {
413		flagFound := false
414		for _, typeCheck := range parser.file.FileTypes {
415			if typeWant == typeCheck {
416				flagFound = true
417			}
418		}
419		if flagFound == false {
420			t.Errorf("didn't find %s in FileTypes", typeWant)
421		}
422	}
423	if len(fileTypes) != len(parser.file.FileTypes) {
424		t.Errorf("expected %d types in FileTypes, got %d", len(fileTypes),
425			len(parser.file.FileTypes))
426	}
427
428	// File Checksums
429	codeSha1 := "85ed0817af83a24ad8da68c2b5094de69833983c"
430	sumSha1 := "SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c"
431	codeSha256 := "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"
432	sumSha256 := "SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"
433	codeMd5 := "624c1abb3664f4b35547e7c73864ad24"
434	sumMd5 := "MD5: 624c1abb3664f4b35547e7c73864ad24"
435	err = parser.parsePairFromFile2_1("FileChecksum", sumSha1)
436	if err != nil {
437		t.Errorf("expected nil error, got %v", err)
438	}
439	err = parser.parsePairFromFile2_1("FileChecksum", sumSha256)
440	if err != nil {
441		t.Errorf("expected nil error, got %v", err)
442	}
443	err = parser.parsePairFromFile2_1("FileChecksum", sumMd5)
444	if err != nil {
445		t.Errorf("expected nil error, got %v", err)
446	}
447	for _, checksum := range parser.file.Checksums {
448		switch checksum.Algorithm {
449		case common.SHA1:
450			if checksum.Value != codeSha1 {
451				t.Errorf("expected %s for FileChecksumSHA1, got %s", codeSha1, checksum.Value)
452			}
453		case common.SHA256:
454			if checksum.Value != codeSha256 {
455				t.Errorf("expected %s for FileChecksumSHA1, got %s", codeSha256, checksum.Value)
456			}
457		case common.MD5:
458			if checksum.Value != codeMd5 {
459				t.Errorf("expected %s for FileChecksumSHA1, got %s", codeMd5, checksum.Value)
460			}
461		}
462	}
463	// Concluded License
464	err = parser.parsePairFromFile2_1("LicenseConcluded", "Apache-2.0 OR GPL-2.0-or-later")
465	if err != nil {
466		t.Errorf("expected nil error, got %v", err)
467	}
468	if parser.file.LicenseConcluded != "Apache-2.0 OR GPL-2.0-or-later" {
469		t.Errorf("got %v for LicenseConcluded", parser.file.LicenseConcluded)
470	}
471
472	// License Information in File
473	lics := []string{
474		"Apache-2.0",
475		"GPL-2.0-or-later",
476		"CC0-1.0",
477	}
478	for _, lic := range lics {
479		err = parser.parsePairFromFile2_1("LicenseInfoInFile", lic)
480		if err != nil {
481			t.Errorf("expected nil error, got %v", err)
482		}
483	}
484	for _, licWant := range lics {
485		flagFound := false
486		for _, licCheck := range parser.file.LicenseInfoInFiles {
487			if licWant == licCheck {
488				flagFound = true
489			}
490		}
491		if flagFound == false {
492			t.Errorf("didn't find %s in LicenseInfoInFiles", licWant)
493		}
494	}
495	if len(lics) != len(parser.file.LicenseInfoInFiles) {
496		t.Errorf("expected %d licenses in LicenseInfoInFiles, got %d", len(lics),
497			len(parser.file.LicenseInfoInFiles))
498	}
499
500	// Comments on License
501	err = parser.parsePairFromFile2_1("LicenseComments", "this is a comment")
502	if err != nil {
503		t.Errorf("expected nil error, got %v", err)
504	}
505	if parser.file.LicenseComments != "this is a comment" {
506		t.Errorf("got %v for LicenseComments", parser.file.LicenseComments)
507	}
508
509	// Copyright Text
510	err = parser.parsePairFromFile2_1("FileCopyrightText", "copyright (c) me")
511	if err != nil {
512		t.Errorf("expected nil error, got %v", err)
513	}
514	if parser.file.FileCopyrightText != "copyright (c) me" {
515		t.Errorf("got %v for FileCopyrightText", parser.file.FileCopyrightText)
516	}
517
518	// Artifact of Projects: Name, HomePage and URI
519	// Artifact set 1
520	err = parser.parsePairFromFile2_1("ArtifactOfProjectName", "project1")
521	if err != nil {
522		t.Errorf("expected nil error, got %v", err)
523	}
524	err = parser.parsePairFromFile2_1("ArtifactOfProjectHomePage", "http://example.com/1/")
525	if err != nil {
526		t.Errorf("expected nil error, got %v", err)
527	}
528	err = parser.parsePairFromFile2_1("ArtifactOfProjectURI", "http://example.com/1/uri.whatever")
529	if err != nil {
530		t.Errorf("expected nil error, got %v", err)
531	}
532	// Artifact set 2 -- just name
533	err = parser.parsePairFromFile2_1("ArtifactOfProjectName", "project2")
534	if err != nil {
535		t.Errorf("expected nil error, got %v", err)
536	}
537	// Artifact set 3 -- just name and home page
538	err = parser.parsePairFromFile2_1("ArtifactOfProjectName", "project3")
539	if err != nil {
540		t.Errorf("expected nil error, got %v", err)
541	}
542	err = parser.parsePairFromFile2_1("ArtifactOfProjectHomePage", "http://example.com/3/")
543	if err != nil {
544		t.Errorf("expected nil error, got %v", err)
545	}
546	// Artifact set 4 -- just name and URI
547	err = parser.parsePairFromFile2_1("ArtifactOfProjectName", "project4")
548	if err != nil {
549		t.Errorf("expected nil error, got %v", err)
550	}
551	err = parser.parsePairFromFile2_1("ArtifactOfProjectURI", "http://example.com/4/uri.whatever")
552	if err != nil {
553		t.Errorf("expected nil error, got %v", err)
554	}
555
556	if len(parser.file.ArtifactOfProjects) != 4 {
557		t.Fatalf("expected len %d, got %d", 4, len(parser.file.ArtifactOfProjects))
558	}
559
560	aop := parser.file.ArtifactOfProjects[0]
561	if aop.Name != "project1" {
562		t.Errorf("expected %v, got %v", "project1", aop.Name)
563	}
564	if aop.HomePage != "http://example.com/1/" {
565		t.Errorf("expected %v, got %v", "http://example.com/1/", aop.HomePage)
566	}
567	if aop.URI != "http://example.com/1/uri.whatever" {
568		t.Errorf("expected %v, got %v", "http://example.com/1/uri.whatever", aop.URI)
569	}
570
571	aop = parser.file.ArtifactOfProjects[1]
572	if aop.Name != "project2" {
573		t.Errorf("expected %v, got %v", "project2", aop.Name)
574	}
575	if aop.HomePage != "" {
576		t.Errorf("expected %v, got %v", "", aop.HomePage)
577	}
578	if aop.URI != "" {
579		t.Errorf("expected %v, got %v", "", aop.URI)
580	}
581
582	aop = parser.file.ArtifactOfProjects[2]
583	if aop.Name != "project3" {
584		t.Errorf("expected %v, got %v", "project3", aop.Name)
585	}
586	if aop.HomePage != "http://example.com/3/" {
587		t.Errorf("expected %v, got %v", "http://example.com/3/", aop.HomePage)
588	}
589	if aop.URI != "" {
590		t.Errorf("expected %v, got %v", "", aop.URI)
591	}
592
593	aop = parser.file.ArtifactOfProjects[3]
594	if aop.Name != "project4" {
595		t.Errorf("expected %v, got %v", "project4", aop.Name)
596	}
597	if aop.HomePage != "" {
598		t.Errorf("expected %v, got %v", "", aop.HomePage)
599	}
600	if aop.URI != "http://example.com/4/uri.whatever" {
601		t.Errorf("expected %v, got %v", "http://example.com/4/uri.whatever", aop.URI)
602	}
603
604	// File Comment
605	err = parser.parsePairFromFile2_1("FileComment", "this is a comment")
606	if err != nil {
607		t.Errorf("expected nil error, got %v", err)
608	}
609	if parser.file.FileComment != "this is a comment" {
610		t.Errorf("got %v for FileComment", parser.file.FileComment)
611	}
612
613	// File Notice
614	err = parser.parsePairFromFile2_1("FileNotice", "this is a Notice")
615	if err != nil {
616		t.Errorf("expected nil error, got %v", err)
617	}
618	if parser.file.FileNotice != "this is a Notice" {
619		t.Errorf("got %v for FileNotice", parser.file.FileNotice)
620	}
621
622	// File Contributor
623	contribs := []string{
624		"John Doe [email protected]",
625		"EvilCorp",
626	}
627	for _, contrib := range contribs {
628		err = parser.parsePairFromFile2_1("FileContributor", contrib)
629		if err != nil {
630			t.Errorf("expected nil error, got %v", err)
631		}
632	}
633	for _, contribWant := range contribs {
634		flagFound := false
635		for _, contribCheck := range parser.file.FileContributors {
636			if contribWant == contribCheck {
637				flagFound = true
638			}
639		}
640		if flagFound == false {
641			t.Errorf("didn't find %s in FileContributors", contribWant)
642		}
643	}
644	if len(contribs) != len(parser.file.FileContributors) {
645		t.Errorf("expected %d contribenses in FileContributors, got %d", len(contribs),
646			len(parser.file.FileContributors))
647	}
648
649	// File Dependencies
650	deps := []string{
651		"f-1.txt",
652		"g.txt",
653	}
654	for _, dep := range deps {
655		err = parser.parsePairFromFile2_1("FileDependency", dep)
656		if err != nil {
657			t.Errorf("expected nil error, got %v", err)
658		}
659	}
660	for _, depWant := range deps {
661		flagFound := false
662		for _, depCheck := range parser.file.FileDependencies {
663			if depWant == depCheck {
664				flagFound = true
665			}
666		}
667		if flagFound == false {
668			t.Errorf("didn't find %s in FileDependency", depWant)
669		}
670	}
671	if len(deps) != len(parser.file.FileDependencies) {
672		t.Errorf("expected %d depenses in FileDependency, got %d", len(deps),
673			len(parser.file.FileDependencies))
674	}
675
676}
677
678func TestParser2_1FileCreatesRelationshipInDocument(t *testing.T) {
679	parser := tvParser2_1{
680		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
681		st:   psFile2_1,
682		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
683		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
684	}
685	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
686	parser.pkg.Files = append(parser.pkg.Files, parser.file)
687
688	err := parser.parsePair2_1("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-whatever")
689	if err != nil {
690		t.Errorf("got error when calling parsePair2_1: %v", err)
691	}
692	if parser.rln == nil {
693		t.Fatalf("parser didn't create and point to Relationship struct")
694	}
695	if parser.rln != parser.doc.Relationships[0] {
696		t.Errorf("pointer to new Relationship doesn't match idx 0 for doc.Relationships[]")
697	}
698}
699
700func TestParser2_1FileCreatesAnnotationInDocument(t *testing.T) {
701	parser := tvParser2_1{
702		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
703		st:   psFile2_1,
704		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
705		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
706	}
707	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
708	parser.pkg.Files = append(parser.pkg.Files, parser.file)
709
710	err := parser.parsePair2_1("Annotator", "Person: John Doe ()")
711	if err != nil {
712		t.Errorf("got error when calling parsePair2_1: %v", err)
713	}
714	if parser.ann == nil {
715		t.Fatalf("parser didn't create and point to Annotation struct")
716	}
717	if parser.ann != parser.doc.Annotations[0] {
718		t.Errorf("pointer to new Annotation doesn't match idx 0 for doc.Annotations[]")
719	}
720}
721
722func TestParser2_1FileUnknownTagFails(t *testing.T) {
723	parser := tvParser2_1{
724		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
725		st:   psFile2_1,
726		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
727		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
728	}
729	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
730	parser.pkg.Files = append(parser.pkg.Files, parser.file)
731
732	err := parser.parsePairFromFile2_1("blah", "something")
733	if err == nil {
734		t.Errorf("expected error from parsing unknown tag")
735	}
736}
737
738func TestFileAOPPointerChangesAfterTags(t *testing.T) {
739	parser := tvParser2_1{
740		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
741		st:   psFile2_1,
742		pkg:  &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
743		file: &v2_1.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"},
744	}
745	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
746	parser.pkg.Files = append(parser.pkg.Files, parser.file)
747
748	err := parser.parsePairFromFile2_1("ArtifactOfProjectName", "project1")
749	if err != nil {
750		t.Errorf("expected nil error, got %v", err)
751	}
752	if parser.fileAOP == nil {
753		t.Errorf("expected non-nil AOP pointer, got nil")
754	}
755	curPtr := parser.fileAOP
756
757	// now, a home page; pointer should stay
758	err = parser.parsePairFromFile2_1("ArtifactOfProjectHomePage", "http://example.com/1/")
759	if err != nil {
760		t.Errorf("expected nil error, got %v", err)
761	}
762	if parser.fileAOP != curPtr {
763		t.Errorf("expected no change in AOP pointer, was %v, got %v", curPtr, parser.fileAOP)
764	}
765
766	// a URI; pointer should stay
767	err = parser.parsePairFromFile2_1("ArtifactOfProjectURI", "http://example.com/1/uri.whatever")
768	if err != nil {
769		t.Errorf("expected nil error, got %v", err)
770	}
771	if parser.fileAOP != curPtr {
772		t.Errorf("expected no change in AOP pointer, was %v, got %v", curPtr, parser.fileAOP)
773	}
774
775	// now, another artifact name; pointer should change but be non-nil
776	// now, a home page; pointer should stay
777	err = parser.parsePairFromFile2_1("ArtifactOfProjectName", "project2")
778	if err != nil {
779		t.Errorf("expected nil error, got %v", err)
780	}
781	if parser.fileAOP == curPtr {
782		t.Errorf("expected change in AOP pointer, got no change")
783	}
784
785	// finally, an unrelated tag; pointer should go away
786	err = parser.parsePairFromFile2_1("FileComment", "whatever")
787	if err != nil {
788		t.Errorf("expected nil error, got %v", err)
789	}
790	if parser.fileAOP != nil {
791		t.Errorf("expected nil AOP pointer, got %v", parser.fileAOP)
792	}
793}
794
795func TestParser2_1FailsIfInvalidSPDXIDInFileSection(t *testing.T) {
796	parser := tvParser2_1{
797		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
798		st:  psFile2_1,
799		pkg: &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
800	}
801	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
802
803	// start with File Name
804	err := parser.parsePairFromFile2_1("FileName", "f1.txt")
805	if err != nil {
806		t.Errorf("expected nil error, got %v", err)
807	}
808	// invalid SPDX Identifier
809	err = parser.parsePairFromFile2_1("SPDXID", "whoops")
810	if err == nil {
811		t.Errorf("expected non-nil error, got nil")
812	}
813}
814
815func TestParser2_1FailsIfInvalidChecksumFormatInFileSection(t *testing.T) {
816	parser := tvParser2_1{
817		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
818		st:  psFile2_1,
819		pkg: &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
820	}
821	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
822
823	// start with File Name
824	err := parser.parsePairFromFile2_1("FileName", "f1.txt")
825	if err != nil {
826		t.Errorf("expected nil error, got %v", err)
827	}
828	// invalid format for checksum line, missing colon
829	err = parser.parsePairFromFile2_1("FileChecksum", "SHA1 85ed0817af83a24ad8da68c2b5094de69833983c")
830	if err == nil {
831		t.Errorf("expected non-nil error, got nil")
832	}
833}
834
835func TestParser2_1FailsIfUnknownChecksumTypeInFileSection(t *testing.T) {
836	parser := tvParser2_1{
837		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
838		st:  psFile2_1,
839		pkg: &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
840	}
841	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
842
843	// start with File Name
844	err := parser.parsePairFromFile2_1("FileName", "f1.txt")
845	if err != nil {
846		t.Errorf("expected nil error, got %v", err)
847	}
848	// unknown checksum type
849	err = parser.parsePairFromFile2_1("FileChecksum", "Special: 85ed0817af83a24ad8da68c2b5094de69833983c")
850	if err == nil {
851		t.Errorf("expected non-nil error, got nil")
852	}
853}
854
855func TestParser2_1FailsIfArtifactHomePageBeforeArtifactName(t *testing.T) {
856	parser := tvParser2_1{
857		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
858		st:  psFile2_1,
859		pkg: &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
860	}
861	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
862
863	// start with File Name
864	err := parser.parsePairFromFile2_1("FileName", "f1.txt")
865	if err != nil {
866		t.Errorf("expected nil error, got %v", err)
867	}
868	// artifact home page appears before artifact name
869	err = parser.parsePairFromFile2_1("ArtifactOfProjectHomePage", "https://example.com")
870	if err == nil {
871		t.Errorf("expected non-nil error, got nil")
872	}
873}
874
875func TestParser2_1FailsIfArtifactURIBeforeArtifactName(t *testing.T) {
876	parser := tvParser2_1{
877		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
878		st:  psFile2_1,
879		pkg: &v2_1.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_1.File{}},
880	}
881	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
882
883	// start with File Name
884	err := parser.parsePairFromFile2_1("FileName", "f1.txt")
885	if err != nil {
886		t.Errorf("expected nil error, got %v", err)
887	}
888	// artifact home page appears before artifact name
889	err = parser.parsePairFromFile2_1("ArtifactOfProjectURI", "https://example.com")
890	if err == nil {
891		t.Errorf("expected non-nil error, got nil")
892	}
893}
894
895func TestParser2_1FilesWithoutSpdxIdThrowError(t *testing.T) {
896	// case 1: The previous file (packaged or unpackaged) does not contain spdxID
897	parser1 := tvParser2_1{
898		doc:  &v2_1.Document{Packages: []*v2_1.Package{}},
899		st:   psFile2_1,
900		file: &v2_1.File{FileName: "FileName"},
901	}
902
903	err := parser1.parsePair2_1("FileName", "f2")
904	if err == nil {
905		t.Errorf("file without SPDX Identifier getting accepted")
906	}
907
908	// case 2: Invalid file with snippet
909	// Last unpackaged file before a snippet starts
910	sid1 := common.ElementID("s1")
911	fileName := "f2.txt"
912	parser2 := tvParser2_1{
913		doc:  &v2_1.Document{},
914		st:   psCreationInfo2_1,
915		file: &v2_1.File{FileName: fileName},
916	}
917	err = parser2.parsePair2_1("SnippetSPDXID", string(sid1))
918	if err == nil {
919		t.Errorf("file without SPDX Identifier getting accepted")
920	}
921
922	// case 3 : Invalid File without snippets
923	// Last unpackaged file before a package starts
924	// Last file of a package and New package starts
925	parser3 := tvParser2_1{
926		doc: &v2_1.Document{},
927		st:  psCreationInfo2_1,
928	}
929	fileName = "f3.txt"
930	err = parser3.parsePair2_1("FileName", fileName)
931	if err != nil {
932		t.Errorf("%s", err)
933	}
934	err = parser3.parsePair2_1("PackageName", "p2")
935	if err == nil {
936		t.Errorf("files withoutSpdx Identifier getting accepted")
937	}
938}
939