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