1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package schema_test
16
17 import (
18 "bytes"
19 "errors"
20 "fmt"
21 "io"
22 "net/url"
23 "os"
24 "path/filepath"
25 "reflect"
26 "strings"
27 "testing"
28
29 "github.com/opencontainers/image-spec/schema"
30 "github.com/russross/blackfriday"
31 )
32
33 var (
34 errFormatInvalid = errors.New("format: invalid")
35 )
36
37 func TestValidateDescriptor(t *testing.T) {
38 validate(t, "../descriptor.md")
39 }
40
41 func TestValidateManifest(t *testing.T) {
42 validate(t, "../manifest.md")
43 }
44
45 func TestValidateImageIndex(t *testing.T) {
46 validate(t, "../image-index.md")
47 }
48
49 func TestValidateImageLayout(t *testing.T) {
50 validate(t, "../image-layout.md")
51 }
52
53 func TestValidateConfig(t *testing.T) {
54 validate(t, "../config.md")
55 }
56
57 func TestSchemaFS(t *testing.T) {
58 expectedSchemaFileNames, err := filepath.Glob("*.json")
59 if err != nil {
60 t.Error(err)
61 }
62
63 dir, err := schema.FileSystem().Open("/")
64 if err != nil {
65 t.Fatal(err)
66 }
67
68 files, err := dir.Readdir(-1)
69 if err != nil {
70 t.Fatal(err)
71 }
72 var schemaFileNames []string
73 for _, f := range files {
74 schemaFileNames = append(schemaFileNames, f.Name())
75 }
76
77 if !reflect.DeepEqual(schemaFileNames, expectedSchemaFileNames) {
78 t.Fatalf("got %v, expected %v", schemaFileNames, expectedSchemaFileNames)
79 }
80 }
81
82
83 func validate(t *testing.T, name string) {
84 m, err := os.Open(name)
85 if err != nil {
86 t.Fatal(err)
87 }
88 defer m.Close()
89
90 examples, err := extractExamples(m)
91 if err != nil {
92 t.Fatal(err)
93 }
94
95 for _, example := range examples {
96 if errors.Is(example.Err, errFormatInvalid) && example.Mediatype == "" {
97 continue
98 }
99
100 if example.Err != nil {
101 printFields(t, "error", example.Mediatype, example.Title, example.Err)
102 t.Error(err)
103 continue
104 }
105
106 err = schema.Validator(example.Mediatype).Validate(strings.NewReader(example.Body))
107 if err == nil {
108 printFields(t, "ok", example.Mediatype, example.Title)
109 t.Log(example.Body, "---")
110 continue
111 }
112
113 var errs []error
114 var verr schema.ValidationError
115 if errors.As(err, &verr) {
116 errs = verr.Errs
117 } else {
118 printFields(t, "error", example.Mediatype, example.Title, err)
119 t.Error(err)
120 t.Log(example.Body, "---")
121 continue
122 }
123
124 for _, err := range errs {
125 printFields(t, "invalid", example.Mediatype, example.Title)
126 t.Error(err)
127 fmt.Println(example.Body, "---")
128 continue
129 }
130 }
131 }
132
133
134 type renderer struct {
135 blackfriday.Renderer
136 fn func(text []byte, lang string)
137 }
138
139 func (r *renderer) BlockCode(out *bytes.Buffer, text []byte, lang string) {
140 r.fn(text, lang)
141 r.Renderer.BlockCode(out, text, lang)
142 }
143
144 type example struct {
145 Lang string
146 Title string
147 Mediatype string
148 Body string
149 Err error
150
151
152
153 }
154
155
156
157
158
159
160
161
162
163
164 func parseExample(lang, body string) (e example) {
165 e.Lang = lang
166 e.Body = body
167
168 parts := strings.SplitN(lang, ",", 2)
169 if len(parts) < 2 {
170 e.Err = errFormatInvalid
171 return
172 }
173
174 m, err := url.ParseQuery(parts[1])
175 if err != nil {
176 e.Err = err
177 return
178 }
179
180 e.Mediatype = m.Get("mediatype")
181 e.Title = m.Get("title")
182 return
183 }
184
185 func extractExamples(rd io.Reader) ([]example, error) {
186 p, err := io.ReadAll(rd)
187 if err != nil {
188 return nil, err
189 }
190
191 var examples []example
192 renderer := &renderer{
193 Renderer: blackfriday.HtmlRenderer(0, "test test", ""),
194 fn: func(text []byte, lang string) {
195 examples = append(examples, parseExample(lang, string(text)))
196 },
197 }
198
199
200
201
202
203 blackfriday.MarkdownOptions(p, renderer, blackfriday.Options{
204 Extensions: blackfriday.EXTENSION_FENCED_CODE,
205 })
206
207 return examples, nil
208 }
209
210
211 func printFields(t *testing.T, vs ...interface{}) {
212 var ss []string
213 for _, f := range vs {
214 ss = append(ss, fmt.Sprint(f))
215 }
216 t.Log(strings.Join(ss, "\t"))
217 }
218
View as plain text