// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later package parser2v3 import ( "fmt" "testing" "github.com/spdx/tools-golang/spdx/common" "github.com/spdx/tools-golang/spdx/v2_3" ) // ===== Parser file section state change tests ===== func TestParser2_3FileStartsNewFileAfterParsingFileNameTag(t *testing.T) { // create the first file fileOldName := "f1.txt" parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: fileOldName, FileSPDXIdentifier: "f1"}, } fileOld := parser.file parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, fileOld) // the Package's Files should have this one only if len(parser.pkg.Files) != 1 { t.Fatalf("expected 1 file, got %d", len(parser.pkg.Files)) } if parser.pkg.Files[0] != fileOld { t.Errorf("expected file %v in Files[f1], got %v", fileOld, parser.pkg.Files[0]) } if parser.pkg.Files[0].FileName != fileOldName { t.Errorf("expected file name %s in Files[f1], got %s", fileOldName, parser.pkg.Files[0].FileName) } // now add a new file fileName := "f2.txt" err := parser.parsePair2_3("FileName", fileName) if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // state should be correct if parser.st != psFile2_3 { t.Errorf("expected state to be %v, got %v", psFile2_3, parser.st) } // and a file should be created if parser.file == nil { t.Fatalf("parser didn't create new file") } // and the file name should be as expected if parser.file.FileName != fileName { t.Errorf("expected file name %s, got %s", fileName, parser.file.FileName) } // and the Package's Files should still be of size 1 and not have this new // one yet, since it hasn't seen an SPDX identifier if len(parser.pkg.Files) != 1 { t.Fatalf("expected 1 file, got %d", len(parser.pkg.Files)) } if parser.pkg.Files[0] != fileOld { t.Errorf("expected file %v in Files[f1], got %v", fileOld, parser.pkg.Files[0]) } if parser.pkg.Files[0].FileName != fileOldName { t.Errorf("expected file name %s in Files[f1], got %s", fileOldName, parser.pkg.Files[0].FileName) } // now parse an SPDX identifier tag err = parser.parsePair2_3("SPDXID", "SPDXRef-f2ID") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // and the Package's Files should now be of size 2 and have this new one if len(parser.pkg.Files) != 2 { t.Fatalf("expected 2 files, got %d", len(parser.pkg.Files)) } if parser.pkg.Files[0] != fileOld { t.Errorf("expected file %v in Files[f1], got %v", fileOld, parser.pkg.Files[0]) } if parser.pkg.Files[0].FileName != fileOldName { t.Errorf("expected file name %s in Files[f1], got %s", fileOldName, parser.pkg.Files[0].FileName) } if parser.pkg.Files[1] != parser.file { t.Errorf("expected file %v in Files[f2ID], got %v", parser.file, parser.pkg.Files[1]) } if parser.pkg.Files[1].FileName != fileName { t.Errorf("expected file name %s in Files[f2ID], got %s", fileName, parser.pkg.Files[1].FileName) } } func TestParser2_3FileAddsToPackageOrUnpackagedFiles(t *testing.T) { // start with no packages parser := tvParser2_3{ doc: &v2_3.Document{}, st: psCreationInfo2_3, } // add a file and SPDX identifier fileName := "f2.txt" err := parser.parsePair2_3("FileName", fileName) if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } err = parser.parsePair2_3("SPDXID", "SPDXRef-f2ID") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } fileOld := parser.file // should have been added to Files if len(parser.doc.Files) != 1 { t.Fatalf("expected 1 file in Files, got %d", len(parser.doc.Files)) } if parser.doc.Files[0] != fileOld { t.Errorf("expected file %v in Files[f2ID], got %v", fileOld, parser.doc.Files[0]) } // now create a package and a new file err = parser.parsePair2_3("PackageName", "package1") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } err = parser.parsePair2_3("SPDXID", "SPDXRef-pkg1") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } err = parser.parsePair2_3("FileName", "f3.txt") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } err = parser.parsePair2_3("SPDXID", "SPDXRef-f3ID") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // Files should still be size 1 and have old file only if len(parser.doc.Files) != 1 { t.Fatalf("expected 1 file in Files, got %d", len(parser.doc.Files)) } if parser.doc.Files[0] != fileOld { t.Errorf("expected file %v in Files[f2ID], got %v", fileOld, parser.doc.Files[0]) } // and new package should have gotten the new file if len(parser.pkg.Files) != 1 { t.Fatalf("expected 1 file in Files, got %d", len(parser.pkg.Files)) } if parser.pkg.Files[0] != parser.file { t.Errorf("expected file %v in Files[f3ID], got %v", parser.file, parser.pkg.Files[0]) } } func TestParser2_3FileStartsNewPackageAfterParsingPackageNameTag(t *testing.T) { // create the first file and package p1Name := "package1" f1Name := "f1.txt" parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: p1Name, PackageSPDXIdentifier: "package1", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: f1Name, FileSPDXIdentifier: "f1"}, } p1 := parser.pkg f1 := parser.file parser.doc.Packages = append(parser.doc.Packages, p1) parser.pkg.Files = append(parser.pkg.Files, f1) // now add a new package p2Name := "package2" err := parser.parsePair2_3("PackageName", p2Name) if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // state should go back to Package if parser.st != psPackage2_3 { t.Errorf("expected state to be %v, got %v", psPackage2_3, parser.st) } // and a package should be created if parser.pkg == nil { t.Fatalf("parser didn't create new pkg") } // and the package name should be as expected if parser.pkg.PackageName != p2Name { t.Errorf("expected package name %s, got %s", p2Name, parser.pkg.PackageName) } // and the package should default to true for FilesAnalyzed if parser.pkg.FilesAnalyzed != true { t.Errorf("expected FilesAnalyzed to default to true, got false") } if parser.pkg.IsFilesAnalyzedTagPresent != false { t.Errorf("expected IsFilesAnalyzedTagPresent to default to false, got true") } // and the new Package should have no files if len(parser.pkg.Files) != 0 { t.Errorf("Expected no files in pkg.Files, got %d", len(parser.pkg.Files)) } // and the Document's Packages should still be of size 1 and not have this // new one, because no SPDX identifier has been seen yet if len(parser.doc.Packages) != 1 { t.Fatalf("expected 1 package, got %d", len(parser.doc.Packages)) } if parser.doc.Packages[0] != p1 { t.Errorf("Expected package %v in Packages[package1], got %v", p1, parser.doc.Packages[0]) } if parser.doc.Packages[0].PackageName != p1Name { t.Errorf("expected package name %s in Packages[package1], got %s", p1Name, parser.doc.Packages[0].PackageName) } // and the first Package's Files should be of size 1 and have f1 only if len(parser.doc.Packages[0].Files) != 1 { t.Errorf("Expected 1 file in Packages[package1].Files, got %d", len(parser.doc.Packages[0].Files)) } if parser.doc.Packages[0].Files[0] != f1 { t.Errorf("Expected file %v in Files[f1], got %v", f1, parser.doc.Packages[0].Files[0]) } if parser.doc.Packages[0].Files[0].FileName != f1Name { t.Errorf("expected file name %s in Files[f1], got %s", f1Name, parser.doc.Packages[0].Files[0].FileName) } // and the current file should be nil if parser.file != nil { t.Errorf("Expected nil for parser.file, got %v", parser.file) } } func TestParser2_3FileMovesToSnippetAfterParsingSnippetSPDXIDTag(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) fileCurrent := parser.file err := parser.parsePair2_3("SnippetSPDXID", "SPDXRef-Test1") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // state should be correct if parser.st != psSnippet2_3 { t.Errorf("expected state to be %v, got %v", psSnippet2_3, parser.st) } // and current file should remain what it was if parser.file != fileCurrent { t.Fatalf("expected file to remain %v, got %v", fileCurrent, parser.file) } } func TestParser2_3FileMovesToOtherLicenseAfterParsingLicenseIDTag(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePair2_3("LicenseID", "LicenseRef-TestLic") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psOtherLicense2_3 { t.Errorf("expected state to be %v, got %v", psOtherLicense2_3, parser.st) } } func TestParser2_3FileMovesToReviewAfterParsingReviewerTag(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePair2_3("Reviewer", "Person: John Doe") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psReview2_3 { t.Errorf("expected state to be %v, got %v", psReview2_3, parser.st) } } func TestParser2_3FileStaysAfterParsingRelationshipTags(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePair2_3("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-else") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // state should remain unchanged if parser.st != psFile2_3 { t.Errorf("expected state to be %v, got %v", psFile2_3, parser.st) } err = parser.parsePair2_3("RelationshipComment", "blah") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } // state should still remain unchanged if parser.st != psFile2_3 { t.Errorf("expected state to be %v, got %v", psFile2_3, parser.st) } } func TestParser2_3FileStaysAfterParsingAnnotationTags(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePair2_3("Annotator", "Person: John Doe ()") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psFile2_3 { t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_3) } err = parser.parsePair2_3("AnnotationDate", "2018-09-15T00:36:00Z") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psFile2_3 { t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_3) } err = parser.parsePair2_3("AnnotationType", "REVIEW") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psFile2_3 { t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_3) } err = parser.parsePair2_3("SPDXREF", "SPDXRef-45") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psFile2_3 { t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_3) } err = parser.parsePair2_3("AnnotationComment", "i guess i had something to say about this particular file") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.st != psFile2_3 { t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_3) } } // ===== File data section tests ===== func TestParser2_3CanParseFileTags(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) // File Name err := parser.parsePairFromFile2_3("FileName", "f1.txt") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.FileName != "f1.txt" { t.Errorf("got %v for FileName", parser.file.FileName) } // should not yet be added to the Packages file list, because we haven't // seen an SPDX identifier yet if len(parser.pkg.Files) != 0 { t.Errorf("expected 0 files, got %d", len(parser.pkg.Files)) } // File SPDX Identifier err = parser.parsePairFromFile2_3("SPDXID", "SPDXRef-f1") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.FileSPDXIdentifier != "f1" { t.Errorf("got %v for FileSPDXIdentifier", parser.file.FileSPDXIdentifier) } // should now be added to the Packages file list if len(parser.pkg.Files) != 1 { t.Errorf("expected 1 file, got %d", len(parser.pkg.Files)) } if parser.pkg.Files[0] != parser.file { t.Errorf("expected Files[f1] to be %v, got %v", parser.file, parser.pkg.Files[0]) } // File Type fileTypes := []string{ "TEXT", "DOCUMENTATION", } for _, ty := range fileTypes { err = parser.parsePairFromFile2_3("FileType", ty) if err != nil { t.Errorf("expected nil error, got %v", err) } } for _, typeWant := range fileTypes { flagFound := false for _, typeCheck := range parser.file.FileTypes { if typeWant == typeCheck { flagFound = true } } if flagFound == false { t.Errorf("didn't find %s in FileTypes", typeWant) } } if len(fileTypes) != len(parser.file.FileTypes) { t.Errorf("expected %d types in FileTypes, got %d", len(fileTypes), len(parser.file.FileTypes)) } testChecksums := map[common.ChecksumAlgorithm]string{ "MD5": "624c1abb3664f4b35547e7c73864ad24", "SHA1": "85ed0817af83a24ad8da68c2b5094de69833983c", "SHA256": "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd", "SHA512": "4ced3267f5ed38df65ceebc43e97aa6c2948cc7ef3288c2e5074e7df7fab544cc93339604513ea5f65616f9ed1c48581465043c8a9b693ef20fd4fddaf25e1b9", "BLAKE3": "981d32ed7aad9e408c5c36f6346c915ba11c2bd8b3e7d44902a11d7a141abdd9", } for algo, tc := range testChecksums { if err := parser.parsePairFromFile2_3( "FileChecksum", fmt.Sprintf("%s: %s", algo, tc)); err != nil { t.Errorf("expected error, got %v", err) } } for _, checksum := range parser.file.Checksums { if checksum.Value != testChecksums[checksum.Algorithm] { t.Errorf( "expected %s for FileChecksum%s, got %s", testChecksums[checksum.Algorithm], checksum.Algorithm, checksum.Value, ) } } // Concluded License err = parser.parsePairFromFile2_3("LicenseConcluded", "Apache-2.0 OR GPL-2.0-or-later") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.LicenseConcluded != "Apache-2.0 OR GPL-2.0-or-later" { t.Errorf("got %v for LicenseConcluded", parser.file.LicenseConcluded) } // License Information in File lics := []string{ "Apache-2.0", "GPL-2.0-or-later", "CC0-1.0", } for _, lic := range lics { err = parser.parsePairFromFile2_3("LicenseInfoInFile", lic) if err != nil { t.Errorf("expected nil error, got %v", err) } } for _, licWant := range lics { flagFound := false for _, licCheck := range parser.file.LicenseInfoInFiles { if licWant == licCheck { flagFound = true } } if flagFound == false { t.Errorf("didn't find %s in LicenseInfoInFiles", licWant) } } if len(lics) != len(parser.file.LicenseInfoInFiles) { t.Errorf("expected %d licenses in LicenseInfoInFiles, got %d", len(lics), len(parser.file.LicenseInfoInFiles)) } // Comments on License err = parser.parsePairFromFile2_3("LicenseComments", "this is a comment") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.LicenseComments != "this is a comment" { t.Errorf("got %v for LicenseComments", parser.file.LicenseComments) } // Copyright Text err = parser.parsePairFromFile2_3("FileCopyrightText", "copyright (c) me") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.FileCopyrightText != "copyright (c) me" { t.Errorf("got %v for FileCopyrightText", parser.file.FileCopyrightText) } // Artifact of Projects: Name, HomePage and URI // Artifact set 1 err = parser.parsePairFromFile2_3("ArtifactOfProjectName", "project1") if err != nil { t.Errorf("expected nil error, got %v", err) } err = parser.parsePairFromFile2_3("ArtifactOfProjectHomePage", "http://example.com/1/") if err != nil { t.Errorf("expected nil error, got %v", err) } err = parser.parsePairFromFile2_3("ArtifactOfProjectURI", "http://example.com/1/uri.whatever") if err != nil { t.Errorf("expected nil error, got %v", err) } // Artifact set 2 -- just name err = parser.parsePairFromFile2_3("ArtifactOfProjectName", "project2") if err != nil { t.Errorf("expected nil error, got %v", err) } // Artifact set 3 -- just name and home page err = parser.parsePairFromFile2_3("ArtifactOfProjectName", "project3") if err != nil { t.Errorf("expected nil error, got %v", err) } err = parser.parsePairFromFile2_3("ArtifactOfProjectHomePage", "http://example.com/3/") if err != nil { t.Errorf("expected nil error, got %v", err) } // Artifact set 4 -- just name and URI err = parser.parsePairFromFile2_3("ArtifactOfProjectName", "project4") if err != nil { t.Errorf("expected nil error, got %v", err) } err = parser.parsePairFromFile2_3("ArtifactOfProjectURI", "http://example.com/4/uri.whatever") if err != nil { t.Errorf("expected nil error, got %v", err) } if len(parser.file.ArtifactOfProjects) != 4 { t.Fatalf("expected len %d, got %d", 4, len(parser.file.ArtifactOfProjects)) } aop := parser.file.ArtifactOfProjects[0] if aop.Name != "project1" { t.Errorf("expected %v, got %v", "project1", aop.Name) } if aop.HomePage != "http://example.com/1/" { t.Errorf("expected %v, got %v", "http://example.com/1/", aop.HomePage) } if aop.URI != "http://example.com/1/uri.whatever" { t.Errorf("expected %v, got %v", "http://example.com/1/uri.whatever", aop.URI) } aop = parser.file.ArtifactOfProjects[1] if aop.Name != "project2" { t.Errorf("expected %v, got %v", "project2", aop.Name) } if aop.HomePage != "" { t.Errorf("expected %v, got %v", "", aop.HomePage) } if aop.URI != "" { t.Errorf("expected %v, got %v", "", aop.URI) } aop = parser.file.ArtifactOfProjects[2] if aop.Name != "project3" { t.Errorf("expected %v, got %v", "project3", aop.Name) } if aop.HomePage != "http://example.com/3/" { t.Errorf("expected %v, got %v", "http://example.com/3/", aop.HomePage) } if aop.URI != "" { t.Errorf("expected %v, got %v", "", aop.URI) } aop = parser.file.ArtifactOfProjects[3] if aop.Name != "project4" { t.Errorf("expected %v, got %v", "project4", aop.Name) } if aop.HomePage != "" { t.Errorf("expected %v, got %v", "", aop.HomePage) } if aop.URI != "http://example.com/4/uri.whatever" { t.Errorf("expected %v, got %v", "http://example.com/4/uri.whatever", aop.URI) } // File Comment err = parser.parsePairFromFile2_3("FileComment", "this is a comment") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.FileComment != "this is a comment" { t.Errorf("got %v for FileComment", parser.file.FileComment) } // File Notice err = parser.parsePairFromFile2_3("FileNotice", "this is a Notice") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.file.FileNotice != "this is a Notice" { t.Errorf("got %v for FileNotice", parser.file.FileNotice) } // File Contributor contribs := []string{ "John Doe jdoe@example.com", "EvilCorp", } for _, contrib := range contribs { err = parser.parsePairFromFile2_3("FileContributor", contrib) if err != nil { t.Errorf("expected nil error, got %v", err) } } for _, contribWant := range contribs { flagFound := false for _, contribCheck := range parser.file.FileContributors { if contribWant == contribCheck { flagFound = true } } if flagFound == false { t.Errorf("didn't find %s in FileContributors", contribWant) } } if len(contribs) != len(parser.file.FileContributors) { t.Errorf("expected %d contribenses in FileContributors, got %d", len(contribs), len(parser.file.FileContributors)) } // File Dependencies deps := []string{ "f-1.txt", "g.txt", } for _, dep := range deps { err = parser.parsePairFromFile2_3("FileDependency", dep) if err != nil { t.Errorf("expected nil error, got %v", err) } } for _, depWant := range deps { flagFound := false for _, depCheck := range parser.file.FileDependencies { if depWant == depCheck { flagFound = true } } if flagFound == false { t.Errorf("didn't find %s in FileDependency", depWant) } } if len(deps) != len(parser.file.FileDependencies) { t.Errorf("expected %d depenses in FileDependency, got %d", len(deps), len(parser.file.FileDependencies)) } // File Attribution Texts attrs := []string{ "Include this notice in all advertising materials", "This is a \nmulti-line string", } for _, attr := range attrs { err = parser.parsePairFromFile2_3("FileAttributionText", attr) if err != nil { t.Errorf("expected nil error, got %v", err) } } for _, attrWant := range attrs { flagFound := false for _, attrCheck := range parser.file.FileAttributionTexts { if attrWant == attrCheck { flagFound = true } } if flagFound == false { t.Errorf("didn't find %s in FileAttributionText", attrWant) } } if len(attrs) != len(parser.file.FileAttributionTexts) { t.Errorf("expected %d attribution texts in FileAttributionTexts, got %d", len(attrs), len(parser.file.FileAttributionTexts)) } } func TestParser2_3FileCreatesRelationshipInDocument(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePair2_3("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-whatever") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.rln == nil { t.Fatalf("parser didn't create and point to Relationship struct") } if parser.rln != parser.doc.Relationships[0] { t.Errorf("pointer to new Relationship doesn't match idx 0 for doc.Relationships[]") } } func TestParser2_3FileCreatesAnnotationInDocument(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePair2_3("Annotator", "Person: John Doe ()") if err != nil { t.Errorf("got error when calling parsePair2_3: %v", err) } if parser.ann == nil { t.Fatalf("parser didn't create and point to Annotation struct") } if parser.ann != parser.doc.Annotations[0] { t.Errorf("pointer to new Annotation doesn't match idx 0 for doc.Annotations[]") } } func TestParser2_3FileUnknownTagFails(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePairFromFile2_3("blah", "something") if err == nil { t.Errorf("expected error from parsing unknown tag") } } func TestFileAOPPointerChangesAfterTags(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, file: &v2_3.File{FileName: "f1.txt", FileSPDXIdentifier: "f1"}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) parser.pkg.Files = append(parser.pkg.Files, parser.file) err := parser.parsePairFromFile2_3("ArtifactOfProjectName", "project1") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.fileAOP == nil { t.Errorf("expected non-nil AOP pointer, got nil") } curPtr := parser.fileAOP // now, a home page; pointer should stay err = parser.parsePairFromFile2_3("ArtifactOfProjectHomePage", "http://example.com/1/") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.fileAOP != curPtr { t.Errorf("expected no change in AOP pointer, was %v, got %v", curPtr, parser.fileAOP) } // a URI; pointer should stay err = parser.parsePairFromFile2_3("ArtifactOfProjectURI", "http://example.com/1/uri.whatever") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.fileAOP != curPtr { t.Errorf("expected no change in AOP pointer, was %v, got %v", curPtr, parser.fileAOP) } // now, another artifact name; pointer should change but be non-nil // now, a home page; pointer should stay err = parser.parsePairFromFile2_3("ArtifactOfProjectName", "project2") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.fileAOP == curPtr { t.Errorf("expected change in AOP pointer, got no change") } // finally, an unrelated tag; pointer should go away err = parser.parsePairFromFile2_3("FileComment", "whatever") if err != nil { t.Errorf("expected nil error, got %v", err) } if parser.fileAOP != nil { t.Errorf("expected nil AOP pointer, got %v", parser.fileAOP) } } func TestParser2_3FailsIfInvalidSPDXIDInFileSection(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) // start with File Name err := parser.parsePairFromFile2_3("FileName", "f1.txt") if err != nil { t.Errorf("expected nil error, got %v", err) } // invalid SPDX Identifier err = parser.parsePairFromFile2_3("SPDXID", "whoops") if err == nil { t.Errorf("expected non-nil error, got nil") } } func TestParser2_3FailsIfInvalidChecksumFormatInFileSection(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) // start with File Name err := parser.parsePairFromFile2_3("FileName", "f1.txt") if err != nil { t.Errorf("expected nil error, got %v", err) } // invalid format for checksum line, missing colon err = parser.parsePairFromFile2_3("FileChecksum", "SHA1 85ed0817af83a24ad8da68c2b5094de69833983c") if err == nil { t.Errorf("expected non-nil error, got nil") } } func TestParser2_1FailsIfUnknownChecksumTypeInFileSection(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) // start with File Name err := parser.parsePairFromFile2_3("FileName", "f1.txt") if err != nil { t.Errorf("expected nil error, got %v", err) } // unknown checksum type err = parser.parsePairFromFile2_3("FileChecksum", "Special: 85ed0817af83a24ad8da68c2b5094de69833983c") if err == nil { t.Errorf("expected non-nil error, got nil") } } func TestParser2_3FailsIfArtifactHomePageBeforeArtifactName(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) // start with File Name err := parser.parsePairFromFile2_3("FileName", "f1.txt") if err != nil { t.Errorf("expected nil error, got %v", err) } // artifact home page appears before artifact name err = parser.parsePairFromFile2_3("ArtifactOfProjectHomePage", "https://example.com") if err == nil { t.Errorf("expected non-nil error, got nil") } } func TestParser2_3FailsIfArtifactURIBeforeArtifactName(t *testing.T) { parser := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, pkg: &v2_3.Package{PackageName: "test", PackageSPDXIdentifier: "test", Files: []*v2_3.File{}}, } parser.doc.Packages = append(parser.doc.Packages, parser.pkg) // start with File Name err := parser.parsePairFromFile2_3("FileName", "f1.txt") if err != nil { t.Errorf("expected nil error, got %v", err) } // artifact home page appears before artifact name err = parser.parsePairFromFile2_3("ArtifactOfProjectURI", "https://example.com") if err == nil { t.Errorf("expected non-nil error, got nil") } } func TestParser2_3FilesWithoutSpdxIdThrowError(t *testing.T) { // case 1: The previous file (packaged or unpackaged) does not contain spdx ID parser1 := tvParser2_3{ doc: &v2_3.Document{Packages: []*v2_3.Package{}}, st: psFile2_3, file: &v2_3.File{FileName: "FileName"}, } err := parser1.parsePair2_3("FileName", "f2") if err == nil { t.Errorf("file without SPDX Identifier getting accepted") } // case 2: Invalid file with snippet // Last unpackaged file before the snippet start fileName := "f2.txt" sid1 := common.ElementID("s1") parser2 := tvParser2_3{ doc: &v2_3.Document{}, st: psCreationInfo2_3, file: &v2_3.File{FileName: fileName}, } err = parser2.parsePair2_3("SnippetSPDXID", string(sid1)) if err == nil { t.Errorf("file without SPDX Identifier getting accepted") } // case 3: Invalid File without snippets // Last unpackaged file before the package starts // Last file of a package and New package starts parser3 := tvParser2_3{ doc: &v2_3.Document{}, st: psCreationInfo2_3, } fileName = "f3.txt" err = parser3.parsePair2_3("FileName", fileName) if err != nil { t.Errorf("%s", err) } err = parser3.parsePair2_3("PackageName", "p2") if err == nil { t.Errorf("file without SPDX Identifier getting accepted") } }