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