github.com/kaptinlin/jsonschema@v0.4.6/tests/utils.go (about) 1 package tests 2 3 import ( 4 "context" 5 "errors" 6 "log" 7 "net/http" 8 "os" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/goccy/go-json" 14 "github.com/kaptinlin/jsonschema" 15 ) 16 17 // Helper function to create *float64 18 func ptrFloat64(v float64) *float64 { 19 return &v 20 } 21 22 // Helper function to create *string 23 func ptrString(v string) *string { 24 return &v 25 } 26 27 // startTestServer starts an HTTP server for serving remote schemas. 28 func startTestServer() *http.Server { 29 server := &http.Server{ 30 Addr: ":1234", 31 Handler: http.FileServer(http.Dir("../testdata/JSON-Schema-Test-Suite/remotes")), 32 ReadHeaderTimeout: 1 * time.Second, 33 } 34 35 go func() { 36 if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { 37 log.Fatalf("Failed to start server: %v", err) 38 } 39 }() 40 41 // Give the server a moment to start 42 time.Sleep(100 * time.Millisecond) 43 return server 44 } 45 46 // stopTestServer stops the given HTTP server. 47 func stopTestServer(server *http.Server) { 48 if err := server.Shutdown(context.TODO()); err != nil { 49 log.Fatalf("Failed to shutdown server: %v", err) 50 } 51 } 52 53 // TestJSONSchemaTestSuiteWithFilePath runs schema validation tests from a JSON file against the ForTestSuiteschema implementation. 54 func testJSONSchemaTestSuiteWithFilePath(t *testing.T, filePath string, exclusions ...string) { 55 t.Helper() 56 57 // Start the server 58 server := startTestServer() 59 defer stopTestServer(server) 60 61 // Read the JSON file containing the test definitions. 62 data, err := os.ReadFile(filePath) //nolint:gosec 63 if err != nil { 64 t.Fatalf("Failed to read test file: %s", err) 65 } 66 67 type Test struct { 68 Description string `json:"description"` 69 Data interface{} `json:"data"` 70 Valid bool `json:"valid"` 71 } 72 type TestCase struct { 73 Description string `json:"description"` 74 SchemaData interface{} `json:"schema"` 75 Tests []Test `json:"tests"` 76 } 77 var testCases []TestCase 78 79 // Unmarshal the JSON into the test cases struct. 80 if err := json.Unmarshal(data, &testCases); err != nil { 81 t.Fatalf("Failed to unmarshal test cases: %v", err) 82 } 83 84 exclusionMap := make(map[string]bool) 85 for _, exc := range exclusions { 86 exclusionMap[exc] = true 87 } 88 89 // Run each test case. 90 for _, tc := range testCases { 91 t.Run(tc.Description, func(t *testing.T) { 92 if exclusionMap[tc.Description] { 93 t.Skip("Skipping test case due to exclusion settings.") 94 } 95 96 // Convert schema data into JSON bytes and compile it into a Schema object. 97 schemaJSON, err := json.Marshal(tc.SchemaData) 98 if err != nil { 99 t.Fatalf("Failed to marshal schema data: %v", err) 100 } 101 102 // Initialize the compiler with necessary configurations. 103 compiler := jsonschema.NewCompiler() 104 105 // Assert format for optional/format test cases. 106 if strings.Contains(filePath, "optional/format") { 107 compiler.SetAssertFormat(true) 108 } 109 110 schema, err := compiler.Compile(schemaJSON) 111 if err != nil { 112 t.Fatalf("Failed to compile schema: %v", err) 113 } 114 115 for _, test := range tc.Tests { 116 if exclusionMap[tc.Description+"/"+test.Description] { 117 t.Run(test.Description, func(t *testing.T) { 118 t.Skip("Skipping test due to nested exclusion settings.") 119 }) 120 continue 121 } 122 t.Run(test.Description, func(t *testing.T) { 123 // Evaluate the data against the schema. 124 result := schema.Validate(test.Data) 125 126 // Check if the test should pass or fail. 127 if test.Valid { 128 if !result.IsValid() { 129 t.Errorf("Expected data to be valid, but got error: %v", result.ToList()) 130 } 131 } else { 132 if result.IsValid() { 133 t.Error("Expected data to be invalid, but got no error") 134 } 135 } 136 }) 137 } 138 }) 139 } 140 }