// Validate validates the provided data (d) against the provided schema (s). func Validate(ctx types.Context, s, d []byte) error { if ctx == nil { log.StandardLogger().WithFields(log.Fields{ "schema": string(s), "body": string(d), }).Debug("validating schema") } else { ctx.WithFields(log.Fields{ "schema": string(s), "body": string(d), }).Debug("validating schema") } validator, err := getSchemaValidator(s) if err != nil { return err } if len(d) == 0 { d = []byte("{}") } data, err := ucl.Parse(bytes.NewReader(d)) if err != nil { return err } return validator.Validate(data) }
func TestCompliance(t *testing.T) { done := make(chan struct{}) go serveRemotes(t, done) f, err := os.Open("draft04schema.json") if err != nil { t.Fatalf("Failed to open draft04schema.json: %s", err) } s, err := json.Parse(f) f.Close() if err != nil { t.Fatalf("Failed to parse draft04schema.json: %s", err) } loader := NewLoader() loader.Add(s) loader.EnableNetworkAccess(true) select { case <-done: t.Fatalf("HTTP server died") default: } files, err := filepath.Glob("schema-tests/tests/draft4/*.json") if err != nil { t.Fatalf("Test files not found: %s", err) } testFiles(t, files, loader) }
func testFiles(t *testing.T, files []string, loader *Loader) { var passing, total, schemaErrors int for _, file := range files { f, err := os.Open(file) if err != nil { t.Fatalf("Failed to open %q: %s", file, err) } v, err := json.Parse(f) f.Close() if err != nil { t.Fatalf("Failed to parse %q: %s", file, err) } tests, ok := v.(*json.Array) if !ok { t.Fatalf("Content of %q is not an array: %T", file, v) } for i, tt := range tests.Value { test, ok := tt.(*json.Object) if !ok { t.Fatalf("Test %d in %q is not an object", i, file) } t.Logf(color.BlueString("=====> Testing %s, case %d: %s", file, i, test.Find("description"))) schema := test.Find("schema") err := ValidateDraft04Schema(schema) if err != nil { t.Errorf(color.RedString("schema does not pass validation: %s", err)) schemaErrors++ } v, _ := NewValidator(schema, loader) // not checking the error since schema is already validated cases := test.Find("tests").(*json.Array) for _, c := range cases.Value { total++ case_ := c.(*json.Object) valid := case_.Find("valid").(*json.Bool).Value err := v.Validate(case_.Find("data")) switch { case err == nil && valid: passing++ t.Logf("%s %s", color.GreenString("PASSED"), case_.Find("description")) case err != nil && !valid: passing++ t.Logf("%s %s: %s", color.GreenString("PASSED"), case_.Find("description"), err) case err != nil && valid: t.Errorf("%s %s: %s", color.RedString("FAILED"), case_.Find("description"), err) case err == nil && !valid: t.Errorf("%s %s", color.RedString("FAILED"), case_.Find("description")) } } } } t.Logf("Passing %d out of %d tests (%g%%)", passing, total, float64(passing)/float64(total)*100) if schemaErrors > 0 { t.Logf("%d schemas failed validation", schemaErrors) } }
func getSchemaValidator(s []byte) (*schema.Validator, error) { volSchema, err := ucl.Parse(bytes.NewReader(s)) if err != nil { return nil, err } rootSchema, err := ucl.Parse(bytes.NewReader(jsonSchema)) if err != nil { return nil, err } loader := schema.NewLoader() if err := loader.Add(rootSchema); err != nil { return nil, err } validator, err := schema.NewValidator(volSchema, loader) if err != nil { return nil, err } return validator, nil }
// Get returns a schema identified with id. func (l *Loader) Get(id string) (json.Value, error) { s, found := l.cache[id] if found { return s, nil } if l.networkEnabled { resp, err := http.Get(id) if err != nil { return nil, err } s, err := json.Parse(resp.Body) resp.Body.Close() if err != nil { return nil, err } l.AddAs(s, id) return s, nil } return nil, fmt.Errorf("schema %q is not present in the cache and fetching is disabled", id) }
func main() { flag.Parse() if *schemaFile == "" || *inputFile == "" { fmt.Fprintf(os.Stderr, "Need --schema and --input\n") os.Exit(1) } f, err := os.Open(*schemaFile) if err != nil { fmt.Fprintf(os.Stderr, "Failed to open %q: %s\n", *schemaFile, err) os.Exit(1) } s, err := json.Parse(f) f.Close() if err != nil { fmt.Fprintf(os.Stderr, "Failed to read schema: %s\n", err) os.Exit(1) } loader := schema.NewLoader() loader.EnableNetworkAccess(*network) if *extra != "" { for _, file := range strings.Split(*extra, " ") { f, err := os.Open(file) if err != nil { fmt.Fprintf(os.Stderr, "Failed to open %q: %s\n", file, err) os.Exit(1) } s, err := json.Parse(f) f.Close() if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse %q: %s\n", file, err) os.Exit(1) } loader.Add(s) } } if !*skipDefaultSchema { ds, err := json.Parse(bytes.NewBuffer(MustAsset("draft04schema.json"))) if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse embedded draft 04 schema: %s\n", err) os.Exit(1) } // Just to be sure, schema.ParseDraft04Schema exercises different code path. v, err := schema.NewValidator(ds, loader) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create validator for draft04 schema, please file a bug: %s\n", err) } else { if err := v.Validate(s); err != nil { fmt.Fprintln(os.Stderr, "If you see this message, please file a bug and attach the schema you're using.") fmt.Fprintf(os.Stderr, "Warning: failed to validate %q with draft 04 schema: %s\n", *schemaFile, err) } } } validator, err := schema.NewValidator(s, loader) if err != nil { fmt.Fprintf(os.Stderr, "Failed to create validator: %s\n", err) os.Exit(1) } f, err = os.Open(*inputFile) if err != nil { fmt.Fprintf(os.Stderr, "Failed to open input file: %s\n", err) os.Exit(1) } defer f.Close() data, err := json.Parse(f) if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse input file: %s\n", err) os.Exit(1) } if err := validator.Validate(data); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }