aboutsummaryrefslogtreecommitdiff
path: root/rdfloader
diff options
context:
space:
mode:
authorRishabhBhatnagar <bhatnagarrishabh4@gmail.com>2020-08-27 13:02:50 +0530
committerRishabhBhatnagar <bhatnagarrishabh4@gmail.com>2020-08-27 13:02:50 +0530
commitf652816522876a038fed37d869039ee38311f253 (patch)
tree2ff40ce4c8d0a52d588025b02997b839333a365d /rdfloader
parent35fc7e067f87dcffc84fee5e832d8346cac909a0 (diff)
downloadspdx-tools-f652816522876a038fed37d869039ee38311f253.tar.gz
Add Tests And Bug Fixes For parse_file.go
- noticeText can now assume two states: SPDX_NOASSERTION and string - add tests for parse_file.go file - relationship now returns the MUX error - getRelationshipTypeFromURI fixed - add constant for NS_SPDX+"Checksum" (SPDX_CHECKSUM_CAPITALIZED) - file Dependency set to the file being populated - add extended support for licenseInfoInFile Signed-off-by: RishabhBhatnagar <bhatnagarrishabh4@gmail.com>
Diffstat (limited to 'rdfloader')
-rw-r--r--rdfloader/parser2v2/constants.go1
-rw-r--r--rdfloader/parser2v2/parse_file.go60
-rw-r--r--rdfloader/parser2v2/parse_file_test.go701
-rw-r--r--rdfloader/parser2v2/parse_relationship.go26
4 files changed, 766 insertions, 22 deletions
diff --git a/rdfloader/parser2v2/constants.go b/rdfloader/parser2v2/constants.go
index 27a807c..dea7e68 100644
--- a/rdfloader/parser2v2/constants.go
+++ b/rdfloader/parser2v2/constants.go
@@ -32,6 +32,7 @@ var (
SPDX_SPDX_DOCUMENT = NS_SPDX + "spdxDocument"
SPDX_SPDX_DOCUMENT_CAPITALIZED = NS_SPDX + "SpdxDocument"
SPDX_CHECKSUM = NS_SPDX + "checksum"
+ SPDX_CHECKSUM_CAPITALIZED = NS_SPDX + "Checksum"
SPDX_ANNOTATION_TYPE = NS_SPDX + "annotationType"
SPDX_ANNOTATION_TYPE_OTHER = NS_SPDX + "annotationType_other"
SPDX_ANNOTATION_TYPE_REVIEW = NS_SPDX + "annotationType_review"
diff --git a/rdfloader/parser2v2/parse_file.go b/rdfloader/parser2v2/parse_file.go
index c91db64..a080808 100644
--- a/rdfloader/parser2v2/parse_file.go
+++ b/rdfloader/parser2v2/parse_file.go
@@ -13,7 +13,7 @@ import (
func (parser *rdfParser2_2) getFileFromNode(fileNode *gordfParser.Node) (file *spdx.File2_2, err error) {
file = &spdx.File2_2{}
- err = setFileIdentifier(fileNode.ID, file, parser) // 4.2
+ err = setFileIdentifier(fileNode.ID, file) // 4.2
if err != nil {
return nil, err
}
@@ -25,7 +25,7 @@ func (parser *rdfParser2_2) getFileFromNode(fileNode *gordfParser.Node) (file *s
file.FileName = subTriple.Object.ID
case SPDX_NAME:
// cardinality: exactly 1
- // todo: check where it will be set in the golang-tools spdx-data-model
+ // TODO: check where it will be set in the golang-tools spdx-data-model
case RDF_TYPE:
// cardinality: exactly 1
case SPDX_FILE_TYPE: // 4.3
@@ -45,16 +45,20 @@ func (parser *rdfParser2_2) getFileFromNode(fileNode *gordfParser.Node) (file *s
file.LicenseConcluded = anyLicense.ToLicenseString()
case SPDX_LICENSE_INFO_IN_FILE: // 4.6
// cardinality: min 1
- lastPart := getLastPartOfURI(subTriple.Object.ID)
- file.LicenseInfoInFile = append(file.LicenseInfoInFile, lastPart)
+ lic, err := parser.getLicenseInfoInFileFromNode(subTriple.Object)
+ if err != nil {
+ return nil, fmt.Errorf("error parsing licenseInfoInFile: %v", err)
+ }
+ file.LicenseInfoInFile = append(file.LicenseInfoInFile, lic.ToLicenseString())
case SPDX_LICENSE_COMMENTS: // 4.7
// cardinality: max 1
file.LicenseComments = subTriple.Object.ID
+ // TODO: allow copyright text to be of type NOASSERTION
case SPDX_COPYRIGHT_TEXT: // 4.8
// cardinality: exactly 1
file.FileCopyrightText = subTriple.Object.ID
case SPDX_LICENSE_INFO_FROM_FILES:
- // todo: implement it. It is not defined in the tools-golang model.
+ // TODO: implement it. It is not defined in the tools-golang model.
// deprecated artifactOf (see sections 4.9, 4.10, 4.11)
case SPDX_ARTIFACT_OF:
// cardinality: min 0
@@ -66,23 +70,26 @@ func (parser *rdfParser2_2) getFileFromNode(fileNode *gordfParser.Node) (file *s
file.FileComment = subTriple.Object.ID
case SPDX_NOTICE_TEXT: // 4.13
// cardinality: max 1
- file.FileNotice = subTriple.Object.ID
+ file.FileNotice = getNoticeTextFromNode(subTriple.Object)
case SPDX_FILE_CONTRIBUTOR: // 4.14
// cardinality: min 0
file.FileContributor = append(file.FileContributor, subTriple.Object.ID)
case SPDX_FILE_DEPENDENCY:
// cardinality: min 0
- file, err := parser.getFileFromNode(subTriple.Object)
+ newFile, err := parser.getFileFromNode(subTriple.Object)
if err != nil {
return nil, fmt.Errorf("error setting a file dependency in a file: %v", err)
}
+ file.FileDependencies = append(file.FileDependencies, string(newFile.FileSPDXIdentifier))
parser.files[file.FileSPDXIdentifier] = file
case SPDX_ATTRIBUTION_TEXT:
// cardinality: min 0
file.FileAttributionTexts = append(file.FileAttributionTexts, subTriple.Object.ID)
- case SPDX_ANNOTATION: // unknown section
+ case SPDX_ANNOTATION:
+ // cardinality: min 0
err = parser.parseAnnotationFromNode(subTriple.Object)
- case SPDX_RELATIONSHIP: // unknown section
+ case SPDX_RELATIONSHIP:
+ // cardinality: min 0
err = parser.parseRelationship(subTriple)
default:
return nil, fmt.Errorf("unknown triple predicate id %s", subTriple.Predicate.ID)
@@ -97,7 +104,7 @@ func (parser *rdfParser2_2) getFileFromNode(fileNode *gordfParser.Node) (file *s
func (parser *rdfParser2_2) setFileChecksumFromNode(file *spdx.File2_2, checksumNode *gordfParser.Node) error {
checksumAlgorithm, checksumValue, err := parser.getChecksumFromNode(checksumNode)
if err != nil {
- return nil
+ return fmt.Errorf("error parsing checksumNode of a file: %v", err)
}
switch checksumAlgorithm {
case "MD5":
@@ -109,7 +116,7 @@ func (parser *rdfParser2_2) setFileChecksumFromNode(file *spdx.File2_2, checksum
case "":
return fmt.Errorf("empty checksum algorithm and value")
default:
- return fmt.Errorf("unknown checksumAlgorithm %s while parsing a file", checksumAlgorithm)
+ return fmt.Errorf("unknown checksumAlgorithm %s for a file", checksumAlgorithm)
}
return nil
}
@@ -135,6 +142,7 @@ func (parser *rdfParser2_2) getArtifactFromNode(node *gordfParser.Node) (*spdx.A
return artifactOf, nil
}
+// TODO: check if the filetype is valid.
func (parser *rdfParser2_2) getFileTypeFromUri(uri string) (string, error) {
// fileType is given as a uri. for example: http://spdx.org/rdf/terms#fileType_text
lastPart := getLastPartOfURI(uri)
@@ -155,7 +163,7 @@ func (parser *rdfParser2_2) setUnpackagedFiles() {
}
}
-func setFileIdentifier(idURI string, file *spdx.File2_2, parser *rdfParser2_2) (err error) {
+func setFileIdentifier(idURI string, file *spdx.File2_2) (err error) {
idURI = strings.TrimSpace(idURI)
uriFragment := getLastPartOfURI(idURI)
file.FileSPDXIdentifier, err = ExtractElementID(uriFragment)
@@ -164,3 +172,31 @@ func setFileIdentifier(idURI string, file *spdx.File2_2, parser *rdfParser2_2) (
}
return nil
}
+
+func getNoticeTextFromNode(node *gordfParser.Node) string {
+ switch node.ID {
+ case SPDX_NOASSERTION_CAPS, SPDX_NOASSERTION_SMALL:
+ return "NOASSERTION"
+ default:
+ return node.ID
+ }
+}
+
+func (parser *rdfParser2_2) getLicenseInfoInFileFromNode(node *gordfParser.Node) (AnyLicenseInfo, error) {
+ // LicenseInfoInFile can either be NONE | NOASSERTION | SimpleLicensingInfo
+ // return type is kept as AnyLicenseInfo because, we can have
+ // either SpecialLicense or SimpleLicensingInfo as the output
+ switch node.ID {
+ case SPDX_NOASSERTION_CAPS, SPDX_NOASSERTION_SMALL:
+ return SpecialLicense{
+ value: NOASSERTION,
+ }, nil
+ case SPDX_NONE_CAPS, SPDX_NONE_SMALL:
+ return SpecialLicense{
+ value: NONE,
+ }, nil
+ }
+
+ // the license must be a SimpleLicense
+ return parser.getSimpleLicensingInfoFromNode(node)
+}
diff --git a/rdfloader/parser2v2/parse_file_test.go b/rdfloader/parser2v2/parse_file_test.go
new file mode 100644
index 0000000..e9fa16c
--- /dev/null
+++ b/rdfloader/parser2v2/parse_file_test.go
@@ -0,0 +1,701 @@
+package parser2v2
+
+import (
+ "bufio"
+ gordfParser "github.com/RishabhBhatnagar/gordf/rdfloader/parser"
+ rdfloader2 "github.com/RishabhBhatnagar/gordf/rdfloader/xmlreader"
+ gordfWriter "github.com/RishabhBhatnagar/gordf/rdfwriter"
+ "github.com/spdx/tools-golang/spdx"
+ "strings"
+ "testing"
+)
+
+// content is the tags within the rdf:RDF tag
+// pads the content with the enclosing rdf:RDF tag
+func wrapIntoTemplate(content string) string {
+ header := `<rdf:RDF
+ xmlns:spdx="http://spdx.org/rdf/terms#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#"
+ xmlns:doap="http://usefulinc.com/ns/doap#"
+ xmlns:j.0="http://www.w3.org/2009/pointers#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">`
+ footer := `</rdf:RDF>`
+ return header + content + footer
+}
+
+func parserFromBodyContent(content string) (*rdfParser2_2, error) {
+ rdfContent := wrapIntoTemplate(content)
+ xmlreader := rdfloader2.XMLReaderFromFileObject(bufio.NewReader(strings.NewReader(rdfContent)))
+ rootBlock, err := xmlreader.Read()
+ if err != nil {
+ return nil, err
+ }
+ parser := gordfParser.New()
+ err = parser.Parse(rootBlock)
+ if err != nil {
+ return nil, err
+ }
+ nodeToTriples := gordfWriter.GetNodeToTriples(parser.Triples)
+ rdfParser := NewParser2_2(parser, nodeToTriples)
+ return rdfParser, err
+}
+
+func Test_rdfParser2_2_getArtifactFromNode(t *testing.T) {
+ // TestCase 1: artifactOf without project URI
+ rdfParser, err := parserFromBodyContent(
+ `<spdx:File>
+ <spdx:artifactOf>
+ <doap:Project>
+ <doap:homepage>http://www.openjena.org/</doap:homepage>
+ <doap:name>Jena</doap:name>
+ </doap:Project>
+ </spdx:artifactOf>
+ </spdx:File>`)
+ if err != nil {
+ t.Errorf("unexpected error while parsing a valid example: %v", err)
+ }
+ artifactOfNode := gordfWriter.FilterTriples(rdfParser.gordfParserObj.Triples, nil, &SPDX_ARTIFACT_OF, nil)[0].Object
+ artifact, err := rdfParser.getArtifactFromNode(artifactOfNode)
+ if err != nil {
+ t.Errorf("error parsing a valid artifactOf node: %v", err)
+ }
+ if artifact.Name != "Jena" {
+ t.Errorf("expected name of artifact: %s, found: %s", "Jena", artifact.Name)
+ }
+ expectedHomePage := "http://www.openjena.org/"
+ if artifact.HomePage != expectedHomePage {
+ t.Errorf("wrong artifact homepage. Expected: %s, found: %s", expectedHomePage, artifact.HomePage)
+ }
+ if artifact.URI != "" {
+ t.Errorf("wrong artifact URI. Expected: %s, found: %s", "", artifact.URI)
+ }
+
+ // TestCase 2: artifactOf with a Project URI
+ rdfParser, err = parserFromBodyContent(
+ `<spdx:File>
+ <spdx:artifactOf>
+ <doap:Project rdf:about="http://subversion.apache.org/doap.rdf">
+ <doap:homepage>http://www.openjena.org/</doap:homepage>
+ <doap:name>Jena</doap:name>
+ </doap:Project>
+ </spdx:artifactOf>
+ </spdx:File>`)
+ if err != nil {
+ t.Errorf("unexpected error while parsing a valid example: %v", err)
+ }
+ artifactOfNode = gordfWriter.FilterTriples(rdfParser.gordfParserObj.Triples, nil, &SPDX_ARTIFACT_OF, nil)[0].Object
+ artifact, err = rdfParser.getArtifactFromNode(artifactOfNode)
+ if err != nil {
+ t.Errorf("error parsing a valid artifactOf node: %v", err)
+ }
+ expectedURI := "http://subversion.apache.org/doap.rdf"
+ if artifact.URI != expectedURI {
+ t.Errorf("wrong artifact URI. Expected: %s, found: %s", expectedURI, artifact.URI)
+ }
+
+ // TestCase 3: artifactOf with unknown predicate
+ rdfParser, err = parserFromBodyContent(
+ `<spdx:File>
+ <spdx:artifactOf>
+ <doap:Project rdf:about="http://subversion.apache.org/doap.rdf">
+ <doap:homepage>http://www.openjena.org/</doap:homepage>
+ <doap:name>Jena</doap:name>
+ <doap:invalidTag rdf:ID="invalid"/>
+ </doap:Project>
+ </spdx:artifactOf>
+ </spdx:File>`)
+ if err != nil {
+ t.Errorf("unexpected error while parsing a valid example: %v", err)
+ }
+ artifactOfNode = gordfWriter.FilterTriples(rdfParser.gordfParserObj.Triples, nil, &SPDX_ARTIFACT_OF, nil)[0].Object
+ _, err = rdfParser.getArtifactFromNode(artifactOfNode)
+ if err == nil {
+ t.Errorf("must've raised an error for an invalid predicate")
+ }
+}
+
+func Test_rdfParser2_2_getFileTypeFromUri(t *testing.T) {
+ rdfParser, _ := parserFromBodyContent(``)
+
+ // TestCase 1: Valid fileType URI:
+ fileTypeURI := "http://spdx.org/rdf/terms#fileType_source"
+ fileType, err := rdfParser.getFileTypeFromUri(fileTypeURI)
+ if err != nil {
+ t.Errorf("error in a valid example: %v", err)
+ }
+ if fileType != "source" {
+ t.Errorf("wrong fileType. expected: %s, found: %s", "source", fileType)
+ }
+
+ // TestCase 2: Invalid fileType URI format.
+ fileTypeURI = "http://spdx.org/rdf/terms#source"
+ fileType, err = rdfParser.getFileTypeFromUri(fileTypeURI)
+ if err == nil {
+ t.Error("should've raised an error for invalid fileType")
+ }
+}
+
+func Test_rdfParser2_2_setUnpackagedFiles(t *testing.T) {
+ // unpackaged files are the files which are not associated with any package
+ // file associated with a package sets parser.assocWithPackage[fileID] to true.
+ rdfParser, _ := parserFromBodyContent(``)
+ file1 := &spdx.File2_2{FileSPDXIdentifier: spdx.ElementID("file1")}
+ file2 := &spdx.File2_2{FileSPDXIdentifier: spdx.ElementID("file2")}
+ file3 := &spdx.File2_2{FileSPDXIdentifier: spdx.ElementID("file3")}
+
+ // setting files to the document as if it were to be set when it was parsed using triples.
+ rdfParser.files[file1.FileSPDXIdentifier] = file1
+ rdfParser.files[file2.FileSPDXIdentifier] = file2
+ rdfParser.files[file3.FileSPDXIdentifier] = file3
+
+ // assuming file1 is associated with a package
+ rdfParser.assocWithPackage[file1.FileSPDXIdentifier] = true
+
+ rdfParser.setUnpackagedFiles()
+
+ // after setting unpackaged files, parser.doc.UnpackagedFiles must've file2 and file3
+ if n := len(rdfParser.doc.UnpackagedFiles); n != 2 {
+ t.Errorf("unpackage files should've had 2 files, found %d files", n)
+ }
+
+ // checking if the unpackagedFiles contain only file2 & file3.
+ for fileID, _ := range rdfParser.doc.UnpackagedFiles {
+ switch string(fileID) {
+ case "file2", "file3":
+ continue
+ default:
+ t.Errorf("unexpected file with id %s found in unpackaged files", fileID)
+ }
+ }
+}
+
+func Test_setFileIdentifier(t *testing.T) {
+ file := &spdx.File2_2{}
+
+ // TestCase 1: valid example
+ err := setFileIdentifier("http://spdx.org/documents/spdx-toolsv2.1.7-SNAPSHOT#SPDXRef-129", file)
+ if err != nil {
+ t.Errorf("unexpected error: %v", err)
+ }
+ if file.FileSPDXIdentifier != "129" {
+ t.Errorf("expected %s, found: %s", "129", file.FileSPDXIdentifier)
+ }
+
+ // TestCase 2: invalid example
+ err = setFileIdentifier("http://spdx.org/documents/spdx-toolsv2.1.7-SNAPSHOT#129", file)
+ if err == nil {
+ t.Errorf("should've raised an error for an invalid example")
+ }
+}
+
+func Test_rdfParser2_2_setFileChecksumFromNode(t *testing.T) {
+ // TestCase 1: md5 checksum
+ parser, _ := parserFromBodyContent(`
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_md5" />
+ <spdx:checksumValue>d2356e0fe1c0b85285d83c6b2ad51b5f</spdx:checksumValue>
+ </spdx:Checksum>
+ `)
+ checksumNode := gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_CHECKSUM_CAPITALIZED)[0].Subject
+ file := &spdx.File2_2{}
+ err := parser.setFileChecksumFromNode(file, checksumNode)
+ if err != nil {
+ t.Errorf("error parsing a valid checksum node")
+ }
+ checksumValue := "d2356e0fe1c0b85285d83c6b2ad51b5f"
+ if file.FileChecksumMD5 != checksumValue {
+ t.Errorf("wrong checksum value for md5. Expected: %s, found: %s", checksumValue, file.FileChecksumMD5)
+ }
+ if file.FileChecksumSHA1 != "" {
+ t.Errorf("incorrectly set sha1, should've been empty")
+ }
+ if file.FileChecksumSHA256 != "" {
+ t.Errorf("incorrectly set sha256, should've been empty")
+ }
+
+ // TestCase 2: valid sha1 checksum
+ parser, _ = parserFromBodyContent(`
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1" />
+ <spdx:checksumValue>d2356e0fe1c0b85285d83c6b2ad51b5f</spdx:checksumValue>
+ </spdx:Checksum>
+ `)
+ checksumNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_CHECKSUM_CAPITALIZED)[0].Subject
+ file = &spdx.File2_2{}
+ err = parser.setFileChecksumFromNode(file, checksumNode)
+ if err != nil {
+ t.Errorf("error parsing a valid checksum node")
+ }
+ if file.FileChecksumSHA1 != checksumValue {
+ t.Errorf("wrong checksum value for sha1. Expected: %s, found: %s", checksumValue, file.FileChecksumSHA1)
+ }
+ if file.FileChecksumMD5 != "" {
+ t.Errorf("incorrectly set md5, should've been empty")
+ }
+ if file.FileChecksumSHA256 != "" {
+ t.Errorf("incorrectly set sha256, should've been empty")
+ }
+
+ // TestCase 3: valid sha256 checksum
+ parser, _ = parserFromBodyContent(`
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha256" />
+ <spdx:checksumValue>d2356e0fe1c0b85285d83c6b2ad51b5f</spdx:checksumValue>
+ </spdx:Checksum>
+ `)
+ checksumNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_CHECKSUM_CAPITALIZED)[0].Subject
+ file = &spdx.File2_2{}
+ err = parser.setFileChecksumFromNode(file, checksumNode)
+ if err != nil {
+ t.Errorf("error parsing a valid checksum node")
+ }
+ if file.FileChecksumSHA256 != checksumValue {
+ t.Errorf("wrong checksum value for sha256. Expected: %s, found: %s", checksumValue, file.FileChecksumSHA256)
+ }
+ if file.FileChecksumMD5 != "" {
+ t.Errorf("incorrectly set md5, should've been empty")
+ }
+ if file.FileChecksumSHA1 != "" {
+ t.Errorf("incorrectly set sha1, should've been empty")
+ }
+
+ // TestCase 4: checksum node without one of the mandatory attributes
+ parser, _ = parserFromBodyContent(`
+ <spdx:Checksum>
+ <spdx:checksumValue>d2356e0fe1c0b85285d83c6b2ad51b5f</spdx:checksumValue>
+ </spdx:Checksum>
+ `)
+ checksumNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_CHECKSUM_CAPITALIZED)[0].Subject
+ file = &spdx.File2_2{}
+ err = parser.setFileChecksumFromNode(file, checksumNode)
+ if err == nil {
+ t.Errorf("should've raised an error parsing an invalid checksum node")
+ }
+
+ // TestCase 5: invalid checksum algorithm
+ parser, _ = parserFromBodyContent(`
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_md43" />
+ <spdx:checksumValue>d2356e0fe1c0b85285d83c6b2ad51b5f</spdx:checksumValue>
+ </spdx:Checksum>
+ `)
+ checksumNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_CHECKSUM_CAPITALIZED)[0].Subject
+ file = &spdx.File2_2{}
+ err = parser.setFileChecksumFromNode(file, checksumNode)
+ if err == nil {
+ t.Errorf("should've raised an error parsing an invalid checksum node")
+ }
+
+ // TestCase 6: valid checksum algorithm which is invalid for file (like md4, md6, sha384, etc.)
+ parser, _ = parserFromBodyContent(`
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha384" />
+ <spdx:checksumValue>d2356e0fe1c0b85285d83c6b2ad51b5f</spdx:checksumValue>
+ </spdx:Checksum>
+ `)
+ checksumNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_CHECKSUM_CAPITALIZED)[0].Subject
+ file = &spdx.File2_2{}
+ err = parser.setFileChecksumFromNode(file, checksumNode)
+ if err == nil {
+ t.Errorf("should've raised an error parsing an invalid checksum algorithm for a file")
+ }
+}
+
+func Test_rdfParser2_2_getFileFromNode(t *testing.T) {
+ // TestCase 1: file with invalid id
+ parser, _ := parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gzspdx.rdf#item177"/>
+ `)
+ fileNode := gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err := parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid file ID")
+ }
+
+ // TestCase 2: invalid fileType
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:fileType rdf:resource="http://spdx.org/rdf/terms#source"/>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid fileType")
+ }
+
+ // TestCase 3: invalid file checksum
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:checksum>
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha384" />
+ <spdx:checksumValue>0a3a0e1ab72b7c132f5021c538a7a3ea6d539bcd</spdx:checksumValue>
+ </spdx:Checksum>
+ </spdx:checksum>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid checksum")
+ }
+
+ // TestCase 4: invalid license concluded
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:licenseConcluded rdf:resource="http://spdx.org/rdf/terms#invalid_license" />
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid license Concluded")
+ }
+
+ // TestCase 5: invalid artifactOf attribute
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:artifactOf>
+ <doap:Project>
+ <doap:unknown_tag />
+ <doap:name>Jena</doap:name>
+ </doap:Project>
+ </spdx:artifactOf>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid artifactOf predicate")
+ }
+
+ // TestCase 6: invalid file dependency
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:fileDependency rdf:resource="http://spdx.org/spdxdocs/spdx-example#CommonsLangSrc"/>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid fileDependency")
+ }
+
+ // TestCase 7: invalid annotation with unknown predicate
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:annotation>
+ <spdx:Annotation>
+ <spdx:unknownAttribute />
+ </spdx:Annotation>
+ </spdx:annotation>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid annotation predicate")
+ }
+
+ // TestCase 8: invalid relationship
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:relationship>
+ <spdx:Relationship>
+ <spdx:relationshipType rdf:resource="http://spdx.org/rdf/terms#dynamicLink"/>
+ </spdx:Relationship>
+ </spdx:relationship>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid relationship Type")
+ }
+
+ // TestCase 8: unknown predicate
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:unknown />
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ _, err = parser.getFileFromNode(fileNode)
+ if err == nil {
+ t.Errorf("should've raised an error stating invalid predicate for a file")
+ }
+
+ // TestCase 9: all valid attribute and it's values.
+ parser, _ = parserFromBodyContent(`
+ <spdx:File rdf:about="http://anupam-VirtualBox/repo/SPDX2_time-1.9.tar.gz_1535120734-spdx.rdf#SPDXRef-item177">
+ <spdx:fileName>time-1.9/ChangeLog</spdx:fileName>
+ <spdx:name/>
+ <spdx:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+ <spdx:checksum>
+ <spdx:Checksum>
+ <spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1" />
+ <spdx:checksumValue>0a3a0e1ab72b7c132f5021c538a7a3ea6d539bcd</spdx:checksumValue>
+ </spdx:Checksum>
+ </spdx:checksum>
+ <spdx:licenseConcluded rdf:resource="http://spdx.org/rdf/terms#noassertion" />
+ <spdx:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#NOASSERTION" />
+ <spdx:licenseComments>no comments</spdx:licenseComments>
+ <spdx:copyrightText>from spdx file</spdx:copyrightText>
+ <spdx:artifactOf>
+ <doap:Project>
+ <doap:homepage>http://www.openjena.org/</doap:homepage>
+ <doap:name>Jena</doap:name>
+ </doap:Project>
+ </spdx:artifactOf>
+ <rdfs:comment>no comments</rdfs:comment>
+ <spdx:noticeText rdf:resource="http://spdx.org/rdf/terms#noassertion"/>
+ <spdx:fileContributor>Some Organization</spdx:fileContributor>
+ <spdx:fileDependency rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-CommonsLangSrc"/>
+ <spdx:attributionText>attribution text</spdx:attributionText>
+ <spdx:annotation>
+ <spdx:Annotation>
+ <spdx:annotationDate>2011-01-29T18:30:22Z</spdx:annotationDate>
+ <rdfs:comment>File level annotation copied from a spdx document</rdfs:comment>
+ <spdx:annotator>Person: File Commenter</spdx:annotator>
+ <spdx:annotationType rdf:resource="http://spdx.org/rdf/terms#annotationType_other"/>
+ </spdx:Annotation>
+ </spdx:annotation>
+ <spdx:relationship>
+ <spdx:Relationship>
+ <spdx:relationshipType rdf:resource="http://spdx.org/rdf/terms#relationshipType_contains"/>
+ <spdx:relatedSpdxElement rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-Package"/>
+ </spdx:Relationship>
+ </spdx:relationship>
+ </spdx:File>
+ `)
+ fileNode = gordfWriter.FilterTriples(parser.gordfParserObj.Triples, nil, &RDF_TYPE, &SPDX_FILE)[0].Subject
+ file, err := parser.getFileFromNode(fileNode)
+ if err != nil {
+ t.Errorf("unexpected error parsing a valid file: %v", err)
+ }
+
+ // checking each and every attribute of the obtained file.
+
+ expectedFileName := "time-1.9/ChangeLog"
+ if file.FileName != expectedFileName {
+ t.Errorf("expected %s, found %s", expectedFileName, file.FileName)
+ }
+
+ if len(file.FileType) != 1 {
+ t.Errorf("given file should have 1 fileType attribute. found %d", len(file.FileType))
+ }
+ expectedFileType := "source"
+ if file.FileType[0] != expectedFileType {
+ t.Errorf("expected %s, found %s", expectedFileType, file.FileType)
+ }
+
+ expectedChecksum := "0a3a0e1ab72b7c132f5021c538a7a3ea6d539bcd"
+ if file.FileChecksumSHA1 != expectedChecksum {
+ t.Errorf("expected %s, found %s", expectedChecksum, file.FileChecksumSHA1)
+ }
+
+ expectedLicenseConcluded := "NOASSERTION"
+ if file.LicenseConcluded != expectedLicenseConcluded {
+ t.Errorf("expected %s, found %s", expectedLicenseConcluded, file.LicenseConcluded)
+ }
+
+ if len(file.LicenseInfoInFile) != 1 {
+ t.Errorf("given file should have 1 licenseInfoInFile attribute. found %d", len(file.LicenseInfoInFile))
+ }
+ expectedLicenseInfoInFile := "NOASSERTION"
+ if file.LicenseInfoInFile[0] != expectedLicenseInfoInFile {
+ t.Errorf("expected %s, found %s", expectedLicenseInfoInFile, file.LicenseInfoInFile[0])
+ }
+
+ expectedLicenseComments := "no comments"
+ if file.LicenseComments != expectedLicenseComments {
+ t.Errorf("expected %s, found %s", expectedLicenseComments, file.LicenseComments)
+ }
+
+ expectedCopyrightText := "from spdx file"
+ if file.FileCopyrightText != expectedCopyrightText {
+ t.Errorf("expected %s, found %s", expectedCopyrightText, file.FileCopyrightText)
+ }
+
+ if n := len(file.ArtifactOfProjects); n != 1 {
+ t.Errorf("given file should have 1 artifactOfProjects attribute. found %d", n)
+ }
+ artifactOf := file.ArtifactOfProjects[0]
+ expectedHomePage := "http://www.openjena.org/"
+ if artifactOf.HomePage != expectedHomePage {
+ t.Errorf("expected %s, found %s", expectedHomePage, artifactOf.HomePage)
+ }
+ if artifactOf.Name != "Jena" {
+ t.Errorf("expected %s, found %s", "Jena", artifactOf.Name)
+ }
+ if artifactOf.URI != "" {
+ t.Errorf("expected artifactOf uri to be empty, found %s", artifactOf.URI)
+ }
+
+ expectedFileComment := "no comments"
+ if file.FileComment != expectedFileComment {
+ t.Errorf("expected %s, found %s", expectedFileName, file.FileComment)
+ }
+
+ expectedNoticeText := "NOASSERTION"
+ if file.FileNotice != expectedNoticeText {
+ t.Errorf("expected %s, found %s", expectedNoticeText, file.FileNotice)
+ }
+
+ if n := len(file.FileContributor); n != 1 {
+ t.Errorf("given file should have 1 fileContributor. found %d", n)
+ }
+ expectedFileContributor := "Some Organization"
+ if file.FileContributor[0] != expectedFileContributor {
+ t.Errorf("expected %s, found %s", expectedFileContributor, file.FileContributor)
+ }
+
+ if n := len(file.FileDependencies); n != 1 {
+ t.Errorf("given file should have 1 fileDependencies. found %d", n)
+ }
+ expectedFileDependency := "CommonsLangSrc"
+ if file.FileDependencies[0] != expectedFileDependency {
+ t.Errorf("expected %s, found %s", expectedFileDependency, file.FileDependencies[0])
+ }
+
+ if n := len(file.FileAttributionTexts); n != 1 {
+ t.Errorf("given file should have 1 attributionText. found %d", n)
+ }
+ expectedAttributionText := "attribution text"
+ if file.FileAttributionTexts[0] != expectedAttributionText {
+ t.Errorf("expected %s, found %s", expectedAttributionText, file.FileAttributionTexts[0])
+ }
+
+ if n := len(parser.doc.Annotations); n != 1 {
+ t.Errorf("doc should've had 1 annotation. found %d", n)
+ }
+ ann := parser.doc.Annotations[0]
+ expectedAnnDate := "2011-01-29T18:30:22Z"
+ if ann.AnnotationDate != expectedAnnDate {
+ t.Errorf("expected %s, found %s", expectedAnnDate, ann.AnnotationDate)
+ }
+ expectedAnnComment := "File level annotation copied from a spdx document"
+ if ann.AnnotationComment != expectedAnnComment {
+ t.Errorf("expected %s, found %s", expectedAnnComment, ann.AnnotationComment)
+ }
+ expectedAnnotationType := "OTHER"
+ if ann.AnnotationType != expectedAnnotationType {
+ t.Errorf("expected %s, found %s", expectedAnnotationType, ann.AnnotationType)
+ }
+ expectedAnnotator := "File Commenter"
+ if ann.Annotator != expectedAnnotator {
+ t.Errorf("expected %s, found %s", expectedAnnotator, ann.Annotator)
+ }
+ expectedAnnotatorType := "Person"
+ if ann.AnnotationType != expectedAnnotationType {
+ t.Errorf("expected %s, found %s", expectedAnnotatorType, ann.AnnotatorType)
+ }
+
+ if n := len(parser.doc.Relationships); n != 1 {
+ t.Errorf("doc should've had 1 relation. found %d", n)
+ }
+ reln := parser.doc.Relationships[0]
+ expectedRefAEID := "item177"
+ if reln.RefA.DocumentRefID != "" {
+ t.Errorf("expected refA.DocumentRefID to be empty, found %s", reln.RefA.DocumentRefID)
+ }
+ if string(reln.RefA.ElementRefID) != expectedRefAEID {
+ t.Errorf("expected %s, found %s", expectedRefAEID, reln.RefA.ElementRefID)
+ }
+ expectedRefBEID := "Package"
+ if reln.RefB.DocumentRefID != "" {
+ t.Errorf("expected refB.DocumentRefID to be empty, found %s", reln.RefB.DocumentRefID)
+ }
+ if string(reln.RefB.ElementRefID) != expectedRefBEID {
+ t.Errorf("expected %s, found %s", expectedRefBEID, reln.RefB.ElementRefID)
+ }
+ expectedRelationType := "contains"
+ if reln.Relationship != expectedRelationType {
+ t.Errorf("expected %s, found %s", expectedRefBEID, reln.RefB.ElementRefID)
+ }
+ if reln.RelationshipComment != "" {
+ t.Errorf("expected relationship comment to be empty, found %s", reln.RelationshipComment)
+ }
+}
+
+func Test_getNoticeTextFromNode(t *testing.T) {
+ // TestCase 1: SPDX_NOASSERTION_SMALL must return NOASSERTION
+ output := getNoticeTextFromNode(&gordfParser.Node{
+ NodeType: gordfParser.IRI,
+ ID: SPDX_NOASSERTION_SMALL,
+ })
+ if strings.ToUpper(output) != "NOASSERTION" {
+ t.Errorf("expected NOASSERTION, found %s", strings.ToUpper(output))
+ }
+
+ // TestCase 2: SPDX_NOASSERTION_CAPS must return NOASSERTION
+ output = getNoticeTextFromNode(&gordfParser.Node{
+ NodeType: gordfParser.IRI,
+ ID: SPDX_NOASSERTION_CAPS,
+ })
+ if strings.ToUpper(output) != "NOASSERTION" {
+ t.Errorf("expected NOASSERTION, found %s", strings.ToUpper(output))
+ }
+
+ // TestCase 3: not a NOASSERTION must return the field verbatim
+ // TestCase 1: SPDX_NOASSERTION_SMALL must return NOASSERTION
+ output = getNoticeTextFromNode(&gordfParser.Node{
+ NodeType: gordfParser.IRI,
+ ID: "text",
+ })
+ if output != "text" {
+ t.Errorf("expected text, found %s", output)
+ }
+}
+
+func Test_rdfParser2_2_getLicenseInfoInFileFromNode(t *testing.T) {
+ parser, _ := parserFromBodyContent(``)
+
+ // TestCase 1: noassertion License
+ lic, err := parser.getLicenseInfoInFileFromNode(&gordfParser.Node{
+ NodeType: gordfParser.RESOURCELITERAL,
+ ID: SPDX_NOASSERTION_CAPS,
+ })
+ if err != nil {
+ t.Errorf("error parsing a valid license")
+ }
+ if lic.ToLicenseString() != "NOASSERTION" {
+ t.Errorf("expected %s, found %s", "NOASSERTION", lic.ToLicenseString())
+ }
+
+ // TestCase 2: none License
+ lic, err = parser.getLicenseInfoInFileFromNode(&gordfParser.Node{
+ NodeType: gordfParser.RESOURCELITERAL,
+ ID: SPDX_NONE_CAPS,
+ })
+ if err != nil {
+ t.Errorf("error parsing a valid license")
+ }
+ if lic.ToLicenseString() != "NONE" {
+ t.Errorf("expected %s, found %s", "NONE", lic.ToLicenseString())
+ }
+
+ // TestCase 3: invalid license
+ // TestCase 1: noassertion License
+ node := &gordfParser.Node{
+ NodeType: gordfParser.BLANK,
+ ID: "N0",
+ }
+ parser.gordfParserObj.Triples = append(parser.gordfParserObj.Triples, &gordfParser.Triple{
+ Subject: node,
+ Predicate: &gordfParser.Node{
+ NodeType: gordfParser.IRI,
+ ID: NS_SPDX + "invalidAttribute",
+ },
+ Object: &gordfParser.Node{
+ NodeType: gordfParser.IRI,
+ ID: NS_SPDX + "weirdLicense",
+ },
+ })
+ lic, err = parser.getLicenseInfoInFileFromNode(node)
+ if err == nil {
+ t.Errorf("should've raised an error parsing an invalid license")
+ }
+}
diff --git a/rdfloader/parser2v2/parse_relationship.go b/rdfloader/parser2v2/parse_relationship.go
index b51105b..b4c4704 100644
--- a/rdfloader/parser2v2/parse_relationship.go
+++ b/rdfloader/parser2v2/parse_relationship.go
@@ -26,7 +26,7 @@ func (parser *rdfParser2_2) parseRelationship(triple *gordfParser.Triple) (err e
switch subTriple.Predicate.ID {
case SPDX_RELATIONSHIP_TYPE:
// cardinality: exactly 1
- reln.Relationship, err = getRelationshipType(subTriple.Object.ID)
+ reln.Relationship, err = getRelationshipTypeFromURI(subTriple.Object.ID)
case RDF_TYPE:
// cardinality: exactly 1
continue
@@ -57,6 +57,9 @@ func (parser *rdfParser2_2) parseRelationship(triple *gordfParser.Triple) (err e
default:
return fmt.Errorf("unexpected predicate id: %s", subTriple.Predicate.ID)
}
+ if err != nil {
+ return err
+ }
}
parser.doc.Relationships = append(parser.doc.Relationships, &reln)
return nil
@@ -102,6 +105,8 @@ func (parser *rdfParser2_2) parseRelatedElementFromTriple(reln spdx.Relationship
return nil
}
+
+// references like RefA and RefB of any relationship
func getReferenceFromURI(uri string) (spdx.DocElementID, error) {
fragment := getLastPartOfURI(uri)
switch strings.ToLower(strings.TrimSpace(fragment)) {
@@ -114,18 +119,19 @@ func getReferenceFromURI(uri string) (spdx.DocElementID, error) {
return ExtractDocElementID(fragment)
}
-func getRelationshipType(relnType string) (string, error) {
- relnType = strings.TrimSpace(relnType)
- if !strings.HasPrefix(relnType, PREFIX_RELATIONSHIP_TYPE) {
- return "", fmt.Errorf("relationshipType must start with %s. found %s", PREFIX_RELATIONSHIP_TYPE, relnType)
+func getRelationshipTypeFromURI(relnTypeURI string) (string, error) {
+ relnTypeURI = strings.TrimSpace(relnTypeURI)
+ lastPart := getLastPartOfURI(relnTypeURI)
+ if !strings.HasPrefix(lastPart, PREFIX_RELATIONSHIP_TYPE) {
+ return "", fmt.Errorf("relationshipType must start with %s. found %s", PREFIX_RELATIONSHIP_TYPE, lastPart)
}
- relnType = strings.TrimPrefix(relnType, PREFIX_RELATIONSHIP_TYPE)
+ lastPart = strings.TrimPrefix(lastPart, PREFIX_RELATIONSHIP_TYPE)
- relnType = strings.TrimSpace(relnType)
+ lastPart = strings.TrimSpace(lastPart)
for _, validRelationshipType := range AllRelationshipTypes() {
- if relnType == validRelationshipType {
- return relnType, nil
+ if lastPart == validRelationshipType {
+ return lastPart, nil
}
}
- return "", fmt.Errorf("unknown relationshipType: %s", relnType)
+ return "", fmt.Errorf("unknown relationshipType: '%s'", lastPart)
}