1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 2 3package parser2v2 4 5import ( 6 "testing" 7 8 gordfParser "github.com/spdx/gordf/rdfloader/parser" 9 "github.com/spdx/tools-golang/spdx/common" 10 "github.com/spdx/tools-golang/spdx/v2_2" 11) 12 13func Test_rdfParser2_2_getSnippetInformationFromTriple2_2(t *testing.T) { 14 var err error 15 var parser *rdfParser2_2 16 var node *gordfParser.Node 17 18 // TestCase 1: invalid snippet id: 19 parser, _ = parserFromBodyContent(` 20 <spdx:Snippet rdf:about="#Snippet"> 21 </spdx:Snippet> 22 `) 23 node = parser.gordfParserObj.Triples[0].Subject 24 _, err = parser.getSnippetInformationFromNode2_2(node) 25 if err == nil { 26 t.Errorf("expected an error due to invalid, got %v", err) 27 } 28 29 // TestCase 2: Invalid LicenseInfoInSnippet 30 parser, _ = parserFromBodyContent(` 31 <spdx:Snippet rdf:about="#SPDXRef-Snippet"> 32 <spdx:licenseInfoInSnippet rdf:resource="http://spdx.org/licenses/Unknown"/> 33 </spdx:Snippet> 34 `) 35 node = parser.gordfParserObj.Triples[0].Subject 36 _, err = parser.getSnippetInformationFromNode2_2(node) 37 if err == nil { 38 t.Errorf("expected an error due to invalid licenseInfoInSnippet, got %v", err) 39 } 40 41 // TestCase 3: Invalid range. 42 parser, _ = parserFromBodyContent(` 43 <spdx:Snippet rdf:about="#SPDXRef-Snippet"> 44 <spdx:range> 45 <spdx:StartEndPointer> 46 <spdx:unknownTag /> 47 </spdx:StartEndPointer> 48 </spdx:range> 49 </spdx:Snippet> 50 `) 51 node = parser.gordfParserObj.Triples[0].Subject 52 _, err = parser.getSnippetInformationFromNode2_2(node) 53 if err == nil { 54 t.Errorf("expected an error due to invalid range, got %v", err) 55 } 56 57 // TestCase 3: invalid file in snippetFromFile 58 parser, _ = parserFromBodyContent(` 59 <spdx:Snippet rdf:about="#SPDXRef-Snippet"> 60 <spdx:snippetFromFile> 61 <spdx:File rdf:resource="http://anupam-VirtualBox/spdx.rdf#item8" /> 62 </spdx:snippetFromFile> 63 </spdx:Snippet> 64 `) 65 node = parser.gordfParserObj.Triples[0].Subject 66 _, err = parser.getSnippetInformationFromNode2_2(node) 67 if err == nil { 68 t.Errorf("expected an error due to invalid snippetFromFile, got %v", err) 69 } 70 71 // TestCase 4: unknown predicate 72 parser, _ = parserFromBodyContent(` 73 <spdx:Snippet rdf:about="#SPDXRef-Snippet"> 74 <spdx:unknownPredicate /> 75 </spdx:Snippet> 76 `) 77 node = parser.gordfParserObj.Triples[0].Subject 78 _, err = parser.getSnippetInformationFromNode2_2(node) 79 if err == nil { 80 t.Errorf("expected an error due to invalid predicate, got %v", err) 81 } 82 83 // TestCase 5: invalid license concluded: 84 parser, _ = parserFromBodyContent(` 85 <spdx:Snippet rdf:about="#SPDXRef-Snippet"> 86 <spdx:licenseConcluded rdf:resource="http://spdx.org/licenses/Unknown"/> 87 </spdx:Snippet> 88 `) 89 node = parser.gordfParserObj.Triples[0].Subject 90 _, err = parser.getSnippetInformationFromNode2_2(node) 91 if err == nil { 92 t.Errorf("expected an error due to invalid licenseConcluded, got %v", err) 93 } 94 95 // TestCase 6: everything valid: 96 parser, _ = parserFromBodyContent(` 97 <spdx:Snippet rdf:about="#SPDXRef-Snippet"> 98 <spdx:snippetFromFile> 99 <spdx:File rdf:about="#SPDXRef-File" /> 100 </spdx:snippetFromFile> 101 <spdx:range> 102 <j.0:StartEndPointer> 103 <j.0:startPointer> 104 <j.0:LineCharPointer> 105 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 106 <j.0:lineNumber>420</j.0:lineNumber> 107 </j.0:LineCharPointer> 108 </j.0:startPointer> 109 <j.0:endPointer> 110 <j.0:LineCharPointer> 111 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 112 <j.0:lineNumber>310</j.0:lineNumber> 113 </j.0:LineCharPointer> 114 </j.0:endPointer> 115 </j.0:StartEndPointer> 116 </spdx:range> 117 <spdx:licenseInfoInSnippet rdf:resource="http://spdx.org/rdf/terms#noassertion"/> 118 <spdx:name>snippet test</spdx:name> 119 <spdx:copyrightText>test</spdx:copyrightText> 120 <spdx:licenseComments>comments</spdx:licenseComments> 121 <rdfs:comment>comments</rdfs:comment> 122 <spdx:licenseConcluded rdf:resource="http://spdx.org/rdf/terms#noassertion"/> 123 </spdx:Snippet> 124 `) 125 node = parser.gordfParserObj.Triples[0].Subject 126 _, err = parser.getSnippetInformationFromNode2_2(node) 127 if err != nil { 128 t.Fatalf("error parsing a valid example: %v", err) 129 } 130} 131 132func Test_setSnippetID(t *testing.T) { 133 // TestCase 1: invalid input (empty) 134 err := setSnippetID("", &v2_2.Snippet{}) 135 if err == nil { 136 t.Errorf("should've raised an error for empty input") 137 } 138 139 // TestCase 2: valid input 140 si := &v2_2.Snippet{} 141 err = setSnippetID("http://spdx.org/spdxdocs/spdx-example#SPDXRef-Snippet", si) 142 if err != nil { 143 t.Errorf("unexpected error: %v", err) 144 } 145 if si.SnippetSPDXIdentifier != "Snippet" { 146 t.Errorf("expected: %s, found: %s", "Snippet", si.SnippetSPDXIdentifier) 147 } 148} 149 150func Test_rdfParser2_2_parseRangeReference(t *testing.T) { 151 var err error 152 var node *gordfParser.Node 153 var parser *rdfParser2_2 154 var si *v2_2.Snippet 155 156 // TestCase 1: ResourceLiteral node without a new file shouldn't raise any error. 157 si = &v2_2.Snippet{} 158 parser, _ = parserFromBodyContent(``) 159 node = &gordfParser.Node{ 160 NodeType: gordfParser.RESOURCELITERAL, 161 ID: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource", 162 } 163 err = parser.parseRangeReference(node, si) 164 if err != nil { 165 t.Errorf("error parsing a valid node: %v", err) 166 } 167 168 // TestCase 2: invalid file in the reference should raise an error 169 si = &v2_2.Snippet{} 170 parser, _ = parserFromBodyContent(` 171 <spdx:File rdf:about="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#DoapSource"> 172 <spdx:fileName> test file </spdx:fileName> 173 </spdx:File> 174 `) 175 node = parser.gordfParserObj.Triples[0].Subject 176 err = parser.parseRangeReference(node, si) 177 if err == nil { 178 t.Errorf("expected an error due to invalid file in the range reference, got %v", err) 179 } 180 181 // TestCase 3: A valid reference must set the file to the files map of the parser. 182 si = &v2_2.Snippet{} 183 parser, _ = parserFromBodyContent(` 184 <spdx:File rdf:about="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"> 185 <spdx:fileName> test file </spdx:fileName> 186 </spdx:File> 187 `) 188 node = parser.gordfParserObj.Triples[0].Subject 189 err = parser.parseRangeReference(node, si) 190 if err != nil { 191 t.Errorf("error parsing a valid input: %v", err) 192 } 193 if len(parser.files) != 1 { 194 t.Errorf("expected parser.files to have 1 file, found %d", len(parser.files)) 195 } 196} 197 198func Test_rdfParser2_2_getPointerFromNode(t *testing.T) { 199 var parser *rdfParser2_2 200 var node *gordfParser.Node 201 var si *v2_2.Snippet 202 var err error 203 var rt RangeType 204 var number int 205 206 // TestCase 1: invalid number in the offset field must raise an error. 207 parser, _ = parserFromBodyContent(` 208 <j.0:startPointer> 209 <j.0:LineCharPointer> 210 <j.0:reference rdf:resource="#SPDXRef-DoapSource"/> 211 <j.0:offset>3-10</j.0:offset> 212 </j.0:LineCharPointer> 213 </j.0:startPointer> 214 `) 215 node = parser.gordfParserObj.Triples[0].Subject 216 _, _, err = parser.getPointerFromNode(node, si) 217 if err == nil { 218 t.Errorf("should've raised an error parsing invalid offset, got %v", err) 219 } 220 221 // TestCase 2: invalid number in the lineNumber field must raise an error. 222 parser, _ = parserFromBodyContent(` 223 <j.0:ByteOffsetPointer> 224 <j.0:reference rdf:resource="#SPDXRef-DoapSource"/> 225 <j.0:offset>3-10</j.0:offset> 226 </j.0:ByteOffsetPointer> 227 `) 228 node = parser.gordfParserObj.Triples[0].Subject 229 _, _, err = parser.getPointerFromNode(node, si) 230 if err == nil { 231 t.Errorf("should've raised an error parsing invalid offset, got %v", err) 232 } 233 234 // TestCase 3: invalid predicate in the pointer field 235 parser, _ = parserFromBodyContent(` 236 <j.0:ByteOffsetPointer> 237 <spdx:invalidTag /> 238 <j.0:reference rdf:resource="#SPDXRef-DoapSource"/> 239 <j.0:lineNumber>3-10</j.0:lineNumber> 240 </j.0:ByteOffsetPointer> 241 `) 242 node = parser.gordfParserObj.Triples[0].Subject 243 _, _, err = parser.getPointerFromNode(node, si) 244 if err == nil { 245 t.Errorf("should've raised an error parsing invalid predicate, got %v", err) 246 } 247 248 // TestCase 4: No range type defined must also raise an error 249 parser, _ = parserFromBodyContent(` 250 <j.0:ByteOffsetPointer> 251 <j.0:reference rdf:resource="#SPDXRef-DoapSource"/> 252 </j.0:ByteOffsetPointer> 253 `) 254 node = parser.gordfParserObj.Triples[0].Subject 255 _, _, err = parser.getPointerFromNode(node, si) 256 if err == nil { 257 t.Errorf("should've raised an error parsing invalid rangeType, got %v", err) 258 } 259 260 // TestCase 5: valid example 261 parser, _ = parserFromBodyContent(` 262 <j.0:ByteOffsetPointer> 263 <j.0:reference rdf:resource="#SPDXRef-DoapSource"/> 264 <j.0:offset>310</j.0:offset> 265 </j.0:ByteOffsetPointer> 266 `) 267 node = parser.gordfParserObj.Triples[0].Subject 268 rt, number, err = parser.getPointerFromNode(node, si) 269 if err != nil { 270 t.Fatalf("unexpected error parsing a valid node: %v", err) 271 } 272 if rt != BYTE_RANGE { 273 t.Errorf("expected: %s, got: %s", BYTE_RANGE, rt) 274 } 275 if number != 310 { 276 t.Errorf("expected: %d, got: %d", 310, number) 277 } 278} 279 280func Test_rdfParser2_2_setSnippetRangeFromNode(t *testing.T) { 281 var parser *rdfParser2_2 282 var err error 283 var si *v2_2.Snippet 284 var node *gordfParser.Node 285 286 // TestCase 1: range with less one pointer less must raise an error 287 // (end-pointer missing in the range) 288 parser, _ = parserFromBodyContent(` 289 <j.0:StartEndPointer> 290 <j.0:startPointer> 291 <j.0:LineCharPointer> 292 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 293 <j.0:offset>310</j.0:offset> 294 </j.0:LineCharPointer> 295 </j.0:startPointer> 296 </j.0:StartEndPointer> 297 298 `) 299 si = &v2_2.Snippet{} 300 node = parser.gordfParserObj.Triples[0].Subject 301 err = parser.setSnippetRangeFromNode(node, si) 302 if err == nil { 303 t.Errorf("expected an error due to missing end pointer, got %v", err) 304 } 305 306 // TestCase 2: triples with 0 or more than one type-triple 307 parser, _ = parserFromBodyContent(` 308 309 <j.0:StartEndPointer> 310 <j.0:endPointer> 311 <j.0:ByteOffsetPointer> 312 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 313 <j.0:offset>420</j.0:offset> 314 </j.0:ByteOffsetPointer> 315 </j.0:endPointer> 316 <j.0:startPointer> 317 <j.0:ByteOffsetPointer> 318 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 319 <j.0:offset>310</j.0:offset> 320 </j.0:ByteOffsetPointer> 321 </j.0:startPointer> 322 </j.0:StartEndPointer> 323 324 `) 325 si = &v2_2.Snippet{} 326 node = parser.gordfParserObj.Triples[0].Subject 327 dummyTriple := parser.gordfParserObj.Triples[0] 328 // resetting the node to be associated with 3 triples which will have 329 // rdf:type triple either thrice or 0 times. 330 parser.nodeStringToTriples[node.String()] = []*gordfParser.Triple{ 331 dummyTriple, dummyTriple, dummyTriple, 332 } 333 err = parser.setSnippetRangeFromNode(node, si) 334 if err == nil { 335 t.Errorf("expected an error due to invalid rdf:type triples, got %v", err) 336 } 337 338 // TestCase 3: triples with 0 startPointer 339 parser, _ = parserFromBodyContent(` 340 <j.0:StartEndPointer> 341 <j.0:endPointer> 342 <j.0:ByteOffsetPointer> 343 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 344 <j.0:offset>420</j.0:offset> 345 </j.0:ByteOffsetPointer> 346 </j.0:endPointer> 347 <j.0:endPointer> 348 <j.0:LineCharPointer> 349 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 350 <j.0:offset>310</j.0:offset> 351 </j.0:LineCharPointer> 352 </j.0:endPointer> 353 </j.0:StartEndPointer> 354 `) 355 si = &v2_2.Snippet{} 356 node = parser.gordfParserObj.Triples[0].Subject 357 err = parser.setSnippetRangeFromNode(node, si) 358 if err == nil { 359 t.Errorf("expected an error due to missing start pointer, got %v", err) 360 } 361 362 // TestCase 4: triples with 0 endPointer 363 parser, _ = parserFromBodyContent(` 364 <j.0:StartEndPointer> 365 <j.0:endPointer> 366 <j.0:ByteOffsetPointer> 367 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 368 <j.0:offset>420</j.0:offset> 369 </j.0:ByteOffsetPointer> 370 </j.0:endPointer> 371 <j.0:endPointer> 372 <j.0:LineCharPointer> 373 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 374 <j.0:offset>310</j.0:offset> 375 </j.0:LineCharPointer> 376 </j.0:endPointer> 377 </j.0:StartEndPointer> 378 `) 379 si = &v2_2.Snippet{} 380 node = parser.gordfParserObj.Triples[0].Subject 381 err = parser.setSnippetRangeFromNode(node, si) 382 if err == nil { 383 t.Errorf("expected an error due to missing end pointer, got %v", err) 384 } 385 386 // TestCase 5: error parsing start pointer must be propagated to the range 387 parser, _ = parserFromBodyContent(` 388 <j.0:StartEndPointer> 389 <j.0:startPointer> 390 <j.0:ByteOffsetPointer> 391 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 392 <j.0:offset>42.0</j.0:offset> 393 </j.0:ByteOffsetPointer> 394 </j.0:startPointer> 395 <j.0:endPointer> 396 <j.0:ByteOffsetPointer> 397 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 398 <j.0:offset>310</j.0:offset> 399 </j.0:ByteOffsetPointer> 400 </j.0:endPointer> 401 </j.0:StartEndPointer> 402 `) 403 si = &v2_2.Snippet{} 404 node = parser.gordfParserObj.Triples[0].Subject 405 err = parser.setSnippetRangeFromNode(node, si) 406 if err == nil { 407 t.Errorf("expected an error due to invalid start pointer, got %v", err) 408 } 409 410 // TestCase 6: error parsing end pointer must be propagated to the range 411 parser, _ = parserFromBodyContent(` 412 <j.0:StartEndPointer> 413 <j.0:startPointer> 414 <j.0:ByteOffsetPointer> 415 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 416 <j.0:offset>420</j.0:offset> 417 </j.0:ByteOffsetPointer> 418 </j.0:startPointer> 419 <j.0:endPointer> 420 <j.0:ByteOffsetPointer> 421 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 422 <j.0:offset>31+0</j.0:offset> 423 </j.0:ByteOffsetPointer> 424 </j.0:endPointer> 425 </j.0:StartEndPointer> 426 `) 427 si = &v2_2.Snippet{} 428 node = parser.gordfParserObj.Triples[0].Subject 429 err = parser.setSnippetRangeFromNode(node, si) 430 if err == nil { 431 t.Errorf("expected an error due to invalid end pointer, got %v", err) 432 } 433 434 // TestCase 7: mismatching start and end pointer must also raise an error. 435 parser, _ = parserFromBodyContent(` 436 <j.0:StartEndPointer> 437 <j.0:startPointer> 438 <j.0:ByteOffsetPointer> 439 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 440 <j.0:offset>420</j.0:offset> 441 </j.0:ByteOffsetPointer> 442 </j.0:startPointer> 443 <j.0:endPointer> 444 <j.0:LineCharPointer> 445 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 446 <j.0:lineNumber>310</j.0:lineNumber> 447 </j.0:LineCharPointer> 448 </j.0:endPointer> 449 </j.0:StartEndPointer> 450 `) 451 si = &v2_2.Snippet{} 452 node = parser.gordfParserObj.Triples[0].Subject 453 err = parser.setSnippetRangeFromNode(node, si) 454 if err == nil { 455 t.Errorf("expected an error due to mismatching start and end pointers, got %v", err) 456 } 457 458 // TestCase 8: everything valid(byte_range): 459 parser, _ = parserFromBodyContent(` 460 <j.0:StartEndPointer> 461 <j.0:startPointer> 462 <j.0:ByteOffsetPointer> 463 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 464 <j.0:offset>420</j.0:offset> 465 </j.0:ByteOffsetPointer> 466 </j.0:startPointer> 467 <j.0:endPointer> 468 <j.0:ByteOffsetPointer> 469 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 470 <j.0:offset>310</j.0:offset> 471 </j.0:ByteOffsetPointer> 472 </j.0:endPointer> 473 </j.0:StartEndPointer> 474 `) 475 si = &v2_2.Snippet{} 476 node = parser.gordfParserObj.Triples[0].Subject 477 err = parser.setSnippetRangeFromNode(node, si) 478 if err != nil { 479 t.Errorf("unexpected error: %v", err) 480 } 481 482 // TestCase 9: everything valid(line_range): 483 parser, _ = parserFromBodyContent(` 484 <j.0:StartEndPointer> 485 <j.0:startPointer> 486 <j.0:LineCharPointer> 487 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 488 <j.0:lineNumber>420</j.0:lineNumber> 489 </j.0:LineCharPointer> 490 </j.0:startPointer> 491 <j.0:endPointer> 492 <j.0:LineCharPointer> 493 <j.0:reference rdf:resource="http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DoapSource"/> 494 <j.0:lineNumber>310</j.0:lineNumber> 495 </j.0:LineCharPointer> 496 </j.0:endPointer> 497 </j.0:StartEndPointer> 498 `) 499 si = &v2_2.Snippet{} 500 node = parser.gordfParserObj.Triples[0].Subject 501 err = parser.setSnippetRangeFromNode(node, si) 502 if err != nil { 503 t.Errorf("unexpected error: %v", err) 504 } 505} 506 507func Test_rdfParser2_2_setSnippetToFileWithID(t *testing.T) { 508 var parser *rdfParser2_2 509 var fileId common.ElementID 510 var si *v2_2.Snippet 511 var file *v2_2.File 512 var err error 513 514 // TestCase 1: file id which is not associated with any file must raise an error. 515 parser, _ = parserFromBodyContent("") 516 si = &v2_2.Snippet{} 517 err = parser.setSnippetToFileWithID(si, fileId) 518 if err == nil { 519 t.Errorf("expected an error saying undefined file") 520 } 521 522 // TestCase 2: file exists, but snippet of the file doesn't ( it mustn't raise any error ) 523 fileId = common.ElementID("File1") 524 file = &v2_2.File{ 525 FileSPDXIdentifier: fileId, 526 } 527 parser.files[fileId] = file 528 file.Snippets = nil // nil snippets 529 err = parser.setSnippetToFileWithID(si, fileId) 530 if err != nil { 531 t.Errorf("unexpected error: %v", err) 532 } 533 if len(file.Snippets) != 1 { 534 t.Errorf("expected file to have 1 snippet, got %d", len(file.Snippets)) 535 } 536} 537