// Copyright 2017 johandorland ( https://github.com/johandorland ) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gojsonschema import ( "encoding/json" "fmt" "io/ioutil" "net/http" "os" "path/filepath" "regexp" "runtime" "strings" "testing" ) type jsonSchemaTest struct { Description string `json:"description"` // Some tests may not always pass, so some tests are manually edited to include // an extra attribute whether that specific test should be disabled and skipped Disabled bool `json:"disabled"` Schema interface{} `json:"schema"` Tests []jsonSchemaTestCase `json:"tests"` } type jsonSchemaTestCase struct { Description string `json:"description"` Data interface{} `json:"data"` Valid bool `json:"valid"` } //Skip any directories not named appropiately // filepath.Walk will also visit files in the root of the test directory var testDirectories = regexp.MustCompile(`(draft\d+)`) var draftMapping = map[string]Draft{ "draft4": Draft4, "draft6": Draft6, "draft7": Draft7, } func executeTests(t *testing.T, path string) error { file, err := os.Open(path) if err != nil { t.Errorf("Error (%s)\n", err.Error()) } fmt.Println(file.Name()) var tests []jsonSchemaTest d := json.NewDecoder(file) d.UseNumber() err = d.Decode(&tests) if err != nil { t.Errorf("Error (%s)\n", err.Error()) } draft := Hybrid if m := testDirectories.FindString(path); m != "" { draft = draftMapping[m] } for _, test := range tests { fmt.Println(" " + test.Description) if test.Disabled { continue } testSchemaLoader := NewRawLoader(test.Schema) sl := NewSchemaLoader() sl.Draft = draft sl.Validate = true testSchema, err := sl.Compile(testSchemaLoader) if err != nil { t.Errorf("Error (%s)\n", err.Error()) } for _, testCase := range test.Tests { testDataLoader := NewRawLoader(testCase.Data) result, err := testSchema.Validate(testDataLoader) if err != nil { t.Errorf("Error (%s)\n", err.Error()) } if result.Valid() != testCase.Valid { schemaString, _ := marshalToJsonString(test.Schema) testCaseString, _ := marshalToJsonString(testCase.Data) t.Errorf("Test failed : %s\n"+ "%s.\n"+ "%s.\n"+ "expects: %t, given %t\n"+ "Schema: %s\n"+ "Data: %s\n", file.Name(), test.Description, testCase.Description, testCase.Valid, result.Valid(), *schemaString, *testCaseString) } } } return nil } func TestSuite(t *testing.T) { wd, err := os.Getwd() if err != nil { panic(err.Error()) } wd = filepath.Join(wd, "testdata") go func() { err := http.ListenAndServe(":1234", http.FileServer(http.Dir(filepath.Join(wd, "remotes")))) if err != nil { panic(err.Error()) } }() err = filepath.Walk(wd, func(path string, fileInfo os.FileInfo, err error) error { if fileInfo.IsDir() && path != wd && !testDirectories.MatchString(fileInfo.Name()) { return filepath.SkipDir } if !strings.HasSuffix(fileInfo.Name(), ".json") { return nil } return executeTests(t, path) }) if err != nil { t.Errorf("Error (%s)\n", err.Error()) } } func TestFormats(t *testing.T) { // Go 1.5 and 1.6 contain minor bugs in parsing URIs and unicode which makes the test suite fail uri and idn-email formats // Therefore disable these tests for these go versions if strings.HasPrefix(runtime.Version(), "go1.5") || strings.HasPrefix(runtime.Version(), "go1.6") { return } wd, err := os.Getwd() if err != nil { panic(err.Error()) } wd = filepath.Join(wd, "testdata") dirs, err := ioutil.ReadDir(wd) if err != nil { panic(err.Error()) } for _, dir := range dirs { if testDirectories.MatchString(dir.Name()) { formatsDirectory := filepath.Join(wd, dir.Name(), "optional", "format") err = filepath.Walk(formatsDirectory, func(path string, fileInfo os.FileInfo, err error) error { if fileInfo == nil || !strings.HasSuffix(fileInfo.Name(), ".json") { return nil } return executeTests(t, path) }) if err != nil { t.Errorf("Error (%s)\n", err.Error()) } } } }