blob: 2a8c094d2a92c903ae61156792b72a5a0be75ee1 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
package parser2v1
import (
"testing"
"github.com/spdx/tools-golang/spdx"
)
// ===== Parser creation info state change tests =====
func TestParser2_1CIMovesToPackageAfterParsingPackageNameTag(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
pkgName := "testPkg"
err := parser.parsePair2_1("PackageName", pkgName)
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
// state should be correct
if parser.st != psPackage2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psPackage2_1)
}
// and a package should be created
if parser.pkg == nil {
t.Fatalf("parser didn't create new package")
}
// and the package name should be as expected
if parser.pkg.PackageName != pkgName {
t.Errorf("expected package name %s, got %s", pkgName, 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 package should NOT be in the SPDX Document's map of packages,
// because it doesn't have an SPDX identifier yet
if len(parser.doc.Packages) != 0 {
t.Errorf("expected 0 packages, got %d", len(parser.doc.Packages))
}
}
func TestParser2_1CIMovesToFileAfterParsingFileNameTagWithNoPackages(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("FileName", "testFile")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
// state should be correct
if parser.st != psFile2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psFile2_1)
}
// and current package should be nil, meaning Files are placed in the
// UnpackagedFiles map instead of in a Package
if parser.pkg != nil {
t.Fatalf("expected pkg to be nil, got non-nil pkg")
}
}
func TestParser2_1CIMovesToOtherLicenseAfterParsingLicenseIDTag(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("LicenseID", "LicenseRef-TestLic")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psOtherLicense2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psOtherLicense2_1)
}
}
func TestParser2_1CIMovesToReviewAfterParsingReviewerTag(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("Reviewer", "Person: John Doe")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psReview2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psReview2_1)
}
}
func TestParser2_1CIStaysAfterParsingRelationshipTags(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-else")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
err = parser.parsePair2_1("RelationshipComment", "blah")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
}
func TestParser2_1CIStaysAfterParsingAnnotationTags(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("Annotator", "Person: John Doe ()")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
err = parser.parsePair2_1("AnnotationDate", "2018-09-15T00:36:00Z")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
err = parser.parsePair2_1("AnnotationType", "REVIEW")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
err = parser.parsePair2_1("SPDXREF", "SPDXRef-45")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
err = parser.parsePair2_1("AnnotationComment", "i guess i had something to say about this spdx file")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %v", err)
}
if parser.st != psCreationInfo2_1 {
t.Errorf("parser is in state %v, expected %v", parser.st, psCreationInfo2_1)
}
}
func TestParser2_1FailsParsingCreationInfoWithInvalidState(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psPackage2_1,
}
err := parser.parsePairFromCreationInfo2_1("SPDXVersion", "SPDX-2.1")
if err == nil {
t.Errorf("expected non-nil error, got nil")
}
}
// ===== Creation Info section tests =====
func TestParser2_1HasCreationInfoAfterCallToParseFirstTag(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePairFromCreationInfo2_1("SPDXVersion", "SPDX-2.1")
if err != nil {
t.Errorf("got error when calling parsePairFromCreationInfo2_1: %v", err)
}
if parser.doc.CreationInfo == nil {
t.Errorf("doc.CreationInfo is still nil after parsing first pair")
}
}
func TestParser2_1CanParseCreationInfoTags(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
// SPDX Version
err := parser.parsePairFromCreationInfo2_1("SPDXVersion", "SPDX-2.1")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.SPDXVersion != "SPDX-2.1" {
t.Errorf("got %v for SPDXVersion", parser.doc.CreationInfo.SPDXVersion)
}
// Data License
err = parser.parsePairFromCreationInfo2_1("DataLicense", "CC0-1.0")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.DataLicense != "CC0-1.0" {
t.Errorf("got %v for DataLicense", parser.doc.CreationInfo.DataLicense)
}
// SPDX Identifier
err = parser.parsePairFromCreationInfo2_1("SPDXID", "SPDXRef-DOCUMENT")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.SPDXIdentifier != "DOCUMENT" {
t.Errorf("got %v for SPDXIdentifier", parser.doc.CreationInfo.SPDXIdentifier)
}
// Document Name
err = parser.parsePairFromCreationInfo2_1("DocumentName", "xyz-2.1.5")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.DocumentName != "xyz-2.1.5" {
t.Errorf("got %v for DocumentName", parser.doc.CreationInfo.DocumentName)
}
// Document Namespace
err = parser.parsePairFromCreationInfo2_1("DocumentNamespace", "http://example.com/xyz-2.1.5.spdx")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.DocumentNamespace != "http://example.com/xyz-2.1.5.spdx" {
t.Errorf("got %v for DocumentNamespace", parser.doc.CreationInfo.DocumentNamespace)
}
// External Document Reference
refs := []string{
"DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759",
"DocumentRef-xyz-2.1.2 http://example.com/xyz-2.1.2 SHA1:d6a770ba38583ed4bb4525bd96e50461655d2760",
}
wantRef0 := spdx.ExternalDocumentRef2_1{
DocumentRefID: "spdx-tool-1.2",
URI: "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301",
Alg: "SHA1",
Checksum: "d6a770ba38583ed4bb4525bd96e50461655d2759",
}
wantRef1 := spdx.ExternalDocumentRef2_1{
DocumentRefID: "xyz-2.1.2",
URI: "http://example.com/xyz-2.1.2",
Alg: "SHA1",
Checksum: "d6a770ba38583ed4bb4525bd96e50461655d2760",
}
err = parser.parsePairFromCreationInfo2_1("ExternalDocumentRef", refs[0])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
err = parser.parsePairFromCreationInfo2_1("ExternalDocumentRef", refs[1])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if len(parser.doc.CreationInfo.ExternalDocumentReferences) != 2 {
t.Errorf("got %d ExternalDocumentReferences, expected %d", len(parser.doc.CreationInfo.ExternalDocumentReferences), 2)
}
gotRef0 := parser.doc.CreationInfo.ExternalDocumentReferences["spdx-tool-1.2"]
if gotRef0.DocumentRefID != wantRef0.DocumentRefID ||
gotRef0.URI != wantRef0.URI ||
gotRef0.Alg != wantRef0.Alg ||
gotRef0.Checksum != wantRef0.Checksum {
t.Errorf("got %#v for ExternalDocumentReferences[0], wanted %#v", gotRef0, wantRef0)
}
gotRef1 := parser.doc.CreationInfo.ExternalDocumentReferences["xyz-2.1.2"]
if gotRef1.DocumentRefID != wantRef1.DocumentRefID ||
gotRef1.URI != wantRef1.URI ||
gotRef1.Alg != wantRef1.Alg ||
gotRef1.Checksum != wantRef1.Checksum {
t.Errorf("got %#v for ExternalDocumentReferences[1], wanted %#v", gotRef1, wantRef1)
}
// License List Version
err = parser.parsePairFromCreationInfo2_1("LicenseListVersion", "2.2")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.LicenseListVersion != "2.2" {
t.Errorf("got %v for LicenseListVersion", parser.doc.CreationInfo.LicenseListVersion)
}
// Creators: Persons
refPersons := []string{
"Person: Person A",
"Person: Person B",
}
err = parser.parsePairFromCreationInfo2_1("Creator", refPersons[0])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
err = parser.parsePairFromCreationInfo2_1("Creator", refPersons[1])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if len(parser.doc.CreationInfo.CreatorPersons) != 2 ||
parser.doc.CreationInfo.CreatorPersons[0] != "Person A" ||
parser.doc.CreationInfo.CreatorPersons[1] != "Person B" {
t.Errorf("got %v for CreatorPersons", parser.doc.CreationInfo.CreatorPersons)
}
// Creators: Organizations
refOrgs := []string{
"Organization: Organization A",
"Organization: Organization B",
}
err = parser.parsePairFromCreationInfo2_1("Creator", refOrgs[0])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
err = parser.parsePairFromCreationInfo2_1("Creator", refOrgs[1])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if len(parser.doc.CreationInfo.CreatorOrganizations) != 2 ||
parser.doc.CreationInfo.CreatorOrganizations[0] != "Organization A" ||
parser.doc.CreationInfo.CreatorOrganizations[1] != "Organization B" {
t.Errorf("got %v for CreatorOrganizations", parser.doc.CreationInfo.CreatorOrganizations)
}
// Creators: Tools
refTools := []string{
"Tool: Tool A",
"Tool: Tool B",
}
err = parser.parsePairFromCreationInfo2_1("Creator", refTools[0])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
err = parser.parsePairFromCreationInfo2_1("Creator", refTools[1])
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if len(parser.doc.CreationInfo.CreatorTools) != 2 ||
parser.doc.CreationInfo.CreatorTools[0] != "Tool A" ||
parser.doc.CreationInfo.CreatorTools[1] != "Tool B" {
t.Errorf("got %v for CreatorTools", parser.doc.CreationInfo.CreatorTools)
}
// Created date
err = parser.parsePairFromCreationInfo2_1("Created", "2018-09-10T11:46:00Z")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.Created != "2018-09-10T11:46:00Z" {
t.Errorf("got %v for Created", parser.doc.CreationInfo.Created)
}
// Creator Comment
err = parser.parsePairFromCreationInfo2_1("CreatorComment", "Blah whatever")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.CreatorComment != "Blah whatever" {
t.Errorf("got %v for CreatorComment", parser.doc.CreationInfo.CreatorComment)
}
// Document Comment
err = parser.parsePairFromCreationInfo2_1("DocumentComment", "Blah whatever")
if err != nil {
t.Errorf("expected nil error, got %v", err)
}
if parser.doc.CreationInfo.DocumentComment != "Blah whatever" {
t.Errorf("got %v for DocumentComment", parser.doc.CreationInfo.DocumentComment)
}
}
func TestParser2_1InvalidCreatorTagsFail(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePairFromCreationInfo2_1("Creator", "blah: somebody")
if err == nil {
t.Errorf("expected error from parsing invalid Creator format, got nil")
}
err = parser.parsePairFromCreationInfo2_1("Creator", "Tool with no colons")
if err == nil {
t.Errorf("expected error from parsing invalid Creator format, got nil")
}
}
func TestParser2_1CreatorTagWithMultipleColonsPasses(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePairFromCreationInfo2_1("Creator", "Tool: tool1:2:3")
if err != nil {
t.Errorf("unexpected error from parsing valid Creator format")
}
}
func TestParser2_1CIUnknownTagFails(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePairFromCreationInfo2_1("blah", "something")
if err == nil {
t.Errorf("expected error from parsing unknown tag")
}
}
func TestParser2_1CICreatesRelationship(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("Relationship", "SPDXRef-blah CONTAINS SPDXRef-blah-whatever")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %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_1CICreatesAnnotation(t *testing.T) {
parser := tvParser2_1{
doc: &spdx.Document2_1{},
st: psCreationInfo2_1,
}
err := parser.parsePair2_1("Annotator", "Person: John Doe ()")
if err != nil {
t.Errorf("got error when calling parsePair2_1: %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[]")
}
}
// ===== Helper function tests =====
func TestCanExtractExternalDocumentReference(t *testing.T) {
refstring := "DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1:d6a770ba38583ed4bb4525bd96e50461655d2759"
wantDocumentRefID := "spdx-tool-1.2"
wantURI := "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301"
wantAlg := "SHA1"
wantChecksum := "d6a770ba38583ed4bb4525bd96e50461655d2759"
gotDocumentRefID, gotURI, gotAlg, gotChecksum, err := extractExternalDocumentReference(refstring)
if err != nil {
t.Errorf("got non-nil error: %v", err)
}
if wantDocumentRefID != gotDocumentRefID {
t.Errorf("wanted document ref ID %s, got %s", wantDocumentRefID, gotDocumentRefID)
}
if wantURI != gotURI {
t.Errorf("wanted URI %s, got %s", wantURI, gotURI)
}
if wantAlg != gotAlg {
t.Errorf("wanted alg %s, got %s", wantAlg, gotAlg)
}
if wantChecksum != gotChecksum {
t.Errorf("wanted checksum %s, got %s", wantChecksum, gotChecksum)
}
}
func TestCanExtractExternalDocumentReferenceWithExtraWhitespace(t *testing.T) {
refstring := " DocumentRef-spdx-tool-1.2 \t http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 \t SHA1: \t d6a770ba38583ed4bb4525bd96e50461655d2759"
wantDocumentRefID := "spdx-tool-1.2"
wantURI := "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301"
wantAlg := "SHA1"
wantChecksum := "d6a770ba38583ed4bb4525bd96e50461655d2759"
gotDocumentRefID, gotURI, gotAlg, gotChecksum, err := extractExternalDocumentReference(refstring)
if err != nil {
t.Errorf("got non-nil error: %v", err)
}
if wantDocumentRefID != gotDocumentRefID {
t.Errorf("wanted document ref ID %s, got %s", wantDocumentRefID, gotDocumentRefID)
}
if wantURI != gotURI {
t.Errorf("wanted URI %s, got %s", wantURI, gotURI)
}
if wantAlg != gotAlg {
t.Errorf("wanted alg %s, got %s", wantAlg, gotAlg)
}
if wantChecksum != gotChecksum {
t.Errorf("wanted checksum %s, got %s", wantChecksum, gotChecksum)
}
}
func TestFailsExternalDocumentReferenceWithInvalidFormats(t *testing.T) {
invalidRefs := []string{
"whoops",
"DocumentRef-",
"DocumentRef- ",
"DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301",
"DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 d6a770ba38583ed4bb4525bd96e50461655d2759",
"DocumentRef-spdx-tool-1.2",
"spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1:d6a770ba38583ed4bb4525bd96e50461655d2759",
}
for _, refstring := range invalidRefs {
_, _, _, _, err := extractExternalDocumentReference(refstring)
if err == nil {
t.Errorf("expected non-nil error for %s, got nil", refstring)
}
}
}