xref: /aosp_15_r20/external/spdx-tools/tvsaver/saver2v3/save_package_test.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2
3package saver2v3
4
5import (
6	"bytes"
7	"testing"
8
9	"github.com/spdx/tools-golang/spdx/common"
10	"github.com/spdx/tools-golang/spdx/v2_3"
11)
12
13// ===== Package section Saver tests =====
14func TestSaver2_3PackageSavesTextCombo1(t *testing.T) {
15	// include package external refs
16	// test Supplier:Organization, Originator:Person
17	// FilesAnalyzed true, IsFilesAnalyzedTagPresent true
18	// PackageVerificationCodeExcludedFile has string
19
20	// NOTE, this is an entirely made up CPE and the format is likely invalid
21	per1 := &v2_3.PackageExternalReference{
22		Category:           "SECURITY",
23		RefType:            "cpe22Type",
24		Locator:            "cpe:/a:john_doe_inc:p1:0.1.0",
25		ExternalRefComment: "this is an external ref comment #1",
26	}
27
28	// NOTE, this is an entirely made up NPM
29	per2 := &v2_3.PackageExternalReference{
30		Category: "PACKAGE-MANAGER",
31		RefType:  "npm",
32		Locator:  "[email protected]",
33		ExternalRefComment: `this is a
34multi-line external ref comment`,
35	}
36
37	// NOTE, this is an entirely made up SWH persistent ID
38	per3 := &v2_3.PackageExternalReference{
39		Category: "PERSISTENT-ID",
40		RefType:  "swh",
41		Locator:  "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2",
42		// no ExternalRefComment for this one
43	}
44
45	per4 := &v2_3.PackageExternalReference{
46		Category: "OTHER",
47		RefType:  "anything",
48		Locator:  "anything-without-spaces-can-go-here",
49		// no ExternalRefComment for this one
50	}
51
52	pkg := &v2_3.Package{
53		PackageName:               "p1",
54		PackageSPDXIdentifier:     common.ElementID("p1"),
55		PackageVersion:            "0.1.0",
56		PackageFileName:           "p1-0.1.0-master.tar.gz",
57		PackageSupplier:           &common.Supplier{SupplierType: "Organization", Supplier: "John Doe, Inc."},
58		PackageOriginator:         &common.Originator{Originator: "John Doe", OriginatorType: "Person"},
59		PackageDownloadLocation:   "http://example.com/p1/p1-0.1.0-master.tar.gz",
60		FilesAnalyzed:             true,
61		IsFilesAnalyzedTagPresent: true,
62		PackageVerificationCode: &common.PackageVerificationCode{
63			Value:         "0123456789abcdef0123456789abcdef01234567",
64			ExcludedFiles: []string{"p1-0.1.0.spdx"},
65		},
66		PackageChecksums: []common.Checksum{
67			{
68				Algorithm: common.SHA1,
69				Value:     "85ed0817af83a24ad8da68c2b5094de69833983c",
70			},
71			{
72				Algorithm: common.SHA256,
73				Value:     "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
74			},
75			{
76				Algorithm: common.MD5,
77				Value:     "624c1abb3664f4b35547e7c73864ad24",
78			},
79		},
80		PackageHomePage:         "http://example.com/p1",
81		PackageSourceInfo:       "this is a source comment",
82		PackageLicenseConcluded: "GPL-2.0-or-later",
83		PackageLicenseInfoFromFiles: []string{
84			"Apache-1.1",
85			"Apache-2.0",
86			"GPL-2.0-or-later",
87		},
88		PackageLicenseDeclared:  "Apache-2.0 OR GPL-2.0-or-later",
89		PackageLicenseComments:  "this is a license comment(s)",
90		PackageCopyrightText:    "Copyright (c) John Doe, Inc.",
91		PackageSummary:          "this is a summary comment",
92		PackageDescription:      "this is a description comment",
93		PackageComment:          "this is a comment comment",
94		PackageAttributionTexts: []string{"Include this notice in all advertising materials"},
95		PackageExternalReferences: []*v2_3.PackageExternalReference{
96			per1,
97			per2,
98			per3,
99			per4,
100		},
101		PrimaryPackagePurpose: "LIBRARY",
102		BuiltDate:             "2021-09-15T02:38:00Z",
103		ValidUntilDate:        "2022-10-15T02:38:00Z",
104		ReleaseDate:           "2021-10-15T02:38:00Z",
105	}
106
107	// what we want to get, as a buffer of bytes
108	want := bytes.NewBufferString(`PackageName: p1
109SPDXID: SPDXRef-p1
110PackageVersion: 0.1.0
111PackageFileName: p1-0.1.0-master.tar.gz
112PackageSupplier: Organization: John Doe, Inc.
113PackageOriginator: Person: John Doe
114PackageDownloadLocation: http://example.com/p1/p1-0.1.0-master.tar.gz
115PrimaryPackagePurpose: LIBRARY
116ReleaseDate: 2021-10-15T02:38:00Z
117BuiltDate: 2021-09-15T02:38:00Z
118ValidUntilDate: 2022-10-15T02:38:00Z
119FilesAnalyzed: true
120PackageVerificationCode: 0123456789abcdef0123456789abcdef01234567 (excludes: p1-0.1.0.spdx)
121PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c
122PackageChecksum: SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd
123PackageChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24
124PackageHomePage: http://example.com/p1
125PackageSourceInfo: this is a source comment
126PackageLicenseConcluded: GPL-2.0-or-later
127PackageLicenseInfoFromFiles: Apache-1.1
128PackageLicenseInfoFromFiles: Apache-2.0
129PackageLicenseInfoFromFiles: GPL-2.0-or-later
130PackageLicenseDeclared: Apache-2.0 OR GPL-2.0-or-later
131PackageLicenseComments: this is a license comment(s)
132PackageCopyrightText: Copyright (c) John Doe, Inc.
133PackageSummary: this is a summary comment
134PackageDescription: this is a description comment
135PackageComment: this is a comment comment
136ExternalRef: SECURITY cpe22Type cpe:/a:john_doe_inc:p1:0.1.0
137ExternalRefComment: this is an external ref comment #1
138ExternalRef: PACKAGE-MANAGER npm p1@0.1.0
139ExternalRefComment: <text>this is a
140multi-line external ref comment</text>
141ExternalRef: PERSISTENT-ID swh swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2
142ExternalRef: OTHER anything anything-without-spaces-can-go-here
143PackageAttributionText: Include this notice in all advertising materials
144
145`)
146
147	// render as buffer of bytes
148	var got bytes.Buffer
149	err := renderPackage2_3(pkg, &got)
150	if err != nil {
151		t.Errorf("Expected nil error, got %v", err)
152	}
153
154	// check that they match
155	c := bytes.Compare(want.Bytes(), got.Bytes())
156	if c != 0 {
157		t.Errorf("Expected %v, got %v", want.String(), got.String())
158	}
159}
160
161func TestSaver2_3PackageSavesTextCombo2(t *testing.T) {
162	// no package external refs
163	// test Supplier:NOASSERTION, Originator:Organization
164	// FilesAnalyzed true, IsFilesAnalyzedTagPresent false
165	// PackageVerificationCodeExcludedFile is empty
166
167	pkg := &v2_3.Package{
168		PackageName:               "p1",
169		PackageSPDXIdentifier:     common.ElementID("p1"),
170		PackageVersion:            "0.1.0",
171		PackageFileName:           "p1-0.1.0-master.tar.gz",
172		PackageSupplier:           &common.Supplier{Supplier: "NOASSERTION"},
173		PackageOriginator:         &common.Originator{OriginatorType: "Organization", Originator: "John Doe, Inc."},
174		PackageDownloadLocation:   "http://example.com/p1/p1-0.1.0-master.tar.gz",
175		FilesAnalyzed:             true,
176		IsFilesAnalyzedTagPresent: false,
177		PackageVerificationCode:   &common.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
178		PackageChecksums: []common.Checksum{
179			{
180				Algorithm: common.SHA1,
181				Value:     "85ed0817af83a24ad8da68c2b5094de69833983c",
182			},
183			{
184				Algorithm: common.SHA256,
185				Value:     "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
186			},
187			{
188				Algorithm: common.MD5,
189				Value:     "624c1abb3664f4b35547e7c73864ad24",
190			},
191		},
192		PackageHomePage:         "http://example.com/p1",
193		PackageSourceInfo:       "this is a source comment",
194		PackageLicenseConcluded: "GPL-2.0-or-later",
195		PackageLicenseInfoFromFiles: []string{
196			"Apache-1.1",
197			"Apache-2.0",
198			"GPL-2.0-or-later",
199		},
200		PackageLicenseDeclared:  "Apache-2.0 OR GPL-2.0-or-later",
201		PackageLicenseComments:  "this is a license comment(s)",
202		PackageCopyrightText:    "Copyright (c) John Doe, Inc.",
203		PackageSummary:          "this is a summary comment",
204		PackageDescription:      "this is a description comment",
205		PackageComment:          "this is a comment comment",
206		PackageAttributionTexts: []string{"Include this notice in all advertising materials"},
207	}
208
209	// what we want to get, as a buffer of bytes
210	want := bytes.NewBufferString(`PackageName: p1
211SPDXID: SPDXRef-p1
212PackageVersion: 0.1.0
213PackageFileName: p1-0.1.0-master.tar.gz
214PackageSupplier: NOASSERTION
215PackageOriginator: Organization: John Doe, Inc.
216PackageDownloadLocation: http://example.com/p1/p1-0.1.0-master.tar.gz
217PackageVerificationCode: 0123456789abcdef0123456789abcdef01234567
218PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c
219PackageChecksum: SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd
220PackageChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24
221PackageHomePage: http://example.com/p1
222PackageSourceInfo: this is a source comment
223PackageLicenseConcluded: GPL-2.0-or-later
224PackageLicenseInfoFromFiles: Apache-1.1
225PackageLicenseInfoFromFiles: Apache-2.0
226PackageLicenseInfoFromFiles: GPL-2.0-or-later
227PackageLicenseDeclared: Apache-2.0 OR GPL-2.0-or-later
228PackageLicenseComments: this is a license comment(s)
229PackageCopyrightText: Copyright (c) John Doe, Inc.
230PackageSummary: this is a summary comment
231PackageDescription: this is a description comment
232PackageComment: this is a comment comment
233PackageAttributionText: Include this notice in all advertising materials
234
235`)
236
237	// render as buffer of bytes
238	var got bytes.Buffer
239	err := renderPackage2_3(pkg, &got)
240	if err != nil {
241		t.Errorf("Expected nil error, got %v", err)
242	}
243
244	// check that they match
245	c := bytes.Compare(want.Bytes(), got.Bytes())
246	if c != 0 {
247		t.Errorf("Expected %v, got %v", want.String(), got.String())
248	}
249}
250
251func TestSaver2_3PackageSavesTextCombo3(t *testing.T) {
252	// no package external refs
253	// test Supplier:Person, Originator:NOASSERTION
254	// FilesAnalyzed false, IsFilesAnalyzedTagPresent true
255	// PackageVerificationCodeExcludedFile is empty
256	// three PackageAttributionTexts, one with multi-line text
257
258	pkg := &v2_3.Package{
259		PackageName:               "p1",
260		PackageSPDXIdentifier:     common.ElementID("p1"),
261		PackageVersion:            "0.1.0",
262		PackageFileName:           "p1-0.1.0-master.tar.gz",
263		PackageSupplier:           &common.Supplier{Supplier: "John Doe", SupplierType: "Person"},
264		PackageOriginator:         &common.Originator{Originator: "NOASSERTION"},
265		PackageDownloadLocation:   "http://example.com/p1/p1-0.1.0-master.tar.gz",
266		FilesAnalyzed:             false,
267		IsFilesAnalyzedTagPresent: true,
268		// NOTE that verification code MUST be omitted from output
269		// since FilesAnalyzed is false
270		PackageVerificationCode: &common.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
271		PackageChecksums: []common.Checksum{
272			{
273				Algorithm: common.SHA1,
274				Value:     "85ed0817af83a24ad8da68c2b5094de69833983c",
275			},
276			{
277				Algorithm: common.SHA256,
278				Value:     "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
279			},
280			{
281				Algorithm: common.MD5,
282				Value:     "624c1abb3664f4b35547e7c73864ad24",
283			},
284		},
285		PackageHomePage:         "http://example.com/p1",
286		PackageSourceInfo:       "this is a source comment",
287		PackageLicenseConcluded: "GPL-2.0-or-later",
288		// NOTE that license info from files MUST be omitted from output
289		// since FilesAnalyzed is false
290		PackageLicenseInfoFromFiles: []string{
291			"Apache-1.1",
292			"Apache-2.0",
293			"GPL-2.0-or-later",
294		},
295		PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
296		PackageLicenseComments: "this is a license comment(s)",
297		PackageCopyrightText:   "Copyright (c) John Doe, Inc.",
298		PackageSummary:         "this is a summary comment",
299		PackageDescription:     "this is a description comment",
300		PackageComment:         "this is a comment comment",
301		PackageAttributionTexts: []string{
302			"Include this notice in all advertising materials",
303			"and also this notice",
304			`and this multi-line notice
305which goes across two lines`,
306		},
307	}
308
309	// what we want to get, as a buffer of bytes
310	want := bytes.NewBufferString(`PackageName: p1
311SPDXID: SPDXRef-p1
312PackageVersion: 0.1.0
313PackageFileName: p1-0.1.0-master.tar.gz
314PackageSupplier: Person: John Doe
315PackageOriginator: NOASSERTION
316PackageDownloadLocation: http://example.com/p1/p1-0.1.0-master.tar.gz
317FilesAnalyzed: false
318PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c
319PackageChecksum: SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd
320PackageChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24
321PackageHomePage: http://example.com/p1
322PackageSourceInfo: this is a source comment
323PackageLicenseConcluded: GPL-2.0-or-later
324PackageLicenseDeclared: Apache-2.0 OR GPL-2.0-or-later
325PackageLicenseComments: this is a license comment(s)
326PackageCopyrightText: Copyright (c) John Doe, Inc.
327PackageSummary: this is a summary comment
328PackageDescription: this is a description comment
329PackageComment: this is a comment comment
330PackageAttributionText: Include this notice in all advertising materials
331PackageAttributionText: and also this notice
332PackageAttributionText: <text>and this multi-line notice
333which goes across two lines</text>
334
335`)
336
337	// render as buffer of bytes
338	var got bytes.Buffer
339	err := renderPackage2_3(pkg, &got)
340	if err != nil {
341		t.Errorf("Expected nil error, got %v", err)
342	}
343
344	// check that they match
345	c := bytes.Compare(want.Bytes(), got.Bytes())
346	if c != 0 {
347		t.Errorf("Expected %v, got %v", want.String(), got.String())
348	}
349}
350
351func TestSaver2_3PackageSaveOmitsOptionalFieldsIfEmpty(t *testing.T) {
352	pkg := &v2_3.Package{
353		PackageName:               "p1",
354		PackageSPDXIdentifier:     common.ElementID("p1"),
355		PackageDownloadLocation:   "http://example.com/p1/p1-0.1.0-master.tar.gz",
356		FilesAnalyzed:             false,
357		IsFilesAnalyzedTagPresent: true,
358		// NOTE that verification code MUST be omitted from output,
359		// even if present in model, since FilesAnalyzed is false
360		PackageLicenseConcluded: "GPL-2.0-or-later",
361		// NOTE that license info from files MUST be omitted from output
362		// even if present in model, since FilesAnalyzed is false
363		PackageLicenseInfoFromFiles: []string{
364			"Apache-1.1",
365			"Apache-2.0",
366			"GPL-2.0-or-later",
367		},
368		PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
369		PackageCopyrightText:   "Copyright (c) John Doe, Inc.",
370	}
371
372	// what we want to get, as a buffer of bytes
373	want := bytes.NewBufferString(`PackageName: p1
374SPDXID: SPDXRef-p1
375PackageDownloadLocation: http://example.com/p1/p1-0.1.0-master.tar.gz
376FilesAnalyzed: false
377PackageLicenseConcluded: GPL-2.0-or-later
378PackageLicenseDeclared: Apache-2.0 OR GPL-2.0-or-later
379PackageCopyrightText: Copyright (c) John Doe, Inc.
380
381`)
382
383	// render as buffer of bytes
384	var got bytes.Buffer
385	err := renderPackage2_3(pkg, &got)
386	if err != nil {
387		t.Errorf("Expected nil error, got %v", err)
388	}
389
390	// check that they match
391	c := bytes.Compare(want.Bytes(), got.Bytes())
392	if c != 0 {
393		t.Errorf("Expected %v, got %v", want.String(), got.String())
394	}
395}
396
397func TestSaver2_3PackageSavesFilesIfPresent(t *testing.T) {
398	f1 := &v2_3.File{
399		FileName:           "/tmp/whatever1.txt",
400		FileSPDXIdentifier: common.ElementID("File1231"),
401		Checksums: []common.Checksum{
402			{
403				Algorithm: common.SHA1,
404				Value:     "85ed0817af83a24ad8da68c2b5094de69833983c",
405			},
406		},
407		LicenseConcluded:   "Apache-2.0",
408		LicenseInfoInFiles: []string{"Apache-2.0"},
409		FileCopyrightText:  "Copyright (c) Jane Doe",
410	}
411
412	f2 := &v2_3.File{
413		FileName:           "/tmp/whatever2.txt",
414		FileSPDXIdentifier: common.ElementID("File1232"),
415		Checksums: []common.Checksum{
416			{
417				Algorithm: common.SHA1,
418				Value:     "85ed0817af83a24ad8da68c2b5094de69833983d",
419			},
420		},
421		LicenseConcluded:   "MIT",
422		LicenseInfoInFiles: []string{"MIT"},
423		FileCopyrightText:  "Copyright (c) John Doe",
424	}
425
426	pkg := &v2_3.Package{
427		PackageName:               "p1",
428		PackageSPDXIdentifier:     common.ElementID("p1"),
429		PackageDownloadLocation:   "http://example.com/p1/p1-0.1.0-master.tar.gz",
430		FilesAnalyzed:             false,
431		IsFilesAnalyzedTagPresent: true,
432		// NOTE that verification code MUST be omitted from output,
433		// even if present in model, since FilesAnalyzed is false
434		PackageLicenseConcluded: "GPL-2.0-or-later",
435		// NOTE that license info from files MUST be omitted from output
436		// even if present in model, since FilesAnalyzed is false
437		PackageLicenseInfoFromFiles: []string{
438			"Apache-1.1",
439			"Apache-2.0",
440			"GPL-2.0-or-later",
441		},
442		PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
443		PackageCopyrightText:   "Copyright (c) John Doe, Inc.",
444		Files: []*v2_3.File{
445			f1,
446			f2,
447		},
448	}
449
450	// what we want to get, as a buffer of bytes
451	want := bytes.NewBufferString(`PackageName: p1
452SPDXID: SPDXRef-p1
453PackageDownloadLocation: http://example.com/p1/p1-0.1.0-master.tar.gz
454FilesAnalyzed: false
455PackageLicenseConcluded: GPL-2.0-or-later
456PackageLicenseDeclared: Apache-2.0 OR GPL-2.0-or-later
457PackageCopyrightText: Copyright (c) John Doe, Inc.
458
459FileName: /tmp/whatever1.txt
460SPDXID: SPDXRef-File1231
461FileChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c
462LicenseConcluded: Apache-2.0
463LicenseInfoInFile: Apache-2.0
464FileCopyrightText: Copyright (c) Jane Doe
465
466FileName: /tmp/whatever2.txt
467SPDXID: SPDXRef-File1232
468FileChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983d
469LicenseConcluded: MIT
470LicenseInfoInFile: MIT
471FileCopyrightText: Copyright (c) John Doe
472
473`)
474
475	// render as buffer of bytes
476	var got bytes.Buffer
477	err := renderPackage2_3(pkg, &got)
478	if err != nil {
479		t.Errorf("Expected nil error, got %v", err)
480	}
481
482	// check that they match
483	c := bytes.Compare(want.Bytes(), got.Bytes())
484	if c != 0 {
485		t.Errorf("Expected %v, got %v", want.String(), got.String())
486	}
487}
488
489func TestSaver2_3PackageWrapsMultiLine(t *testing.T) {
490	pkg := &v2_3.Package{
491		PackageName:               "p1",
492		PackageSPDXIdentifier:     common.ElementID("p1"),
493		PackageDownloadLocation:   "http://example.com/p1/p1-0.1.0-master.tar.gz",
494		FilesAnalyzed:             false,
495		IsFilesAnalyzedTagPresent: true,
496		PackageLicenseConcluded:   "GPL-2.0-or-later",
497		PackageLicenseInfoFromFiles: []string{
498			"Apache-1.1",
499			"Apache-2.0",
500			"GPL-2.0-or-later",
501		},
502		PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
503		PackageCopyrightText: `Copyright (c) John Doe, Inc.
504Copyright Jane Doe`,
505	}
506
507	// what we want to get, as a buffer of bytes
508	want := bytes.NewBufferString(`PackageName: p1
509SPDXID: SPDXRef-p1
510PackageDownloadLocation: http://example.com/p1/p1-0.1.0-master.tar.gz
511FilesAnalyzed: false
512PackageLicenseConcluded: GPL-2.0-or-later
513PackageLicenseDeclared: Apache-2.0 OR GPL-2.0-or-later
514PackageCopyrightText: <text>Copyright (c) John Doe, Inc.
515Copyright Jane Doe</text>
516
517`)
518
519	// render as buffer of bytes
520	var got bytes.Buffer
521	err := renderPackage2_3(pkg, &got)
522	if err != nil {
523		t.Errorf("Expected nil error, got %v", err)
524	}
525
526	// check that they match
527	c := bytes.Compare(want.Bytes(), got.Bytes())
528	if c != 0 {
529		t.Errorf("Expected %v, got %v", want.String(), got.String())
530	}
531}
532