xref: /aosp_15_r20/external/spdx-tools/tvloader/parser2v1/parse_package_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 package section state change tests =====
12func TestParser2_1PackageStartsNewPackageAfterParsingPackageNameTag(t *testing.T) {
13	// create the first package
14	pkgOldName := "p1"
15
16	parser := tvParser2_1{
17		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
18		st:  psPackage2_1,
19		pkg: &v2_1.Package{PackageName: pkgOldName, PackageSPDXIdentifier: "p1"},
20	}
21	pkgOld := parser.pkg
22	parser.doc.Packages = append(parser.doc.Packages, pkgOld)
23
24	// now add a new package
25	pkgName := "p2"
26	err := parser.parsePair2_1("PackageName", pkgName)
27	if err != nil {
28		t.Errorf("got error when calling parsePair2_1: %v", err)
29	}
30	// state should be correct
31	if parser.st != psPackage2_1 {
32		t.Errorf("expected state to be %v, got %v", psPackage2_1, parser.st)
33	}
34	// and a package should be created
35	if parser.pkg == nil {
36		t.Fatalf("parser didn't create new package")
37	}
38	// and it should not be pkgOld
39	if parser.pkg == pkgOld {
40		t.Errorf("expected new package, got pkgOld")
41	}
42	// and the package name should be as expected
43	if parser.pkg.PackageName != pkgName {
44		t.Errorf("expected package name %s, got %s", pkgName, parser.pkg.PackageName)
45	}
46	// and the package should default to true for FilesAnalyzed
47	if parser.pkg.FilesAnalyzed != true {
48		t.Errorf("expected FilesAnalyzed to default to true, got false")
49	}
50	if parser.pkg.IsFilesAnalyzedTagPresent != false {
51		t.Errorf("expected IsFilesAnalyzedTagPresent to default to false, got true")
52	}
53	// and the Document's Packages should still be of size 1 and have pkgOld only
54	if parser.doc.Packages[0] != pkgOld {
55		t.Errorf("Expected package %v, got %v", pkgOld, parser.doc.Packages[0])
56	}
57	if len(parser.doc.Packages) != 1 {
58		t.Errorf("expected 1 package, got %d", len(parser.doc.Packages))
59	}
60}
61
62func TestParser2_1PackageStartsNewPackageAfterParsingPackageNameTagWhileInUnpackaged(t *testing.T) {
63	// pkg is nil, so that Files appearing before the first PackageName tag
64	// are added to Files instead of Packages
65	parser := tvParser2_1{
66		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
67		st:  psFile2_1,
68		pkg: nil,
69	}
70	// the Document's Packages should be empty
71	if len(parser.doc.Packages) != 0 {
72		t.Errorf("Expected zero packages, got %d", len(parser.doc.Packages))
73	}
74
75	// now add a new package
76	pkgName := "p2"
77	err := parser.parsePair2_1("PackageName", pkgName)
78	if err != nil {
79		t.Errorf("got error when calling parsePair2_1: %v", err)
80	}
81	// state should be correct
82	if parser.st != psPackage2_1 {
83		t.Errorf("expected state to be %v, got %v", psPackage2_1, parser.st)
84	}
85	// and a package should be created
86	if parser.pkg == nil {
87		t.Fatalf("parser didn't create new package")
88	}
89	// and the package name should be as expected
90	if parser.pkg.PackageName != pkgName {
91		t.Errorf("expected package name %s, got %s", pkgName, parser.pkg.PackageName)
92	}
93	// and the package should default to true for FilesAnalyzed
94	if parser.pkg.FilesAnalyzed != true {
95		t.Errorf("expected FilesAnalyzed to default to true, got false")
96	}
97	if parser.pkg.IsFilesAnalyzedTagPresent != false {
98		t.Errorf("expected IsFilesAnalyzedTagPresent to default to false, got true")
99	}
100	// and the Document's Packages should be of size 0, because the prior was
101	// unpackaged files and this one won't be added until an SPDXID is seen
102	if len(parser.doc.Packages) != 0 {
103		t.Errorf("Expected %v packages in doc, got %v", 0, len(parser.doc.Packages))
104	}
105}
106
107func TestParser2_1PackageMovesToFileAfterParsingFileNameTag(t *testing.T) {
108	parser := tvParser2_1{
109		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
110		st:  psPackage2_1,
111		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
112	}
113	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
114	pkgCurrent := parser.pkg
115
116	err := parser.parsePair2_1("FileName", "testFile")
117	if err != nil {
118		t.Errorf("got error when calling parsePair2_1: %v", err)
119	}
120	// state should be correct
121	if parser.st != psFile2_1 {
122		t.Errorf("expected state to be %v, got %v", psFile2_1, parser.st)
123	}
124	// and current package should remain what it was
125	if parser.pkg != pkgCurrent {
126		t.Fatalf("expected package to remain %v, got %v", pkgCurrent, parser.pkg)
127	}
128}
129
130func TestParser2_1PackageMovesToOtherLicenseAfterParsingLicenseIDTag(t *testing.T) {
131	parser := tvParser2_1{
132		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
133		st:  psPackage2_1,
134		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
135	}
136	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
137
138	err := parser.parsePair2_1("LicenseID", "LicenseRef-TestLic")
139	if err != nil {
140		t.Errorf("got error when calling parsePair2_1: %v", err)
141	}
142	if parser.st != psOtherLicense2_1 {
143		t.Errorf("expected state to be %v, got %v", psOtherLicense2_1, parser.st)
144	}
145}
146
147func TestParser2_1PackageMovesToReviewAfterParsingReviewerTag(t *testing.T) {
148	parser := tvParser2_1{
149		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
150		st:  psPackage2_1,
151		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
152	}
153	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
154
155	err := parser.parsePair2_1("Reviewer", "Person: John Doe")
156	if err != nil {
157		t.Errorf("got error when calling parsePair2_1: %v", err)
158	}
159	if parser.st != psReview2_1 {
160		t.Errorf("expected state to be %v, got %v", psReview2_1, parser.st)
161	}
162}
163
164func TestParser2_1PackageStaysAfterParsingRelationshipTags(t *testing.T) {
165	parser := tvParser2_1{
166		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
167		st:  psPackage2_1,
168		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
169	}
170	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
171
172	err := parser.parsePair2_1("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-else")
173	if err != nil {
174		t.Errorf("got error when calling parsePair2_1: %v", err)
175	}
176	// state should remain unchanged
177	if parser.st != psPackage2_1 {
178		t.Errorf("expected state to be %v, got %v", psPackage2_1, parser.st)
179	}
180
181	err = parser.parsePair2_1("RelationshipComment", "blah")
182	if err != nil {
183		t.Errorf("got error when calling parsePair2_1: %v", err)
184	}
185	// state should still remain unchanged
186	if parser.st != psPackage2_1 {
187		t.Errorf("expected state to be %v, got %v", psPackage2_1, parser.st)
188	}
189}
190
191func TestParser2_1PackageStaysAfterParsingAnnotationTags(t *testing.T) {
192	parser := tvParser2_1{
193		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
194		st:  psPackage2_1,
195		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
196	}
197	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
198
199	err := parser.parsePair2_1("Annotator", "Person: John Doe ()")
200	if err != nil {
201		t.Errorf("got error when calling parsePair2_1: %v", err)
202	}
203	if parser.st != psPackage2_1 {
204		t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_1)
205	}
206
207	err = parser.parsePair2_1("AnnotationDate", "2018-09-15T00:36:00Z")
208	if err != nil {
209		t.Errorf("got error when calling parsePair2_1: %v", err)
210	}
211	if parser.st != psPackage2_1 {
212		t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_1)
213	}
214
215	err = parser.parsePair2_1("AnnotationType", "REVIEW")
216	if err != nil {
217		t.Errorf("got error when calling parsePair2_1: %v", err)
218	}
219	if parser.st != psPackage2_1 {
220		t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_1)
221	}
222
223	err = parser.parsePair2_1("SPDXREF", "SPDXRef-45")
224	if err != nil {
225		t.Errorf("got error when calling parsePair2_1: %v", err)
226	}
227	if parser.st != psPackage2_1 {
228		t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_1)
229	}
230
231	err = parser.parsePair2_1("AnnotationComment", "i guess i had something to say about this package")
232	if err != nil {
233		t.Errorf("got error when calling parsePair2_1: %v", err)
234	}
235	if parser.st != psPackage2_1 {
236		t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_1)
237	}
238}
239
240// ===== Package data section tests =====
241func TestParser2_1CanParsePackageTags(t *testing.T) {
242	parser := tvParser2_1{
243		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
244		st:  psPackage2_1,
245		pkg: &v2_1.Package{},
246	}
247
248	// should not yet be in Packages map, b/c no SPDX identifier
249	if len(parser.doc.Packages) != 0 {
250		t.Errorf("expected 0 packages, got %d", len(parser.doc.Packages))
251	}
252
253	// Package Name
254	err := parser.parsePairFromPackage2_1("PackageName", "p1")
255	if err != nil {
256		t.Errorf("expected nil error, got %v", err)
257	}
258	if parser.pkg.PackageName != "p1" {
259		t.Errorf("got %v for PackageName", parser.pkg.PackageName)
260	}
261	// still should not yet be in Packages map, b/c no SPDX identifier
262	if len(parser.doc.Packages) != 0 {
263		t.Errorf("expected 0 packages, got %d", len(parser.doc.Packages))
264	}
265
266	// Package SPDX Identifier
267	err = parser.parsePairFromPackage2_1("SPDXID", "SPDXRef-p1")
268	if err != nil {
269		t.Errorf("expected nil error, got %v", err)
270	}
271	// "SPDXRef-" prefix should be removed from the item
272	if parser.pkg.PackageSPDXIdentifier != "p1" {
273		t.Errorf("got %v for PackageSPDXIdentifier", parser.pkg.PackageSPDXIdentifier)
274	}
275	// and it should now be added to the Packages map
276	if len(parser.doc.Packages) != 1 {
277		t.Errorf("expected 1 package, got %d", len(parser.doc.Packages))
278	}
279	if parser.doc.Packages[0] != parser.pkg {
280		t.Errorf("expected to point to parser.pkg, got %v", parser.doc.Packages[0])
281	}
282
283	// Package Version
284	err = parser.parsePairFromPackage2_1("PackageVersion", "2.1.1")
285	if err != nil {
286		t.Errorf("expected nil error, got %v", err)
287	}
288	if parser.pkg.PackageVersion != "2.1.1" {
289		t.Errorf("got %v for PackageVersion", parser.pkg.PackageVersion)
290	}
291
292	// Package File Name
293	err = parser.parsePairFromPackage2_1("PackageFileName", "p1-2.1.1.tar.gz")
294	if err != nil {
295		t.Errorf("expected nil error, got %v", err)
296	}
297	if parser.pkg.PackageFileName != "p1-2.1.1.tar.gz" {
298		t.Errorf("got %v for PackageFileName", parser.pkg.PackageFileName)
299	}
300
301	// Package Supplier
302	// SKIP -- separate tests for subvalues below
303
304	// Package Originator
305	// SKIP -- separate tests for subvalues below
306
307	// Package Download Location
308	err = parser.parsePairFromPackage2_1("PackageDownloadLocation", "https://example.com/whatever")
309	if err != nil {
310		t.Errorf("expected nil error, got %v", err)
311	}
312	if parser.pkg.PackageDownloadLocation != "https://example.com/whatever" {
313		t.Errorf("got %v for PackageDownloadLocation", parser.pkg.PackageDownloadLocation)
314	}
315
316	// Files Analyzed
317	err = parser.parsePairFromPackage2_1("FilesAnalyzed", "false")
318	if err != nil {
319		t.Errorf("expected nil error, got %v", err)
320	}
321	if parser.pkg.FilesAnalyzed != false {
322		t.Errorf("got %v for FilesAnalyzed", parser.pkg.FilesAnalyzed)
323	}
324	if parser.pkg.IsFilesAnalyzedTagPresent != true {
325		t.Errorf("got %v for IsFilesAnalyzedTagPresent", parser.pkg.IsFilesAnalyzedTagPresent)
326	}
327
328	// Package Verification Code
329	// SKIP -- separate tests for "excludes", or not, below
330
331	// Package Checksums
332	codeSha1 := "85ed0817af83a24ad8da68c2b5094de69833983c"
333	sumSha1 := "SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c"
334	codeSha256 := "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"
335	sumSha256 := "SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"
336	codeMd5 := "624c1abb3664f4b35547e7c73864ad24"
337	sumMd5 := "MD5: 624c1abb3664f4b35547e7c73864ad24"
338	err = parser.parsePairFromPackage2_1("PackageChecksum", sumSha1)
339	if err != nil {
340		t.Errorf("expected nil error, got %v", err)
341	}
342	err = parser.parsePairFromPackage2_1("PackageChecksum", sumSha256)
343	if err != nil {
344		t.Errorf("expected nil error, got %v", err)
345	}
346	err = parser.parsePairFromPackage2_1("PackageChecksum", sumMd5)
347	if err != nil {
348		t.Errorf("expected nil error, got %v", err)
349	}
350
351	for _, checksum := range parser.pkg.PackageChecksums {
352		switch checksum.Algorithm {
353		case common.SHA1:
354			if checksum.Value != codeSha1 {
355				t.Errorf("expected %s for PackageChecksum SHA1, got %s", codeSha1, checksum.Value)
356			}
357		case common.SHA256:
358			if checksum.Value != codeSha256 {
359				t.Errorf("expected %s for PackageChecksum SHA256, got %s", codeSha256, checksum.Value)
360			}
361		case common.MD5:
362			if checksum.Value != codeMd5 {
363				t.Errorf("expected %s for PackageChecksum MD5, got %s", codeMd5, checksum.Value)
364			}
365		}
366	}
367
368	// Package Home Page
369	err = parser.parsePairFromPackage2_1("PackageHomePage", "https://example.com/whatever2")
370	if err != nil {
371		t.Errorf("expected nil error, got %v", err)
372	}
373	if parser.pkg.PackageHomePage != "https://example.com/whatever2" {
374		t.Errorf("got %v for PackageHomePage", parser.pkg.PackageHomePage)
375	}
376
377	// Package Source Info
378	err = parser.parsePairFromPackage2_1("PackageSourceInfo", "random comment")
379	if err != nil {
380		t.Errorf("expected nil error, got %v", err)
381	}
382	if parser.pkg.PackageSourceInfo != "random comment" {
383		t.Errorf("got %v for PackageSourceInfo", parser.pkg.PackageSourceInfo)
384	}
385
386	// Package License Concluded
387	err = parser.parsePairFromPackage2_1("PackageLicenseConcluded", "Apache-2.0 OR GPL-2.0-or-later")
388	if err != nil {
389		t.Errorf("expected nil error, got %v", err)
390	}
391	if parser.pkg.PackageLicenseConcluded != "Apache-2.0 OR GPL-2.0-or-later" {
392		t.Errorf("got %v for PackageLicenseConcluded", parser.pkg.PackageLicenseConcluded)
393	}
394
395	// All Licenses Info From Files
396	lics := []string{
397		"Apache-2.0",
398		"GPL-2.0-or-later",
399		"CC0-1.0",
400	}
401	for _, lic := range lics {
402		err = parser.parsePairFromPackage2_1("PackageLicenseInfoFromFiles", lic)
403		if err != nil {
404			t.Errorf("expected nil error, got %v", err)
405		}
406	}
407	for _, licWant := range lics {
408		flagFound := false
409		for _, licCheck := range parser.pkg.PackageLicenseInfoFromFiles {
410			if licWant == licCheck {
411				flagFound = true
412			}
413		}
414		if flagFound == false {
415			t.Errorf("didn't find %s in PackageLicenseInfoFromFiles", licWant)
416		}
417	}
418	if len(lics) != len(parser.pkg.PackageLicenseInfoFromFiles) {
419		t.Errorf("expected %d licenses in PackageLicenseInfoFromFiles, got %d", len(lics),
420			len(parser.pkg.PackageLicenseInfoFromFiles))
421	}
422
423	// Package License Declared
424	err = parser.parsePairFromPackage2_1("PackageLicenseDeclared", "Apache-2.0 OR GPL-2.0-or-later")
425	if err != nil {
426		t.Errorf("expected nil error, got %v", err)
427	}
428	if parser.pkg.PackageLicenseDeclared != "Apache-2.0 OR GPL-2.0-or-later" {
429		t.Errorf("got %v for PackageLicenseDeclared", parser.pkg.PackageLicenseDeclared)
430	}
431
432	// Package License Comments
433	err = parser.parsePairFromPackage2_1("PackageLicenseComments", "this is a license comment")
434	if err != nil {
435		t.Errorf("expected nil error, got %v", err)
436	}
437	if parser.pkg.PackageLicenseComments != "this is a license comment" {
438		t.Errorf("got %v for PackageLicenseComments", parser.pkg.PackageLicenseComments)
439	}
440
441	// Package Copyright Text
442	err = parser.parsePairFromPackage2_1("PackageCopyrightText", "Copyright (c) me myself and i")
443	if err != nil {
444		t.Errorf("expected nil error, got %v", err)
445	}
446	if parser.pkg.PackageCopyrightText != "Copyright (c) me myself and i" {
447		t.Errorf("got %v for PackageCopyrightText", parser.pkg.PackageCopyrightText)
448	}
449
450	// Package Summary
451	err = parser.parsePairFromPackage2_1("PackageSummary", "i wrote this package")
452	if err != nil {
453		t.Errorf("expected nil error, got %v", err)
454	}
455	if parser.pkg.PackageSummary != "i wrote this package" {
456		t.Errorf("got %v for PackageSummary", parser.pkg.PackageSummary)
457	}
458
459	// Package Description
460	err = parser.parsePairFromPackage2_1("PackageDescription", "i wrote this package a lot")
461	if err != nil {
462		t.Errorf("expected nil error, got %v", err)
463	}
464	if parser.pkg.PackageDescription != "i wrote this package a lot" {
465		t.Errorf("got %v for PackageDescription", parser.pkg.PackageDescription)
466	}
467
468	// Package Comment
469	err = parser.parsePairFromPackage2_1("PackageComment", "i scanned this package")
470	if err != nil {
471		t.Errorf("expected nil error, got %v", err)
472	}
473	if parser.pkg.PackageComment != "i scanned this package" {
474		t.Errorf("got %v for PackageComment", parser.pkg.PackageComment)
475	}
476
477	// Package External References and Comments
478	ref1 := "SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"
479	ref1Category := "SECURITY"
480	ref1Type := common.TypeSecurityCPE23Type
481	ref1Locator := "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"
482	ref1Comment := "this is comment #1"
483	ref2 := "OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3alpha"
484	ref2Category := "OTHER"
485	ref2Type := "LocationRef-acmeforge"
486	ref2Locator := "acmecorp/acmenator/4.1.3alpha"
487	ref2Comment := "this is comment #2"
488	err = parser.parsePairFromPackage2_1("ExternalRef", ref1)
489	if err != nil {
490		t.Errorf("expected nil error, got %v", err)
491	}
492	if len(parser.pkg.PackageExternalReferences) != 1 {
493		t.Errorf("expected 1 external reference, got %d", len(parser.pkg.PackageExternalReferences))
494	}
495	if parser.pkgExtRef == nil {
496		t.Errorf("expected non-nil pkgExtRef, got nil")
497	}
498	if parser.pkg.PackageExternalReferences[0] == nil {
499		t.Errorf("expected non-nil PackageExternalReferences[0], got nil")
500	}
501	if parser.pkgExtRef != parser.pkg.PackageExternalReferences[0] {
502		t.Errorf("expected pkgExtRef to match PackageExternalReferences[0], got no match")
503	}
504	err = parser.parsePairFromPackage2_1("ExternalRefComment", ref1Comment)
505	if err != nil {
506		t.Errorf("expected nil error, got %v", err)
507	}
508	err = parser.parsePairFromPackage2_1("ExternalRef", ref2)
509	if err != nil {
510		t.Errorf("expected nil error, got %v", err)
511	}
512	if len(parser.pkg.PackageExternalReferences) != 2 {
513		t.Errorf("expected 2 external references, got %d", len(parser.pkg.PackageExternalReferences))
514	}
515	if parser.pkgExtRef == nil {
516		t.Errorf("expected non-nil pkgExtRef, got nil")
517	}
518	if parser.pkg.PackageExternalReferences[1] == nil {
519		t.Errorf("expected non-nil PackageExternalReferences[1], got nil")
520	}
521	if parser.pkgExtRef != parser.pkg.PackageExternalReferences[1] {
522		t.Errorf("expected pkgExtRef to match PackageExternalReferences[1], got no match")
523	}
524	err = parser.parsePairFromPackage2_1("ExternalRefComment", ref2Comment)
525	if err != nil {
526		t.Errorf("expected nil error, got %v", err)
527	}
528	// finally, check these values
529	gotRef1 := parser.pkg.PackageExternalReferences[0]
530	if gotRef1.Category != ref1Category {
531		t.Errorf("expected ref1 category to be %s, got %s", gotRef1.Category, ref1Category)
532	}
533	if gotRef1.RefType != ref1Type {
534		t.Errorf("expected ref1 type to be %s, got %s", gotRef1.RefType, ref1Type)
535	}
536	if gotRef1.Locator != ref1Locator {
537		t.Errorf("expected ref1 locator to be %s, got %s", gotRef1.Locator, ref1Locator)
538	}
539	if gotRef1.ExternalRefComment != ref1Comment {
540		t.Errorf("expected ref1 comment to be %s, got %s", gotRef1.ExternalRefComment, ref1Comment)
541	}
542	gotRef2 := parser.pkg.PackageExternalReferences[1]
543	if gotRef2.Category != ref2Category {
544		t.Errorf("expected ref2 category to be %s, got %s", gotRef2.Category, ref2Category)
545	}
546	if gotRef2.RefType != ref2Type {
547		t.Errorf("expected ref2 type to be %s, got %s", gotRef2.RefType, ref2Type)
548	}
549	if gotRef2.Locator != ref2Locator {
550		t.Errorf("expected ref2 locator to be %s, got %s", gotRef2.Locator, ref2Locator)
551	}
552	if gotRef2.ExternalRefComment != ref2Comment {
553		t.Errorf("expected ref2 comment to be %s, got %s", gotRef2.ExternalRefComment, ref2Comment)
554	}
555
556}
557
558func TestParser2_1CanParsePackageSupplierPersonTag(t *testing.T) {
559	parser := tvParser2_1{
560		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
561		st:  psPackage2_1,
562		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
563	}
564	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
565
566	// Package Supplier: Person
567	err := parser.parsePairFromPackage2_1("PackageSupplier", "Person: John Doe")
568	if err != nil {
569		t.Errorf("expected nil error, got %v", err)
570	}
571	if parser.pkg.PackageSupplier.Supplier != "John Doe" {
572		t.Errorf("got %v for PackageSupplierPerson", parser.pkg.PackageSupplier.Supplier)
573	}
574}
575
576func TestParser2_1CanParsePackageSupplierOrganizationTag(t *testing.T) {
577	parser := tvParser2_1{
578		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
579		st:  psPackage2_1,
580		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
581	}
582	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
583
584	// Package Supplier: Organization
585	err := parser.parsePairFromPackage2_1("PackageSupplier", "Organization: John Doe, Inc.")
586	if err != nil {
587		t.Errorf("expected nil error, got %v", err)
588	}
589	if parser.pkg.PackageSupplier.Supplier != "John Doe, Inc." {
590		t.Errorf("got %v for PackageSupplierOrganization", parser.pkg.PackageSupplier.Supplier)
591	}
592}
593
594func TestParser2_1CanParsePackageSupplierNOASSERTIONTag(t *testing.T) {
595	parser := tvParser2_1{
596		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
597		st:  psPackage2_1,
598		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
599	}
600	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
601
602	// Package Supplier: NOASSERTION
603	err := parser.parsePairFromPackage2_1("PackageSupplier", "NOASSERTION")
604	if err != nil {
605		t.Errorf("expected nil error, got %v", err)
606	}
607	if parser.pkg.PackageSupplier.Supplier != "NOASSERTION" {
608		t.Errorf("got false for PackageSupplierNOASSERTION")
609	}
610}
611
612func TestParser2_1CanParsePackageOriginatorPersonTag(t *testing.T) {
613	parser := tvParser2_1{
614		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
615		st:  psPackage2_1,
616		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
617	}
618	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
619
620	// Package Originator: Person
621	err := parser.parsePairFromPackage2_1("PackageOriginator", "Person: John Doe")
622	if err != nil {
623		t.Errorf("expected nil error, got %v", err)
624	}
625	if parser.pkg.PackageOriginator.Originator != "John Doe" {
626		t.Errorf("got %v for PackageOriginatorPerson", parser.pkg.PackageOriginator.Originator)
627	}
628}
629
630func TestParser2_1CanParsePackageOriginatorOrganizationTag(t *testing.T) {
631	parser := tvParser2_1{
632		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
633		st:  psPackage2_1,
634		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
635	}
636	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
637
638	// Package Originator: Organization
639	err := parser.parsePairFromPackage2_1("PackageOriginator", "Organization: John Doe, Inc.")
640	if err != nil {
641		t.Errorf("expected nil error, got %v", err)
642	}
643	if parser.pkg.PackageOriginator.Originator != "John Doe, Inc." {
644		t.Errorf("got %v for PackageOriginatorOrganization", parser.pkg.PackageOriginator.Originator)
645	}
646}
647
648func TestParser2_1CanParsePackageOriginatorNOASSERTIONTag(t *testing.T) {
649	parser := tvParser2_1{
650		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
651		st:  psPackage2_1,
652		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
653	}
654	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
655
656	// Package Originator: NOASSERTION
657	err := parser.parsePairFromPackage2_1("PackageOriginator", "NOASSERTION")
658	if err != nil {
659		t.Errorf("expected nil error, got %v", err)
660	}
661	if parser.pkg.PackageOriginator.Originator != "NOASSERTION" {
662		t.Errorf("got false for PackageOriginatorNOASSERTION")
663	}
664}
665
666func TestParser2_1CanParsePackageVerificationCodeTagWithExcludes(t *testing.T) {
667	parser := tvParser2_1{
668		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
669		st:  psPackage2_1,
670		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
671	}
672	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
673
674	// Package Verification Code with excludes parenthetical
675	code := "d6a770ba38583ed4bb4525bd96e50461655d2758"
676	fileName := "./package.spdx"
677	fullCodeValue := "d6a770ba38583ed4bb4525bd96e50461655d2758 (excludes: ./package.spdx)"
678	err := parser.parsePairFromPackage2_1("PackageVerificationCode", fullCodeValue)
679	if err != nil {
680		t.Errorf("expected nil error, got %v", err)
681	}
682	if parser.pkg.PackageVerificationCode.Value != code {
683		t.Errorf("got %v for PackageVerificationCode", parser.pkg.PackageVerificationCode)
684	}
685	if len(parser.pkg.PackageVerificationCode.ExcludedFiles) != 1 || parser.pkg.PackageVerificationCode.ExcludedFiles[0] != fileName {
686		t.Errorf("got %v for PackageVerificationCodeExcludedFile", parser.pkg.PackageVerificationCode.ExcludedFiles)
687	}
688
689}
690
691func TestParser2_1CanParsePackageVerificationCodeTagWithoutExcludes(t *testing.T) {
692	parser := tvParser2_1{
693		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
694		st:  psPackage2_1,
695		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
696	}
697	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
698
699	// Package Verification Code without excludes parenthetical
700	code := "d6a770ba38583ed4bb4525bd96e50461655d2758"
701	err := parser.parsePairFromPackage2_1("PackageVerificationCode", code)
702	if err != nil {
703		t.Errorf("expected nil error, got %v", err)
704	}
705	if parser.pkg.PackageVerificationCode.Value != code {
706		t.Errorf("got %v for PackageVerificationCode", parser.pkg.PackageVerificationCode)
707	}
708	if len(parser.pkg.PackageVerificationCode.ExcludedFiles) != 0 {
709		t.Errorf("got %v for PackageVerificationCodeExcludedFile", parser.pkg.PackageVerificationCode.ExcludedFiles)
710	}
711
712}
713
714func TestPackageExternalRefPointerChangesAfterTags(t *testing.T) {
715	parser := tvParser2_1{
716		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
717		st:  psPackage2_1,
718		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
719	}
720	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
721
722	ref1 := "SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"
723	err := parser.parsePairFromPackage2_1("ExternalRef", ref1)
724	if err != nil {
725		t.Errorf("expected nil error, got %v", err)
726	}
727	if parser.pkgExtRef == nil {
728		t.Errorf("expected non-nil external reference pointer, got nil")
729	}
730
731	// now, a comment; pointer should go away
732	err = parser.parsePairFromPackage2_1("ExternalRefComment", "whatever")
733	if err != nil {
734		t.Errorf("expected nil error, got %v", err)
735	}
736	if parser.pkgExtRef != nil {
737		t.Errorf("expected nil external reference pointer, got non-nil")
738	}
739
740	ref2 := "Other LocationRef-something https://example.com/whatever"
741	err = parser.parsePairFromPackage2_1("ExternalRef", ref2)
742	if err != nil {
743		t.Errorf("expected nil error, got %v", err)
744	}
745	if parser.pkgExtRef == nil {
746		t.Errorf("expected non-nil external reference pointer, got nil")
747	}
748
749	// and some other random tag makes the pointer go away too
750	err = parser.parsePairFromPackage2_1("PackageSummary", "whatever")
751	if err != nil {
752		t.Errorf("expected nil error, got %v", err)
753	}
754	if parser.pkgExtRef != nil {
755		t.Errorf("expected nil external reference pointer, got non-nil")
756	}
757}
758
759func TestParser2_1PackageCreatesRelationshipInDocument(t *testing.T) {
760	parser := tvParser2_1{
761		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
762		st:  psPackage2_1,
763		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
764	}
765	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
766
767	err := parser.parsePair2_1("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-whatever")
768	if err != nil {
769		t.Errorf("got error when calling parsePair2_1: %v", err)
770	}
771	if parser.rln == nil {
772		t.Fatalf("parser didn't create and point to Relationship struct")
773	}
774	if parser.rln != parser.doc.Relationships[0] {
775		t.Errorf("pointer to new Relationship doesn't match idx 0 for doc.Relationships[]")
776	}
777}
778
779func TestParser2_1PackageCreatesAnnotationInDocument(t *testing.T) {
780	parser := tvParser2_1{
781		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
782		st:  psPackage2_1,
783		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
784	}
785	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
786
787	err := parser.parsePair2_1("Annotator", "Person: John Doe ()")
788	if err != nil {
789		t.Errorf("got error when calling parsePair2_1: %v", err)
790	}
791	if parser.ann == nil {
792		t.Fatalf("parser didn't create and point to Annotation struct")
793	}
794	if parser.ann != parser.doc.Annotations[0] {
795		t.Errorf("pointer to new Annotation doesn't match idx 0 for doc.Annotations[]")
796	}
797}
798
799func TestParser2_1PackageUnknownTagFails(t *testing.T) {
800	parser := tvParser2_1{
801		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
802		st:  psPackage2_1,
803		pkg: &v2_1.Package{PackageName: "p1", PackageSPDXIdentifier: "p1"},
804	}
805	parser.doc.Packages = append(parser.doc.Packages, parser.pkg)
806
807	err := parser.parsePairFromPackage2_1("blah", "something")
808	if err == nil {
809		t.Errorf("expected error from parsing unknown tag")
810	}
811}
812
813func TestParser2_1FailsIfInvalidSPDXIDInPackageSection(t *testing.T) {
814	parser := tvParser2_1{
815		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
816		st:  psPackage2_1,
817		pkg: &v2_1.Package{},
818	}
819
820	// start with Package Name
821	err := parser.parsePairFromPackage2_1("PackageName", "p1")
822	if err != nil {
823		t.Errorf("expected nil error, got %v", err)
824	}
825	// invalid ID format
826	err = parser.parsePairFromPackage2_1("SPDXID", "whoops")
827	if err == nil {
828		t.Errorf("expected non-nil error, got nil")
829	}
830}
831
832func TestParser2_1FailsIfInvalidPackageSupplierFormat(t *testing.T) {
833	parser := tvParser2_1{
834		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
835		st:  psPackage2_1,
836		pkg: &v2_1.Package{},
837	}
838
839	// start with Package Name
840	err := parser.parsePairFromPackage2_1("PackageName", "p1")
841	if err != nil {
842		t.Errorf("expected nil error, got %v", err)
843	}
844	// invalid supplier format
845	err = parser.parsePairFromPackage2_1("PackageSupplier", "whoops")
846	if err == nil {
847		t.Errorf("expected non-nil error, got nil")
848	}
849}
850
851func TestParser2_1FailsIfUnknownPackageSupplierType(t *testing.T) {
852	parser := tvParser2_1{
853		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
854		st:  psPackage2_1,
855		pkg: &v2_1.Package{},
856	}
857
858	// start with Package Name
859	err := parser.parsePairFromPackage2_1("PackageName", "p1")
860	if err != nil {
861		t.Errorf("expected nil error, got %v", err)
862	}
863	// invalid supplier type
864	err = parser.parsePairFromPackage2_1("PackageSupplier", "whoops: John Doe")
865	if err == nil {
866		t.Errorf("expected non-nil error, got nil")
867	}
868}
869
870func TestParser2_1FailsIfInvalidPackageOriginatorFormat(t *testing.T) {
871	parser := tvParser2_1{
872		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
873		st:  psPackage2_1,
874		pkg: &v2_1.Package{},
875	}
876
877	// start with Package Name
878	err := parser.parsePairFromPackage2_1("PackageName", "p1")
879	if err != nil {
880		t.Errorf("expected nil error, got %v", err)
881	}
882	// invalid originator format
883	err = parser.parsePairFromPackage2_1("PackageOriginator", "whoops")
884	if err == nil {
885		t.Errorf("expected non-nil error, got nil")
886	}
887}
888
889func TestParser2_1FailsIfUnknownPackageOriginatorType(t *testing.T) {
890	parser := tvParser2_1{
891		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
892		st:  psPackage2_1,
893		pkg: &v2_1.Package{},
894	}
895
896	// start with Package Name
897	err := parser.parsePairFromPackage2_1("PackageName", "p1")
898	if err != nil {
899		t.Errorf("expected nil error, got %v", err)
900	}
901	// invalid originator type
902	err = parser.parsePairFromPackage2_1("PackageOriginator", "whoops: John Doe")
903	if err == nil {
904		t.Errorf("expected non-nil error, got nil")
905	}
906}
907
908func TestParser2_1SetsFilesAnalyzedTagsCorrectly(t *testing.T) {
909	parser := tvParser2_1{
910		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
911		st:  psPackage2_1,
912		pkg: &v2_1.Package{},
913	}
914
915	// start with Package Name
916	err := parser.parsePairFromPackage2_1("PackageName", "p1")
917	if err != nil {
918		t.Errorf("expected nil error, got %v", err)
919	}
920	// set tag
921	err = parser.parsePairFromPackage2_1("FilesAnalyzed", "true")
922	if err != nil {
923		t.Errorf("expected nil error, got %v", err)
924	}
925	if parser.pkg.FilesAnalyzed != true {
926		t.Errorf("expected %v, got %v", true, parser.pkg.FilesAnalyzed)
927	}
928	if parser.pkg.IsFilesAnalyzedTagPresent != true {
929		t.Errorf("expected %v, got %v", true, parser.pkg.IsFilesAnalyzedTagPresent)
930	}
931}
932
933func TestParser2_1FailsIfInvalidPackageChecksumFormat(t *testing.T) {
934	parser := tvParser2_1{
935		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
936		st:  psPackage2_1,
937		pkg: &v2_1.Package{},
938	}
939
940	// start with Package Name
941	err := parser.parsePairFromPackage2_1("PackageName", "p1")
942	if err != nil {
943		t.Errorf("expected nil error, got %v", err)
944	}
945	// invalid checksum format
946	err = parser.parsePairFromPackage2_1("PackageChecksum", "whoops")
947	if err == nil {
948		t.Errorf("expected non-nil error, got nil")
949	}
950}
951
952func TestParser2_1FailsIfInvalidPackageChecksumType(t *testing.T) {
953	parser := tvParser2_1{
954		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
955		st:  psPackage2_1,
956		pkg: &v2_1.Package{},
957	}
958
959	// start with Package Name
960	err := parser.parsePairFromPackage2_1("PackageName", "p1")
961	if err != nil {
962		t.Errorf("expected nil error, got %v", err)
963	}
964	// invalid checksum type
965	err = parser.parsePairFromPackage2_1("PackageChecksum", "whoops: blah")
966	if err == nil {
967		t.Errorf("expected non-nil error, got nil")
968	}
969}
970
971func TestParser2_1FailsIfInvalidExternalRefFormat(t *testing.T) {
972	parser := tvParser2_1{
973		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
974		st:  psPackage2_1,
975		pkg: &v2_1.Package{},
976	}
977
978	// start with Package Name
979	err := parser.parsePairFromPackage2_1("PackageName", "p1")
980	if err != nil {
981		t.Errorf("expected nil error, got %v", err)
982	}
983	// invalid external ref format
984	err = parser.parsePairFromPackage2_1("ExternalRef", "whoops")
985	if err == nil {
986		t.Errorf("expected non-nil error, got nil")
987	}
988}
989
990func TestParser2_1FailsIfExternalRefCommentBeforeExternalRef(t *testing.T) {
991	parser := tvParser2_1{
992		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
993		st:  psPackage2_1,
994		pkg: &v2_1.Package{},
995	}
996
997	// start with Package Name
998	err := parser.parsePairFromPackage2_1("PackageName", "p1")
999	if err != nil {
1000		t.Errorf("expected nil error, got %v", err)
1001	}
1002	// external ref comment before external ref
1003	err = parser.parsePairFromPackage2_1("ExternalRefComment", "whoops")
1004	if err == nil {
1005		t.Errorf("expected non-nil error, got nil")
1006	}
1007}
1008
1009// ===== Helper function tests =====
1010
1011func TestCanCheckAndExtractExcludesFilenameAndCode(t *testing.T) {
1012	code := "d6a770ba38583ed4bb4525bd96e50461655d2758"
1013	fileName := "./package.spdx"
1014	fullCodeValue := "d6a770ba38583ed4bb4525bd96e50461655d2758 (excludes: ./package.spdx)"
1015
1016	gotCode := extractCodeAndExcludes(fullCodeValue)
1017	if gotCode.Value != code {
1018		t.Errorf("got %v for gotCode", gotCode)
1019	}
1020	if len(gotCode.ExcludedFiles) != 1 || gotCode.ExcludedFiles[0] != fileName {
1021		t.Errorf("got %v for gotFileName", gotCode.ExcludedFiles)
1022	}
1023}
1024
1025func TestCanExtractPackageExternalReference(t *testing.T) {
1026	ref1 := "SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"
1027	category := "SECURITY"
1028	refType := common.TypeSecurityCPE23Type
1029	location := "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"
1030
1031	gotCategory, gotRefType, gotLocation, err := extractPackageExternalReference(ref1)
1032	if err != nil {
1033		t.Errorf("got non-nil error: %v", err)
1034	}
1035	if gotCategory != category {
1036		t.Errorf("expected category %s, got %s", category, gotCategory)
1037	}
1038	if gotRefType != refType {
1039		t.Errorf("expected refType %s, got %s", refType, gotRefType)
1040	}
1041	if gotLocation != location {
1042		t.Errorf("expected location %s, got %s", location, gotLocation)
1043	}
1044}
1045
1046func TestCanExtractPackageExternalReferenceWithExtraWhitespace(t *testing.T) {
1047	ref1 := "  SECURITY    \t cpe23Type   cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* \t "
1048	category := "SECURITY"
1049	refType := common.TypeSecurityCPE23Type
1050	location := "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"
1051
1052	gotCategory, gotRefType, gotLocation, err := extractPackageExternalReference(ref1)
1053	if err != nil {
1054		t.Errorf("got non-nil error: %v", err)
1055	}
1056	if gotCategory != category {
1057		t.Errorf("expected category %s, got %s", category, gotCategory)
1058	}
1059	if gotRefType != refType {
1060		t.Errorf("expected refType %s, got %s", refType, gotRefType)
1061	}
1062	if gotLocation != location {
1063		t.Errorf("expected location %s, got %s", location, gotLocation)
1064	}
1065}
1066
1067func TestFailsPackageExternalRefWithInvalidFormat(t *testing.T) {
1068	_, _, _, err := extractPackageExternalReference("whoops")
1069	if err == nil {
1070		t.Errorf("expected non-nil error, got nil")
1071	}
1072}
1073
1074func TestParser2_1PackageWithoutSpdxIdentifierThrowsError(t *testing.T) {
1075	// More than one package, the previous package doesn't contain the SPDXID
1076	pkgOldName := "p1"
1077	parser := tvParser2_1{
1078		doc: &v2_1.Document{Packages: []*v2_1.Package{}},
1079		st:  psPackage2_1,
1080		pkg: &v2_1.Package{PackageName: pkgOldName},
1081	}
1082	pkgOld := parser.pkg
1083	parser.doc.Packages = append(parser.doc.Packages, pkgOld)
1084	// the Document's Packages should have this one only
1085	if parser.doc.Packages[0] != pkgOld {
1086		t.Errorf("expected package %v, got %v", pkgOld, parser.doc.Packages[0])
1087	}
1088	if len(parser.doc.Packages) != 1 {
1089		t.Errorf("expected 1 package, got %d", len(parser.doc.Packages))
1090	}
1091
1092	pkgName := "p2"
1093	err := parser.parsePair2_1("PackageName", pkgName)
1094	if err == nil {
1095		t.Errorf("package without SPDX Identifier getting accepted")
1096	}
1097}
1098