github.com/CycloneDX/sbom-utility@v0.16.0/cmd/query_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * Licensed to the Apache Software Foundation (ASF) under one or more 4 * contributor license agreements. See the NOTICE file distributed with 5 * this work for additional information regarding copyright ownership. 6 * The ASF licenses this file to You under the Apache License, Version 2.0 7 * (the "License"); you may not use this file except in compliance with 8 * the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package cmd 20 21 import ( 22 "bufio" 23 "bytes" 24 "encoding/json" 25 "fmt" 26 "io" 27 "io/fs" 28 "os" 29 "testing" 30 31 "github.com/CycloneDX/sbom-utility/common" 32 "github.com/CycloneDX/sbom-utility/schema" 33 "github.com/CycloneDX/sbom-utility/utils" 34 ) 35 36 // ------------------------------------------- 37 // test helper functions 38 // ------------------------------------------- 39 40 func innerQueryError(t *testing.T, cti *CommonTestInfo, queryRequest *common.QueryRequest, expectedError error) (result interface{}, actualError error) { 41 getLogger().Enter() 42 defer getLogger().Exit() 43 44 result, _, actualError = innerQuery(t, cti, queryRequest) 45 46 // if the query resulted in a failure 47 if !ErrorTypesMatch(actualError, expectedError) { 48 getLogger().Tracef("expected error type: `%T`, actual type: `%T`", expectedError, actualError) 49 t.Errorf("expected error type: `%T`, actual type: `%T`", expectedError, actualError) 50 } 51 return 52 } 53 54 // NOTE: This function "mocks" what the "queryCmdImpl()" function would do 55 func innerQuery(t *testing.T, cti *CommonTestInfo, queryRequest *common.QueryRequest) (resultJson interface{}, outputBuffer bytes.Buffer, err error) { 56 getLogger().Enter() 57 defer getLogger().Exit() 58 59 // Copy the test filename to the command line flags were the code looks for it 60 utils.GlobalFlags.PersistentFlags.InputFile = cti.InputFile 61 62 // allocate response/result object and invoke query 63 var queryResponse = new(common.QueryResponse) 64 resultJson, outputBuffer, err = innerBufferedTestQuery(cti, queryRequest, queryResponse) 65 66 // if the command resulted in a failure 67 if err != nil { 68 // if tests asks us to report a FAIL to the test framework 69 if cti.Autofail { 70 encodedTestInfo, _ := utils.EncodeAnyToDefaultIndentedJSONStr(queryRequest) 71 t.Errorf("%s: failed: %v\nQueryRequest:\n%s", cti.InputFile, err, encodedTestInfo.String()) 72 } 73 return 74 } 75 76 // Log results if trace enabled 77 if err != nil { 78 var buffer bytes.Buffer 79 buffer, err = utils.EncodeAnyToDefaultIndentedJSONStr(resultJson) 80 // Output the JSON data directly to stdout (not subject to log-level) 81 getLogger().Tracef("%s\n", buffer.String()) 82 } 83 return 84 } 85 86 func innerBufferedTestQuery(testInfo *CommonTestInfo, queryRequest *common.QueryRequest, queryResponse *common.QueryResponse) (resultJson interface{}, outputBuffer bytes.Buffer, err error) { 87 88 // The command looks for the input & output filename in global flags struct 89 utils.GlobalFlags.PersistentFlags.InputFile = testInfo.InputFile 90 utils.GlobalFlags.PersistentFlags.OutputFile = testInfo.OutputFile 91 utils.GlobalFlags.PersistentFlags.OutputFormat = testInfo.OutputFormat 92 utils.GlobalFlags.PersistentFlags.OutputIndent = testInfo.OutputIndent 93 var outputWriter io.Writer 94 var outputFile *os.File 95 96 // TODO: centralize this logic to a function all Commands can use... 97 // Note: Any "Mocking" of os.Stdin/os.Stdout should be done in functions that call this one 98 if testInfo.OutputFile == "" { 99 // Declare an output outputBuffer/outputWriter to use used during tests 100 bufferedWriter := bufio.NewWriter(&outputBuffer) 101 outputWriter = bufferedWriter 102 // MUST ensure all data is written to buffer before further testing 103 defer bufferedWriter.Flush() 104 } else { 105 outputFile, outputWriter, err = createOutputFile(testInfo.OutputFile) 106 getLogger().Tracef("outputFile: `%v`; writer: `%v`", testInfo.OutputFile, outputWriter) 107 108 // use function closure to assure consistent error output based upon error type 109 defer func() { 110 // always close the output file (even if error, as long as file handle returned) 111 if outputFile != nil { 112 outputFile.Close() 113 getLogger().Infof("Closed output file: `%s`", testInfo.OutputFile) 114 } 115 }() 116 117 if err != nil { 118 return 119 } 120 } 121 122 resultJson, err = Query(outputWriter, queryRequest, queryResponse) 123 return 124 } 125 126 // Used to help verify query results 127 func UnmarshalResultsToMap(results interface{}) (resultMap map[string]interface{}, err error) { 128 getLogger().Enter() 129 defer getLogger().Exit() 130 131 // we need to marshal the data to normalize it to a []byte 132 var resultBytes []byte 133 resultBytes, err = json.Marshal(results) 134 if err != nil { 135 return 136 } 137 138 err = json.Unmarshal(resultBytes, &resultMap) 139 if err != nil { 140 return 141 } 142 143 return 144 } 145 146 // Used to verify fields specified on a SELECT clause appear in JSON results (map) 147 func VerifySelectedFieldsInJsonMap(t *testing.T, keys []string, results interface{}) (exists bool, err error) { 148 149 if results == nil { 150 t.Errorf("invalid results: %v", results) 151 } 152 153 resultMap, err := UnmarshalResultsToMap(results) 154 if err != nil { 155 getLogger().Tracef("results: %v", resultMap) 156 t.Errorf("invalid JSON: %s: %v", err, resultMap) 157 } 158 159 for _, key := range keys { 160 _, exists = resultMap[key] 161 if !exists { 162 t.Errorf("invalid results: key: `%s` does not exist.", key) 163 } 164 } 165 return 166 } 167 168 // ---------------------------------------- 169 // Command flag tests 170 // ---------------------------------------- 171 172 func TestQueryFailInvalidInputFileLoad(t *testing.T) { 173 cti := NewCommonTestInfoBasic(TEST_INPUT_FILE_NON_EXISTENT) 174 request, _ := common.NewQueryRequestSelectWildcardFrom( 175 "metadata.properties") 176 // Assure we return path error 177 _, _ = innerQueryError(t, cti, request, &fs.PathError{}) 178 } 179 180 // ---------------------------------------- 181 // PASS tests 182 // ---------------------------------------- 183 184 func TestQueryCdx14BomFormatSpecVersion(t *testing.T) { 185 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 186 request, _ := common.NewQueryRequestSelectFrom( 187 "bomFormat,specVersion", 188 "") 189 results, _ := innerQueryError(t, cti, request, nil) 190 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 191 } 192 193 func TestQueryCdx14MetadataTimestampField(t *testing.T) { 194 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 195 request, _ := common.NewQueryRequestSelectFrom( 196 "timestamp", 197 "metadata") 198 results, _ := innerQueryError(t, cti, request, nil) 199 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 200 } 201 202 func TestQueryCdx14MetadataComponentAll(t *testing.T) { 203 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 204 request, _ := common.NewQueryRequestSelectWildcardFrom( 205 "metadata.component") 206 results, _ := innerQueryError(t, cti, request, nil) 207 // Test for concrete keys that SHOULD have been found using wildcard 208 fields := []string{ 209 "type", "bom-ref", "purl", "version", "externalReferences", 210 "name", "description", "licenses", "properties", "hashes", 211 "supplier", "publisher"} 212 _, _ = VerifySelectedFieldsInJsonMap(t, fields, results) 213 } 214 215 func TestQueryCdx14MetadataComponentNameDescriptionVersion(t *testing.T) { 216 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 217 request, _ := common.NewQueryRequestSelectFrom( 218 "name,description,version", 219 "metadata.component") 220 results, _ := innerQueryError(t, cti, request, nil) 221 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 222 } 223 224 func TestQueryCdx14MetadataSupplier(t *testing.T) { 225 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 226 request, _ := common.NewQueryRequestSelectFrom( 227 common.QUERY_TOKEN_WILDCARD, 228 "metadata.supplier") 229 results, _ := innerQueryError(t, cti, request, nil) 230 // Test for concrete keys that SHOULD have been found using wildcard 231 fields := []string{"name", "url", "contact"} 232 _, _ = VerifySelectedFieldsInJsonMap(t, fields, results) 233 } 234 235 func TestQueryCdx14MetadataManufacturer(t *testing.T) { 236 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 237 request, _ := common.NewQueryRequestSelectFrom( 238 common.QUERY_TOKEN_WILDCARD, 239 "metadata.manufacture") 240 results, _ := innerQueryError(t, cti, request, nil) 241 // Test for concrete keys that SHOULD have been found using wildcard 242 fields := []string{"name", "url", "contact"} 243 _, _ = VerifySelectedFieldsInJsonMap(t, fields, results) 244 } 245 246 func TestQueryCdx14MetadataComponentLicenses(t *testing.T) { 247 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 248 request, _ := common.NewQueryRequestSelectFrom( 249 "licenses", 250 "metadata.component") 251 results, _ := innerQueryError(t, cti, request, nil) 252 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 253 } 254 255 func TestQueryCdx14MetadataComponentSupplier(t *testing.T) { 256 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 257 request, _ := common.NewQueryRequestSelectFrom( 258 "supplier", 259 "metadata.component") 260 results, _ := innerQueryError(t, cti, request, nil) 261 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 262 } 263 264 func TestQueryCdx14MetadataComponentPublisher(t *testing.T) { 265 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 266 request, _ := common.NewQueryRequestSelectFrom( 267 "publisher", 268 "metadata.component") 269 results, _ := innerQueryError(t, cti, request, nil) 270 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 271 } 272 273 func TestQueryCdx14MetadataAllWithWildcard(t *testing.T) { 274 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 275 request, _ := common.NewQueryRequestSelectWildcardFrom( 276 "metadata.component") 277 results, _ := innerQueryError(t, cti, request, nil) 278 // Check for all known values that should be on the FROM object 279 fields := []string{"type", "bom-ref", "licenses", "properties", "publisher", "purl", "name", "description", "version", "externalReferences"} 280 _, _ = VerifySelectedFieldsInJsonMap(t, fields, results) 281 } 282 283 // NOTE: properties is an []interface 284 func TestQueryCdx14MetadataComponentProperties(t *testing.T) { 285 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 286 request, _ := common.NewQueryRequestSelectFrom( 287 "properties", 288 "metadata.component") 289 results, _ := innerQueryError(t, cti, request, nil) 290 _, _ = VerifySelectedFieldsInJsonMap(t, request.GetSelectKeys(), results) 291 } 292 293 // ---------------------------------------- 294 // FAIL tests 295 // ---------------------------------------- 296 297 func TestQueryFailSpdx22Metadata(t *testing.T) { 298 cti := NewCommonTestInfoBasic(TEST_SPDX_2_2_MIN_REQUIRED) 299 request, _ := common.NewQueryRequestSelectFrom( 300 common.QUERY_TOKEN_WILDCARD, 301 "metadata") 302 // Expect a QueryError 303 _, _ = innerQueryError(t, cti, request, &schema.UnsupportedFormatError{}) 304 } 305 306 func TestQueryFailCdx14MetadataComponentInvalidKey(t *testing.T) { 307 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 308 request, _ := common.NewQueryRequestSelectFrom( 309 common.QUERY_TOKEN_WILDCARD, 310 "metadata.component.foo") 311 expectedErrorStrings := []string{ 312 common.MSG_QUERY_INVALID_FROM_CLAUSE, 313 MSG_QUERY_ERROR_FROM_KEY_NOT_FOUND, 314 } 315 316 // Expect a QueryError 317 _, err := innerQueryError(t, cti, request, &common.QueryError{}) 318 319 // Assure we received an error with the expected key phrases 320 EvaluateErrorAndKeyPhrases(t, err, expectedErrorStrings) 321 } 322 323 func TestQueryFailCdx14MetadataComponentInvalidDataType(t *testing.T) { 324 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 325 request, _ := common.NewQueryRequestSelectFrom( 326 common.QUERY_TOKEN_WILDCARD, 327 "metadata.component.name") 328 // Expect a QueryResultInvalidTypeError 329 innerQueryError(t, cti, request, &common.QueryResultInvalidTypeError{}) 330 } 331 332 func TestQueryFailCdx14MetadataComponentInvalidSelectClause(t *testing.T) { 333 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 334 request, _ := common.NewQueryRequestSelectFrom( 335 "name,*", 336 "metadata.component") 337 expectedErrorStrings := []string{ 338 common.MSG_QUERY_INVALID_SELECT_CLAUSE, 339 MSG_QUERY_ERROR_SELECT_WILDCARD, 340 } 341 // Expect a QueryError 342 _, err := innerQueryError(t, cti, request, &common.QueryError{}) 343 // Assure we received an error with the expected key phrases 344 EvaluateErrorAndKeyPhrases(t, err, expectedErrorStrings) 345 } 346 347 func TestQueryFailCdx14InvalidFromClauseWithArray(t *testing.T) { 348 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 349 request, _ := common.NewQueryRequestSelectFrom( 350 common.QUERY_TOKEN_WILDCARD, 351 "metadata.properties.name") 352 expectedErrorStrings := []string{ 353 common.MSG_QUERY_INVALID_FROM_CLAUSE, 354 MSG_QUERY_ERROR_FROM_KEY_SLICE_DEREFERENCE, 355 } 356 // Expect a QueryError 357 _, err := innerQueryError(t, cti, request, &common.QueryError{}) 358 // Assure we received an error with the expected key phrases 359 EvaluateErrorAndKeyPhrases(t, err, expectedErrorStrings) 360 } 361 362 // ---------------------------------------- 363 // WHERE clause tests 364 // ---------------------------------------- 365 366 // Force a bad WHERE clause; expect a QueryError 367 func TestQueryCdx14InvalidWhereClauseNoRegex(t *testing.T) { 368 _, err := common.NewQueryRequestSelectFromWhere( 369 common.QUERY_TOKEN_WILDCARD, 370 "metadata.properties", 371 "name") 372 // Note: this tests the parameter parsing function 373 // TODO: move to "common" package 374 if !ErrorTypesMatch(err, &common.QueryError{}) { 375 t.Errorf("expected error type: `%T`, actual type: `%T`", &common.QueryError{}, err) 376 } 377 expectedErrorStrings := []string{ 378 common.MSG_QUERY_INVALID_WHERE_CLAUSE, 379 } 380 // Assure we received an error with the expected key phrases 381 EvaluateErrorAndKeyPhrases(t, err, expectedErrorStrings) 382 } 383 384 func TestQueryCdx14InvalidWhereClauseMultipleRegex(t *testing.T) { 385 _, err := common.NewQueryRequestSelectFromWhere( 386 common.QUERY_TOKEN_WILDCARD, 387 "metadata.properties", 388 "name=foo,value=bar=idk") 389 if !ErrorTypesMatch(err, &common.QueryError{}) { 390 t.Errorf("expected error type: `%T`, actual type: `%T`", &common.QueryError{}, err) 391 } 392 expectedErrorStrings := []string{ 393 common.MSG_QUERY_INVALID_WHERE_CLAUSE, 394 } 395 // Assure we received an error with the expected key phrases 396 EvaluateErrorAndKeyPhrases(t, err, expectedErrorStrings) 397 } 398 399 func TestQueryCdx14InvalidWhereClauseEmptyRegex(t *testing.T) { 400 _, err := common.NewQueryRequestSelectFromWhere( 401 common.QUERY_TOKEN_WILDCARD, 402 "metadata.properties", 403 "name=foo,value=") 404 if !ErrorTypesMatch(err, &common.QueryError{}) { 405 t.Errorf("expected error type: `%T`, actual type: `%T`", &common.QueryError{}, err) 406 } 407 expectedErrorStrings := []string{ 408 common.MSG_QUERY_INVALID_WHERE_CLAUSE, 409 } 410 // Assure we received an error with the expected key phrases 411 EvaluateErrorAndKeyPhrases(t, err, expectedErrorStrings) 412 } 413 414 func TestQueryCdx14RequiredDataLegalDisclaimer(t *testing.T) { 415 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 416 request, errNew := common.NewQueryRequestSelectFromWhere( 417 common.QUERY_TOKEN_WILDCARD, 418 "metadata.properties", 419 "name=urn:example.com:classification") 420 if errNew != nil { 421 t.Errorf("%s: %v", ERR_TYPE_UNEXPECTED_ERROR, errNew) 422 } 423 424 // WARN!!!! TODO: handle error tests locally until code is complete 425 result, _, err := innerQuery(t, cti, request) 426 if err != nil { 427 t.Errorf("%s: %v", ERR_TYPE_UNEXPECTED_ERROR, err) 428 } 429 430 properties, errUnMarshal := schema.UnMarshalProperties(result) 431 432 // TODO: declare error message as a constant 433 if errUnMarshal != nil { 434 t.Errorf("invalid `properties` data: %v", errUnMarshal) 435 } 436 437 // TODO: verify WHERE clause props. are returned 438 getLogger().Debugf("%v", properties) 439 } 440 441 func TestQueryCdx14InvalidWhereClauseOnFromSingleton(t *testing.T) { 442 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 443 request, _ := common.NewQueryRequestSelectFromWhere( 444 common.QUERY_TOKEN_WILDCARD, 445 "metadata.component", 446 "name=foo") 447 // Note: this produces a warning, not an error 448 _, err := innerQueryError(t, cti, request, nil) 449 if err != nil { 450 t.Error(err) 451 } 452 } 453 454 func TestQueryCdx14MetadataToolsSlice(t *testing.T) { 455 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 456 request, _ := common.NewQueryRequestSelectFromWhere( 457 common.QUERY_TOKEN_WILDCARD, 458 "metadata.tools", 459 "") 460 result, err := innerQueryError(t, cti, request, nil) 461 if err != nil { 462 t.Error(err) 463 } 464 if !utils.IsJsonSliceType(result) { 465 fResult, _ := utils.EncodeAnyToDefaultIndentedJSONStr(result) 466 t.Error(fmt.Errorf("expected JSON slice. Actual result: %s", fResult.String())) 467 } 468 469 // verify slice length and contents 470 slice := result.([]interface{}) 471 EXPECTED_SLICE_LENGTH := 2 472 if actualLength := len(slice); actualLength != EXPECTED_SLICE_LENGTH { 473 fResult, _ := utils.EncodeAnyToDefaultIndentedJSONStr(result) 474 t.Error(fmt.Errorf("expected slice length: %v, actual length: %v. Actual result: %s", EXPECTED_SLICE_LENGTH, actualLength, fResult.String())) 475 } 476 } 477 478 func TestQueryCdx14MetadataToolsSliceWhereName(t *testing.T) { 479 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 480 cti.ResultExpectedLineCount = 24 481 request, _ := common.NewQueryRequestSelectFromWhere( 482 common.QUERY_TOKEN_WILDCARD, 483 "components", 484 "name=body-parser") 485 result, err := innerQueryError(t, cti, request, nil) 486 if err != nil { 487 t.Error(err) 488 } 489 if !utils.IsJsonSliceType(result) { 490 fResult, _ := utils.EncodeAnyToDefaultIndentedJSONStr(result) 491 t.Error(fmt.Errorf("expected JSON slice. Actual result: %s", fResult.String())) 492 } 493 494 // verify slice length and contents 495 slice := result.([]interface{}) 496 EXPECTED_SLICE_LENGTH := 1 497 if actualLength := len(slice); actualLength != EXPECTED_SLICE_LENGTH { 498 fResult, _ := utils.EncodeAnyToDefaultIndentedJSONStr(result) 499 t.Error(fmt.Errorf("expected slice length: %v, actual length: %v. Actual result: %s", EXPECTED_SLICE_LENGTH, actualLength, fResult.String())) 500 } 501 buffer, _ := utils.EncodeAnyToIndentedJSONStr(result, utils.DEFAULT_JSON_INDENT_STRING) 502 verifyFileLineCountAndIndentation(t, buffer, cti) 503 } 504 505 func TestQueryCdx14MetadataComponentIndent(t *testing.T) { 506 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 507 cti.ResultExpectedLineCount = 6 508 cti.ResultExpectedIndentLength = DEFAULT_OUTPUT_INDENT_LENGTH 509 cti.ResultExpectedIndentAtLineNum = 1 510 request, _ := common.NewQueryRequestSelectFrom( 511 "name,description,version", 512 "metadata.component") 513 514 // Verify that JSON returned by the query command is able to apply default space indent 515 results, _ := innerQueryError(t, cti, request, nil) 516 buffer, _ := utils.EncodeAnyToIndentedJSONStr(results, utils.DEFAULT_JSON_INDENT_STRING) 517 // Validate output data 518 verifyFileLineCountAndIndentation(t, buffer, cti) 519 } 520 521 func TestQueryCdx14MetadataComponentIndentedFileWrite(t *testing.T) { 522 cti := NewCommonTestInfoBasic(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 523 cti.OutputFile = cti.CreateTemporaryTestOutputFilename(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE) 524 cti.OutputIndent = 3 525 cti.ResultExpectedLineCount = 6 526 cti.ResultExpectedIndentLength = int(cti.OutputIndent) 527 cti.ResultExpectedIndentAtLineNum = 1 528 request, _ := common.NewQueryRequestSelectFrom( 529 "name,description,version", 530 "metadata.component") 531 _, err := innerQueryError(t, cti, request, nil) 532 if err != nil { 533 t.Error(err) 534 } 535 536 var pBuffer *bytes.Buffer 537 pBuffer, err = bufferFile(cti.OutputFile) 538 if err != nil { 539 t.Error(err) 540 } 541 // Validate output data 542 verifyFileLineCountAndIndentation(t, *pBuffer, cti) 543 }