xref: /aosp_15_r20/external/spdx-tools/rdfloader/parser2v3/utils_test.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2
3package parser2v3
4
5import (
6	"reflect"
7	"testing"
8
9	gordfParser "github.com/spdx/gordf/rdfloader/parser"
10	"github.com/spdx/tools-golang/spdx/common"
11)
12
13func Test_getLastPartOfURI(t *testing.T) {
14	// uri of type baseFragment#fragment
15	input := "baseFragment#fragment"
16	expectedOutput := "fragment"
17	output := getLastPartOfURI(input)
18	if output != expectedOutput {
19		t.Errorf("expected %s, found %s", expectedOutput, output)
20	}
21
22	// uri of type baseFragment/subFragment
23	input = "baseFragment/subFragment"
24	expectedOutput = "subFragment"
25	output = getLastPartOfURI(input)
26	if output != expectedOutput {
27		t.Errorf("expected %s, found %s", expectedOutput, output)
28	}
29
30	// neither of the case mustn't raise any error.
31	input = "www.github.com"
32	expectedOutput = input
33	output = getLastPartOfURI(input)
34	if output != expectedOutput {
35		t.Errorf("expected %s, found %s", expectedOutput, output)
36	}
37}
38
39func Test_isUriValid(t *testing.T) {
40	// TestCase 1: Valid Input URI
41	input := "https://www.github.com"
42	isValid := isUriValid(input)
43	if !isValid {
44		t.Errorf("valid input(%s) detected as invalid.", input)
45	}
46
47	// TestCase 2: Invalid Input URI
48	input = `http\:www.github.com`
49	isValid = isUriValid(input)
50	if isValid {
51		t.Errorf("invalid input(%s) detected as valid", input)
52	}
53}
54
55func Test_rdfParser2_3_nodeToTriples(t *testing.T) {
56	var parser *rdfParser2_3
57	var output, expectedOutput []*gordfParser.Triple
58
59	// TestCase 1: a nil node shouldn't raise any error or panic.
60	parser, _ = parserFromBodyContent(``)
61	output = parser.nodeToTriples(nil)
62	if output == nil {
63		t.Errorf("nil input should return an empty slice and not nil")
64	}
65	expectedOutput = []*gordfParser.Triple{}
66	if !reflect.DeepEqual(output, expectedOutput) {
67		t.Errorf("expected %+v, got %+v", expectedOutput, output)
68	}
69
70	// TestCase 2: node should be addressable based on the node content and not the pointer.
71	// It should allow new nodes same as the older ones to retrieve the associated triples.
72	parser, _ = parserFromBodyContent(`
73		  <spdx:Checksum rdf:about="#checksum">
74			<spdx:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1" />
75			<spdx:checksumValue>75068c26abbed3ad3980685bae21d7202d288317</spdx:checksumValue>
76		  </spdx:Checksum>
77	`)
78	newNode := &gordfParser.Node{
79		NodeType: gordfParser.IRI,
80		ID:       "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#checksum",
81	}
82	output = parser.nodeToTriples(newNode)
83
84	// The output must have 3 triples:
85	// 1. newNode rdf:type Checksum
86	// 2. newNode spdx:algorithm http://spdx.org/rdf/terms#checksumAlgorithm_sha1
87	// 3. newNode spdx:checksumValue 75068c26abbed3ad3980685bae21d7202d288317
88	if len(output) != 3 {
89		t.Errorf("expected output to have 3 triples, got %d", len(output))
90	}
91}
92
93func Test_boolFromString(t *testing.T) {
94	// TestCase 1: Valid Input: "true"
95	// mustn't raise any error
96	input := "true"
97	val, err := boolFromString(input)
98	if err != nil {
99		t.Errorf("function raised an error for a valid input(%s): %s", input, err)
100	}
101	if val != true {
102		t.Errorf("invalid output. Expected %v, found %v", true, val)
103	}
104
105	// TestCase 2: Valid Input: "true"
106	// mustn't raise any error
107	input = "false"
108	val, err = boolFromString(input)
109	if err != nil {
110		t.Errorf("function raised an error for a valid input(%s): %s", input, err)
111	}
112	if val != false {
113		t.Errorf("invalid output. Expected %v, found %v", false, val)
114	}
115
116	// TestCase 3: invalid input: ""
117	// it must raise an error
118	input = ""
119	val, err = boolFromString(input)
120	if err == nil {
121		t.Errorf("invalid input should've raised an error")
122	}
123}
124
125func Test_getNodeTypeFromTriples(t *testing.T) {
126	var err error
127	var node *gordfParser.Node
128	var triples []*gordfParser.Triple
129	var nodeType, expectedNodeType string
130
131	// TestCase 1: nil node must raise an error because,
132	// nil nodes cannot be associated with any rdf:type attribute.
133	_, err = getNodeTypeFromTriples(triples, nil)
134	if err == nil {
135		t.Errorf("expected an error due to nil node, got %v", err)
136	}
137
138	// TestCase 2: none of the triples give information about the rdf:type of a node.
139	node = &gordfParser.Node{
140		NodeType: gordfParser.IRI,
141		ID:       "N0",
142	}
143	_, err = getNodeTypeFromTriples(triples, node)
144	if err == nil {
145		t.Errorf("expected an error saying no rdf:type found, got %v", err)
146	}
147
148	// TestCase 3: node is associated with exactly one rdf:type triples
149	typeTriple := &gordfParser.Triple{
150		Subject: node,
151		Predicate: &gordfParser.Node{
152			NodeType: gordfParser.IRI,
153			ID:       RDF_TYPE,
154		},
155		Object: &gordfParser.Node{
156			NodeType: gordfParser.IRI,
157			ID:       "http://spdx.org/rdf/terms#Checksum",
158		},
159	}
160	triples = append(triples, typeTriple)
161	expectedNodeType = "http://spdx.org/rdf/terms#Checksum"
162	nodeType, err = getNodeTypeFromTriples(triples, node)
163	if err != nil {
164		t.Fatalf("unexpected error: %v", err)
165	}
166	if nodeType != expectedNodeType {
167		t.Errorf("expected: %v, got: %v", nodeType, expectedNodeType)
168	}
169
170	// TestCase 4: node associated with more than one rdf:type triples must raise an error.
171	typeTriple = &gordfParser.Triple{
172		Subject: node,
173		Predicate: &gordfParser.Node{
174			NodeType: gordfParser.IRI,
175			ID:       RDF_TYPE,
176		},
177		Object: &gordfParser.Node{
178			NodeType: gordfParser.IRI,
179			ID:       "http://spdx.org/rdf/terms#Snippet",
180		},
181	}
182	triples = append(triples, typeTriple)
183	_, err = getNodeTypeFromTriples(triples, node)
184	if err == nil {
185		t.Errorf("expected an error saying more than one rdf:type found, got %v", err)
186	}
187}
188
189// following tests are copy pasted from tvloader/parser2v3/util_test.go
190
191func TestCanExtractDocumentAndElementRefsFromID(t *testing.T) {
192	// test with valid ID in this document
193	helperForExtractDocElementID(t, "SPDXRef-file1", false, "", "file1")
194	// test with valid ID in another document
195	helperForExtractDocElementID(t, "DocumentRef-doc2:SPDXRef-file2", false, "doc2", "file2")
196	// test with invalid ID in this document
197	helperForExtractDocElementID(t, "a:SPDXRef-file1", true, "", "")
198	helperForExtractDocElementID(t, "file1", true, "", "")
199	helperForExtractDocElementID(t, "SPDXRef-", true, "", "")
200	helperForExtractDocElementID(t, "SPDXRef-file1:", true, "", "")
201	// test with invalid ID in another document
202	helperForExtractDocElementID(t, "DocumentRef-doc2", true, "", "")
203	helperForExtractDocElementID(t, "DocumentRef-doc2:", true, "", "")
204	helperForExtractDocElementID(t, "DocumentRef-doc2:SPDXRef-", true, "", "")
205	helperForExtractDocElementID(t, "DocumentRef-doc2:a", true, "", "")
206	helperForExtractDocElementID(t, "DocumentRef-:", true, "", "")
207	helperForExtractDocElementID(t, "DocumentRef-:SPDXRef-file1", true, "", "")
208	// test with invalid formats
209	helperForExtractDocElementID(t, "DocumentRef-doc2:SPDXRef-file1:file2", true, "", "")
210}
211
212func helperForExtractDocElementID(t *testing.T, tst string, wantErr bool, wantDoc string, wantElt string) {
213	deID, err := ExtractDocElementID(tst)
214	if err != nil && wantErr == false {
215		t.Errorf("testing %v: expected nil error, got %v", tst, err)
216	}
217	if err == nil && wantErr == true {
218		t.Errorf("testing %v: expected non-nil error, got nil", tst)
219	}
220	if deID.DocumentRefID != wantDoc {
221		if wantDoc == "" {
222			t.Errorf("testing %v: want empty string for DocumentRefID, got %v", tst, deID.DocumentRefID)
223		} else {
224			t.Errorf("testing %v: want %v for DocumentRefID, got %v", tst, wantDoc, deID.DocumentRefID)
225		}
226	}
227	if deID.ElementRefID != common.ElementID(wantElt) {
228		if wantElt == "" {
229			t.Errorf("testing %v: want emptyString for ElementRefID, got %v", tst, deID.ElementRefID)
230		} else {
231			t.Errorf("testing %v: want %v for ElementRefID, got %v", tst, wantElt, deID.ElementRefID)
232		}
233	}
234}
235
236func TestCanExtractElementRefsOnlyFromID(t *testing.T) {
237	// test with valid ID in this document
238	helperForExtractElementID(t, "SPDXRef-file1", false, "file1")
239	// test with valid ID in another document
240	helperForExtractElementID(t, "DocumentRef-doc2:SPDXRef-file2", true, "")
241	// test with invalid ID in this document
242	helperForExtractElementID(t, "a:SPDXRef-file1", true, "")
243	helperForExtractElementID(t, "file1", true, "")
244	helperForExtractElementID(t, "SPDXRef-", true, "")
245	helperForExtractElementID(t, "SPDXRef-file1:", true, "")
246	// test with invalid ID in another document
247	helperForExtractElementID(t, "DocumentRef-doc2", true, "")
248	helperForExtractElementID(t, "DocumentRef-doc2:", true, "")
249	helperForExtractElementID(t, "DocumentRef-doc2:SPDXRef-", true, "")
250	helperForExtractElementID(t, "DocumentRef-doc2:a", true, "")
251	helperForExtractElementID(t, "DocumentRef-:", true, "")
252	helperForExtractElementID(t, "DocumentRef-:SPDXRef-file1", true, "")
253}
254
255func helperForExtractElementID(t *testing.T, tst string, wantErr bool, wantElt string) {
256	eID, err := ExtractElementID(tst)
257	if err != nil && wantErr == false {
258		t.Errorf("testing %v: expected nil error, got %v", tst, err)
259	}
260	if err == nil && wantErr == true {
261		t.Errorf("testing %v: expected non-nil error, got nil", tst)
262	}
263	if eID != common.ElementID(wantElt) {
264		if wantElt == "" {
265			t.Errorf("testing %v: want emptyString for ElementRefID, got %v", tst, eID)
266		} else {
267			t.Errorf("testing %v: want %v for ElementRefID, got %v", tst, wantElt, eID)
268		}
269	}
270}
271
272func TestCanExtractSubvalues(t *testing.T) {
273	subkey, subvalue, err := ExtractSubs("SHA1: abc123", ":")
274	if err != nil {
275		t.Errorf("got error when calling extractSubs: %v", err)
276	}
277	if subkey != "SHA1" {
278		t.Errorf("got %v for subkey", subkey)
279	}
280	if subvalue != "abc123" {
281		t.Errorf("got %v for subvalue", subvalue)
282	}
283}
284
285func TestReturnsErrorForInvalidSubvalueFormat(t *testing.T) {
286	_, _, err := ExtractSubs("blah", ":")
287	if err == nil {
288		t.Errorf("expected error when calling extractSubs for invalid format (0 colons), got nil")
289	}
290}
291