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