15
15
package jsonschema_test
16
16
17
17
import (
18
+ stdjson "encoding/json"
18
19
"fmt"
19
20
"os"
20
21
"path"
@@ -28,6 +29,7 @@ import (
28
29
"cuelang.org/go/cue/cuecontext"
29
30
"cuelang.org/go/cue/errors"
30
31
"cuelang.org/go/cue/format"
32
+ "cuelang.org/go/cue/token"
31
33
"cuelang.org/go/encoding/json"
32
34
"cuelang.org/go/encoding/jsonschema"
33
35
"cuelang.org/go/encoding/jsonschema/internal/externaltest"
@@ -100,23 +102,32 @@ func runExternalSchemaTests(t *testing.T, filename string, s *externaltest.Schem
100
102
qt .Assert (t , qt .IsNil (err ))
101
103
schemaValue = ctx .CompileBytes (b , cue .Filename ("generated.cue" ))
102
104
if err := schemaValue .Err (); err != nil {
105
+ t .Logf ("extracted schema: %q" , b )
103
106
extractErr = fmt .Errorf ("cannot compile resulting schema: %v" , errors .Details (err , nil ))
104
107
}
105
108
}
106
109
107
110
if extractErr != nil {
111
+ t .Logf ("location: %v" , testdataPos (s ))
112
+ t .Logf ("txtar:\n %s" , schemaFailureTxtar (s ))
108
113
for _ , test := range s .Tests {
109
114
t .Run ("" , func (t * testing.T ) {
110
- testFailed (t , & test .Skip , "could not compile schema" )
115
+ testFailed (t , & test .Skip , test , "could not compile schema" )
111
116
})
112
117
}
113
- testFailed (t , & s .Skip , fmt .Sprintf ("extract error: %v" , extractErr ))
118
+ testFailed (t , & s .Skip , s , fmt .Sprintf ("extract error: %v" , extractErr ))
114
119
return
115
120
}
116
- testSucceeded (t , & s .Skip )
121
+ testSucceeded (t , & s .Skip , s )
117
122
118
123
for _ , test := range s .Tests {
119
124
t .Run (testName (test .Description ), func (t * testing.T ) {
125
+ defer func () {
126
+ if t .Failed () || testing .Verbose () {
127
+ t .Logf ("txtar:\n %s" , testCaseTxtar (s , test ))
128
+ }
129
+ }()
130
+ t .Logf ("location: %v" , testdataPos (test ))
120
131
instAST , err := json .Extract ("instance.json" , test .Data )
121
132
if err != nil {
122
133
t .Fatal (err )
@@ -129,21 +140,60 @@ func runExternalSchemaTests(t *testing.T, filename string, s *externaltest.Schem
129
140
err = instValue .Unify (schemaValue ).Err ()
130
141
if test .Valid {
131
142
if err != nil {
132
- testFailed (t , & test .Skip , errors .Details (err , nil ))
143
+ testFailed (t , & test .Skip , test , errors .Details (err , nil ))
133
144
} else {
134
- testSucceeded (t , & test .Skip )
145
+ testSucceeded (t , & test .Skip , test )
135
146
}
136
147
} else {
137
148
if err == nil {
138
- testFailed (t , & test .Skip , "unexpected success" )
149
+ testFailed (t , & test .Skip , test , "unexpected success" )
139
150
} else {
140
- testSucceeded (t , & test .Skip )
151
+ testSucceeded (t , & test .Skip , test )
141
152
}
142
153
}
143
154
})
144
155
}
145
156
}
146
157
158
+ // testCaseTxtar returns a testscript that runs the given test.
159
+ func testCaseTxtar (s * externaltest.Schema , test * externaltest.Test ) string {
160
+ var buf strings.Builder
161
+ fmt .Fprintf (& buf , "env CUE_EXPERIMENT=evalv3\n " )
162
+ fmt .Fprintf (& buf , "exec cue def json+jsonschema: schema.json\n " )
163
+ if ! test .Valid {
164
+ buf .WriteString ("! " )
165
+ }
166
+ // TODO add $schema when one isn't already present?
167
+ fmt .Fprintf (& buf , "exec cue vet -c instance.json json+jsonschema: schema.json\n " )
168
+ fmt .Fprintf (& buf , "\n " )
169
+ fmt .Fprintf (& buf , "-- schema.json --\n %s\n " , indentJSON (s .Schema ))
170
+ fmt .Fprintf (& buf , "-- instance.json --\n %s\n " , indentJSON (test .Data ))
171
+ return buf .String ()
172
+ }
173
+
174
+ // testCaseTxtar returns a testscript that decodes the given schema.
175
+ func schemaFailureTxtar (s * externaltest.Schema ) string {
176
+ var buf strings.Builder
177
+ fmt .Fprintf (& buf , "env CUE_EXPERIMENT=evalv3\n " )
178
+ fmt .Fprintf (& buf , "exec cue def -o schema.cue json+jsonschema: schema.json\n " )
179
+ fmt .Fprintf (& buf , "exec cat schema.cue\n " )
180
+ fmt .Fprintf (& buf , "exec cue vet schema.cue\n " )
181
+ fmt .Fprintf (& buf , "-- schema.json --\n %s\n " , indentJSON (s .Schema ))
182
+ return buf .String ()
183
+ }
184
+
185
+ func indentJSON (x stdjson.RawMessage ) []byte {
186
+ data , err := stdjson .MarshalIndent (x , "" , "\t " )
187
+ if err != nil {
188
+ panic (err )
189
+ }
190
+ return data
191
+ }
192
+
193
+ type positioner interface {
194
+ Pos () token.Pos
195
+ }
196
+
147
197
// testName returns a test name that doesn't contain any
148
198
// slashes because slashes muck with matching.
149
199
func testName (s string ) string {
@@ -153,7 +203,7 @@ func testName(s string) string {
153
203
// testFailed marks the current test as failed with the
154
204
// given error message, and updates the
155
205
// skip field pointed to by skipField if necessary.
156
- func testFailed (t * testing.T , skipField * string , errStr string ) {
206
+ func testFailed (t * testing.T , skipField * string , p positioner , errStr string ) {
157
207
if cuetest .UpdateGoldenFiles {
158
208
if * skipField == "" && ! allowRegressions () {
159
209
t .Fatalf ("test regression; was succeeding, now failing: %v" , errStr )
@@ -169,7 +219,7 @@ func testFailed(t *testing.T, skipField *string, errStr string) {
169
219
170
220
// testFails marks the current test as succeeded and updates the
171
221
// skip field pointed to by skipField if necessary.
172
- func testSucceeded (t * testing.T , skipField * string ) {
222
+ func testSucceeded (t * testing.T , skipField * string , p positioner ) {
173
223
if cuetest .UpdateGoldenFiles {
174
224
* skipField = ""
175
225
return
@@ -179,6 +229,12 @@ func testSucceeded(t *testing.T, skipField *string) {
179
229
}
180
230
}
181
231
232
+ func testdataPos (p positioner ) token.Position {
233
+ pp := p .Pos ().Position ()
234
+ pp .Filename = path .Join (testDir , pp .Filename )
235
+ return pp
236
+ }
237
+
182
238
func allowRegressions () bool {
183
239
return os .Getenv ("CUE_ALLOW_REGRESSIONS" ) != ""
184
240
}
0 commit comments