1
2
3
4
5 package disco
6
7 import (
8 "os"
9 "reflect"
10 "strings"
11 "testing"
12 )
13
14 var stringSchema = &Schema{
15 Type: "string",
16 Kind: SimpleKind,
17 }
18
19 func TestDocument(t *testing.T) {
20 bytes, err := os.ReadFile("testdata/test-api.json")
21 if err != nil {
22 t.Fatal(err)
23 }
24 got, err := NewDocument(bytes)
25 if err != nil {
26 t.Fatal(err)
27 }
28 want := &Document{
29 ID: "storage:v1",
30 Name: "storage",
31 Version: "v1",
32 Title: "Cloud Storage JSON API",
33 RootURL: "https://www.googleapis.com/",
34 ServicePath: "storage/v1/",
35 BasePath: "/storage/v1/",
36 DocumentationLink: "https://developers.google.com/storage/docs/json_api/",
37 Auth: Auth{
38 OAuth2Scopes: []Scope{
39 {"https://www.googleapis.com/auth/cloud-platform",
40 "View and manage your data across Google Cloud Platform services"},
41 {"https://www.googleapis.com/auth/cloud-platform.read-only",
42 "View your data across Google Cloud Platform services"},
43 {"https://www.googleapis.com/auth/devstorage.full_control",
44 "Manage your data and permissions in Google Cloud Storage"},
45 {"https://www.googleapis.com/auth/devstorage.read_only",
46 "View your data in Google Cloud Storage"},
47 {"https://www.googleapis.com/auth/devstorage.read_write",
48 "Manage your data in Google Cloud Storage"},
49 },
50 },
51 Features: []string{"dataWrapper"},
52 Schemas: map[string]*Schema{
53 "Bucket": {
54 Name: "Bucket",
55 ID: "Bucket",
56 Type: "object",
57 Description: "A bucket.",
58 Kind: StructKind,
59 Properties: []*Property{
60 {"cors", &Schema{
61 Type: "array",
62 Kind: ArrayKind,
63 ItemSchema: &Schema{
64 Type: "object",
65 Kind: StructKind,
66 Properties: []*Property{
67 {"maxAgeSeconds", &Schema{
68 Type: "integer",
69 Format: "int32",
70 Kind: SimpleKind,
71 }},
72 {"method", &Schema{
73 Type: "array",
74 Kind: ArrayKind,
75 ItemSchema: stringSchema,
76 }},
77 },
78 },
79 }},
80 {"id", stringSchema},
81 {"kind", &Schema{
82 Type: "string",
83 Kind: SimpleKind,
84 Default: "storage#bucket",
85 }},
86 },
87 },
88 "Buckets": {
89 ID: "Buckets",
90 Name: "Buckets",
91 Type: "object",
92 Kind: StructKind,
93 Properties: []*Property{
94 {"items", &Schema{
95 Type: "array",
96 Kind: ArrayKind,
97 ItemSchema: &Schema{
98 Kind: ReferenceKind,
99 Ref: "Bucket",
100 RefSchema: nil,
101 },
102 }},
103 },
104 },
105 "VariantExample": {
106 ID: "VariantExample",
107 Name: "VariantExample",
108 Type: "object",
109 Kind: StructKind,
110 Variant: &Variant{
111 Discriminant: "type",
112 Map: []*VariantMapItem{
113 {TypeValue: "Bucket", Ref: "Bucket"},
114 {TypeValue: "Buckets", Ref: "Buckets"},
115 },
116 },
117 },
118 },
119 Methods: MethodList{
120 &Method{
121 Name: "getCertForOpenIdConnect",
122 ID: "oauth2.getCertForOpenIdConnect",
123 Path: "oauth2/v1/certs",
124 HTTPMethod: "GET",
125 Response: &Schema{Ref: "Bucket", Kind: ReferenceKind},
126 },
127 },
128 Resources: ResourceList{
129 &Resource{
130 Name: "buckets",
131 FullName: ".buckets",
132 Methods: MethodList{
133 &Method{
134 Name: "get",
135 ID: "storage.buckets.get",
136 Path: "b/{bucket}",
137 HTTPMethod: "GET",
138 Description: "d",
139 Parameters: ParameterList{
140 &Parameter{
141 Name: "bucket",
142 Schema: Schema{
143 Type: "string",
144 },
145 Required: true,
146 Location: "path",
147 },
148 &Parameter{
149 Name: "ifMetagenerationMatch",
150 Schema: Schema{
151 Type: "string",
152 Format: "int64",
153 },
154 Location: "query",
155 },
156 &Parameter{
157 Name: "projection",
158 Schema: Schema{
159 Type: "string",
160 Enums: []string{"full", "noAcl"},
161 EnumDescriptions: []string{
162 "Include all properties.",
163 "Omit owner, acl and defaultObjectAcl properties.",
164 },
165 },
166 Location: "query",
167 },
168 },
169 ParameterOrder: []string{"bucket"},
170 Response: &Schema{Ref: "Bucket", Kind: ReferenceKind},
171 Scopes: []string{
172 "https://www.googleapis.com/auth/cloud-platform",
173 "https://www.googleapis.com/auth/cloud-platform.read-only",
174 "https://www.googleapis.com/auth/devstorage.full_control",
175 "https://www.googleapis.com/auth/devstorage.read_only",
176 "https://www.googleapis.com/auth/devstorage.read_write",
177 },
178 SupportsMediaDownload: true,
179 MediaUpload: &MediaUpload{
180 Accept: []string{"application/octet-stream"},
181 MaxSize: "1GB",
182 Protocols: map[string]Protocol{
183 "simple": {
184 Multipart: true,
185 Path: "/upload/customDataSources/{customDataSourceId}/uploads",
186 },
187 "resumable": {
188 Multipart: true,
189 Path: "/resumable/upload/customDataSources/{customDataSourceId}/uploads",
190 },
191 },
192 },
193 },
194 },
195 },
196 },
197 }
198
199 bucket := want.Schemas["Bucket"]
200 want.Schemas["Buckets"].Properties[0].Schema.ItemSchema.RefSchema = bucket
201 want.Methods[0].Response.RefSchema = bucket
202 want.Resources[0].Methods[0].Response.RefSchema = bucket
203 for k, gs := range got.Schemas {
204 ws := want.Schemas[k]
205 if !reflect.DeepEqual(gs, ws) {
206 t.Fatalf("schema %s: got\n%+v\nwant\n%+v", k, gs, ws)
207 }
208 }
209 if len(got.Schemas) != len(want.Schemas) {
210 t.Errorf("want %d schemas, got %d", len(got.Schemas), len(want.Schemas))
211 }
212 compareMethodLists(t, got.Methods, want.Methods)
213 for i, gr := range got.Resources {
214 wr := want.Resources[i]
215 compareMethodLists(t, gr.Methods, wr.Methods)
216 if !reflect.DeepEqual(gr, wr) {
217 t.Fatalf("resource %d: got\n%+v\nwant\n%+v", i, gr, wr)
218 }
219 }
220 if len(got.Resources) != len(want.Resources) {
221 t.Errorf("want %d resources, got %d", len(got.Resources), len(want.Resources))
222 }
223 if !reflect.DeepEqual(got, want) {
224 t.Errorf("got\n%+v\nwant\n%+v", got, want)
225 }
226 }
227
228 func compareMethodLists(t *testing.T, got, want MethodList) {
229 if len(got) != len(want) {
230 t.Fatalf("got %d methods, want %d", len(got), len(want))
231 }
232 for i, gm := range got {
233 gm.JSONMap = nil
234 wm := want[i]
235 if !reflect.DeepEqual(gm, wm) {
236 t.Errorf("#%d: got\n%+v\nwant\n%+v", i, gm, wm)
237 }
238 }
239 }
240
241 func TestDocumentErrors(t *testing.T) {
242 for _, in := range []string{
243 `{"name": "X"`,
244 `{"id": 3}`,
245 `{"auth": "oauth2": { "scopes": "string" }}`,
246 } {
247 _, err := NewDocument([]byte(in))
248 if err == nil {
249 t.Errorf("%s: got nil, want error", in)
250 }
251 }
252 }
253
254 func TestSchemaErrors(t *testing.T) {
255 for _, s := range []*Schema{
256 {Type: "array"},
257 {Type: "string", ItemSchema: &Schema{}},
258 {Type: "moose"},
259 {Ref: "Thing"},
260 } {
261 if err := s.init(nil); err == nil {
262 t.Errorf("%+v: got nil, want error", s)
263 }
264 }
265 }
266
267 func TestErrorDoc(t *testing.T) {
268 bytes, err := os.ReadFile("testdata/error.json")
269 if err != nil {
270 t.Fatal(err)
271 }
272 if _, err := NewDocument(bytes); err == nil {
273 t.Error("got nil, want error")
274 } else if !strings.Contains(err.Error(), "404") {
275 t.Errorf("got %v, want 404", err)
276 }
277 }
278
View as plain text