github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/test/cli/json_schema_test.go (about)

     1  package cli
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/xeipuuv/gojsonschema"
    10  
    11  	"github.com/anchore/stereoscope/pkg/imagetest"
    12  	"github.com/anchore/syft/internal"
    13  )
    14  
    15  // this is the path to the json schema directory relative to the root of the repo
    16  const jsonSchemaPath = "schema/json"
    17  
    18  func TestJSONSchema(t *testing.T) {
    19  
    20  	imageFixture := func(t *testing.T) string {
    21  		fixtureImageName := "image-pkg-coverage"
    22  		imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName)
    23  		tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName)
    24  		return "docker-archive:" + tarPath
    25  	}
    26  
    27  	tests := []struct {
    28  		name       string
    29  		subcommand string
    30  		args       []string
    31  		fixture    func(*testing.T) string
    32  	}{
    33  		{
    34  			name:       "packages:image:docker-archive:pkg-coverage",
    35  			subcommand: "packages",
    36  			args:       []string{"-o", "json"},
    37  			fixture:    imageFixture,
    38  		},
    39  		{
    40  			name:       "power-user:image:docker-archive:pkg-coverage",
    41  			subcommand: "power-user",
    42  			fixture:    imageFixture,
    43  		},
    44  		{
    45  			name:       "packages:dir:pkg-coverage",
    46  			subcommand: "packages",
    47  			args:       []string{"-o", "json"},
    48  			fixture: func(t *testing.T) string {
    49  				return "dir:test-fixtures/image-pkg-coverage"
    50  			},
    51  		},
    52  	}
    53  
    54  	for _, test := range tests {
    55  		t.Run(test.name, func(t *testing.T) {
    56  			fixtureRef := test.fixture(t)
    57  			args := []string{
    58  				test.subcommand, fixtureRef, "-q",
    59  			}
    60  			args = append(args, test.args...)
    61  
    62  			_, stdout, stderr := runSyft(t, nil, args...)
    63  
    64  			if len(strings.Trim(stdout, "\n ")) < 100 {
    65  				t.Fatalf("bad syft run:\noutput: %q\n:error: %q", stdout, stderr)
    66  			}
    67  
    68  			validateJsonAgainstSchema(t, stdout)
    69  		})
    70  	}
    71  }
    72  
    73  func validateJsonAgainstSchema(t testing.TB, json string) {
    74  	t.Helper()
    75  	fullSchemaPath := path.Join(repoRoot(t), jsonSchemaPath, fmt.Sprintf("schema-%s.json", internal.JSONSchemaVersion))
    76  	schemaLoader := gojsonschema.NewReferenceLoader(fmt.Sprintf("file://%s", fullSchemaPath))
    77  	documentLoader := gojsonschema.NewStringLoader(json)
    78  
    79  	result, err := gojsonschema.Validate(schemaLoader, documentLoader)
    80  	if err != nil {
    81  		t.Fatal("unable to validate json schema:", err.Error())
    82  	}
    83  
    84  	if !result.Valid() {
    85  		t.Errorf("failed json schema validation:")
    86  		t.Errorf("JSON:\n%s\n", json)
    87  		for _, desc := range result.Errors() {
    88  			t.Errorf("  - %s\n", desc)
    89  		}
    90  	}
    91  }