1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.bean.swagger;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.bean.swagger.SwaggerBuilder.*;
21 import static org.apache.juneau.commons.utils.CollectionUtils.*;
22 import static org.apache.juneau.junit.bct.BctAssertions.*;
23 import static org.junit.jupiter.api.Assertions.*;
24
25 import java.net.*;
26 import java.util.*;
27
28 import org.apache.juneau.*;
29 import org.apache.juneau.collections.*;
30 import org.junit.jupiter.api.*;
31
32
33
34
35 class SchemaInfo_Test extends TestBase {
36
37 @Nested class A_basicTests extends TestBase {
38
39 private static final BeanTester<SchemaInfo> TESTER =
40 testBean(
41 bean()
42 .setAdditionalProperties(schemaInfo().setType("a"))
43 .setAllOf(set(schemaInfo().setType("b")))
44 .setDefault("c")
45 .setDescription("d")
46 .setDiscriminator("e")
47 .setEnum(set("f"))
48 .setExample("g")
49 .setExclusiveMaximum(true)
50 .setExclusiveMinimum(true)
51 .setExternalDocs(externalDocumentation().setUrl(URI.create("h")))
52 .setFormat("i")
53 .setItems(items().setType("j"))
54 .setMaximum(1)
55 .setMaxItems(2)
56 .setMaxLength(3)
57 .setMaxProperties(4)
58 .setMinimum(5)
59 .setMinItems(6)
60 .setMinLength(7)
61 .setMinProperties(8)
62 .setMultipleOf(9)
63 .setPattern("k")
64 .setProperties(map("x1", schemaInfo().setType("x2")))
65 .setReadOnly(true)
66 .setRef("l")
67 .setRequired(true)
68 .setRequiredProperties("m")
69 .setTitle("n")
70 .setType("o")
71 .setUniqueItems(true)
72 .setXml(xml().setName("p"))
73 )
74 .props("additionalProperties{type},allOf{#{type}},default,description,discriminator,enum,example,exclusiveMaximum,exclusiveMinimum,externalDocs{url},format,items{type},maximum,maxItems,maxLength,maxProperties,minimum,minItems,minLength,minProperties,multipleOf,pattern,properties{x1{type}},readOnly,ref,required,requiredProperties,title,type,uniqueItems,xml{name}")
75 .vals("{a},{[{b}]},c,d,e,[f],g,true,true,{h},i,{j},1,2,3,4,5,6,7,8,9,k,{{x2}},true,l,true,[m],n,o,true,{p}")
76 .json("{'$ref':'l',additionalProperties:{type:'a'},allOf:[{type:'b'}],'default':'c',description:'d',discriminator:'e','enum':['f'],example:'g',exclusiveMaximum:true,exclusiveMinimum:true,externalDocs:{url:'h'},format:'i',items:{type:'j'},maxItems:2,maxLength:3,maxProperties:4,maximum:1,minItems:6,minLength:7,minProperties:8,minimum:5,multipleOf:9,pattern:'k',properties:{x1:{type:'x2'}},readOnly:true,required:true,requiredProperties:['m'],title:'n',type:'o',uniqueItems:true,xml:{name:'p'}}")
77 .string("{'$ref':'l','additionalProperties':{'type':'a'},'allOf':[{'type':'b'}],'default':'c','description':'d','discriminator':'e','enum':['f'],'example':'g','exclusiveMaximum':true,'exclusiveMinimum':true,'externalDocs':{'url':'h'},'format':'i','items':{'type':'j'},'maxItems':2,'maxLength':3,'maxProperties':4,'maximum':1,'minItems':6,'minLength':7,'minProperties':8,'minimum':5,'multipleOf':9,'pattern':'k','properties':{'x1':{'type':'x2'}},'readOnly':true,'required':true,'requiredProperties':['m'],'title':'n','type':'o','uniqueItems':true,'xml':{'name':'p'}}".replace('\'', '"'))
78 ;
79
80 @Test void a01_gettersAndSetters() {
81 TESTER.assertGettersAndSetters();
82 }
83
84 @Test void a02_copy() {
85 TESTER.assertCopy();
86 }
87
88 @Test void a03_toJson() {
89 TESTER.assertToJson();
90 }
91
92 @Test void a04_fromJson() {
93 TESTER.assertFromJson();
94 }
95
96 @Test void a05_roundTrip() {
97 TESTER.assertRoundTrip();
98 }
99
100 @Test void a06_toString() {
101 TESTER.assertToString();
102 }
103
104 @Test void a07_keySet() {
105 assertList(TESTER.bean().keySet(), "$ref", "additionalProperties", "allOf", "default", "description", "discriminator", "enum", "example", "exclusiveMaximum", "exclusiveMinimum", "externalDocs", "format", "items", "maxItems", "maxLength", "maxProperties", "maximum", "minItems", "minLength", "minProperties", "minimum", "multipleOf", "pattern", "properties", "readOnly", "required", "requiredProperties", "title", "type", "uniqueItems", "xml");
106 }
107
108 @Test void a08_addMethods() {
109 var x = bean()
110 .addEnum("a1")
111 .setAllOf(schemaInfo().setTitle("a1"))
112 .addAllOf(schemaInfo().setTitle("a2"))
113 ;
114
115 assertNotNull(x);
116 assertNotNull(x.getEnum());
117 assertNotNull(x.getAllOf());
118 }
119
120 @Test void a09_asMap() {
121 assertBean(
122 bean()
123 .setDescription("a")
124 .setTitle("b")
125 .setType("c")
126 .set("x1", "x1a")
127 .asMap(),
128 "description,title,type,x1",
129 "a,b,c,x1a"
130 );
131 }
132
133 @Test void a10_extraKeys() {
134 var x = bean().set("x1", "x1a").set("x2", "x2a");
135 assertList(x.extraKeys(), "x1", "x2");
136 assertEmpty(bean().extraKeys());
137 }
138
139 @Test void a11_strictMode() {
140 assertThrows(RuntimeException.class, () -> bean().strict().set("foo", "bar"));
141 assertDoesNotThrow(() -> bean().set("foo", "bar"));
142
143 assertFalse(bean().isStrict());
144 assertTrue(bean().strict().isStrict());
145 assertFalse(bean().strict(false).isStrict());
146 }
147
148 @Test void a12_collectionSetters() {
149 var x = bean()
150 .setAllOf(l(schemaInfo().setType("a"), schemaInfo().setType("b")))
151 .setEnum(l("c", "d"))
152 .setRequiredProperties(l("e", "f"));
153
154 assertBean(x,
155 "allOf{#{type}},enum,requiredProperties",
156 "{[{a},{b}]},[c,d],[e,f]"
157 );
158 }
159
160 @Test void a13_varargAdders() {
161 var x = bean()
162 .addAllOf(schemaInfo().setType("a1"))
163 .addAllOf(schemaInfo().setType("a2"))
164 .addEnum("b1")
165 .addEnum("b2")
166 .addRequiredProperties("c1")
167 .addRequiredProperties("c2");
168
169 assertBean(x,
170 "allOf{#{type}},enum,requiredProperties",
171 "{[{a1},{a2}]},[b1,b2],[c1,c2]"
172 );
173 }
174
175 @Test void a14_collectionAdders() {
176
177
178
179 var x = bean()
180 .addAllOf(l(schemaInfo().setType("a1")))
181 .addAllOf(l(schemaInfo().setType("a2")))
182 .addEnum(l("b1"))
183 .addEnum(l("b2"))
184 .addRequiredProperties(l("c1"))
185 .addRequiredProperties(l("c2"));
186
187 assertBean(x,
188 "allOf{#{type}},enum,requiredProperties",
189 "{[{a1},{a2}]},[b1,b2],[c1,c2]"
190 );
191 }
192 }
193
194 @Nested class B_emptyTests extends TestBase {
195
196 private static final BeanTester<SchemaInfo> TESTER =
197 testBean(bean())
198 .props("description,title,type,format,items,collectionFormat,default,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,enum,multipleOf,discriminator,readOnly,xml,externalDocs,example,required,properties,additionalProperties,allOf")
199 .vals("<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>")
200 .json("{}")
201 .string("{}")
202 ;
203
204 @Test void b01_gettersAndSetters() {
205 TESTER.assertGettersAndSetters();
206 }
207
208 @Test void b02_copy() {
209 TESTER.assertCopy();
210 }
211
212 @Test void b03_toJson() {
213 TESTER.assertToJson();
214 }
215
216 @Test void b04_fromJson() {
217 TESTER.assertFromJson();
218 }
219
220 @Test void b05_roundTrip() {
221 TESTER.assertRoundTrip();
222 }
223
224 @Test void b06_toString() {
225 TESTER.assertToString();
226 }
227
228 @Test void b07_keySet() {
229 assertEmpty(TESTER.bean().keySet());
230 }
231
232 @Test void b08_nullParameters() {
233 var x = bean();
234 assertThrows(IllegalArgumentException.class, () -> x.get(null, String.class));
235 assertThrows(IllegalArgumentException.class, () -> x.set(null, "value"));
236 }
237 }
238
239 @Nested class C_extraProperties extends TestBase {
240
241 private static final BeanTester<SchemaInfo> TESTER =
242 testBean(
243 bean()
244 .set("additionalProperties", schemaInfo().setType("a"))
245 .set("allOf", set(schemaInfo().setType("b")))
246 .set("default", "c")
247 .set("description", "d")
248 .set("discriminator", "e")
249 .set("enum", set("f"))
250 .set("example", "g")
251 .set("exclusiveMaximum", true)
252 .set("exclusiveMinimum", true)
253 .set("externalDocs", externalDocumentation().setUrl(URI.create("h")))
254 .set("format", "i")
255 .set("items", items().setType("j"))
256 .set("maximum", 1)
257 .set("maxItems", 2)
258 .set("maxLength", 3)
259 .set("maxProperties", 4)
260 .set("minimum", 5)
261 .set("minItems", 6)
262 .set("minLength", 7)
263 .set("minProperties", 8)
264 .set("multipleOf", 9)
265 .set("pattern", "k")
266 .set("properties", m("x1", schemaInfo().setType("x2")))
267 .set("readOnly", true)
268 .set("$ref", "l")
269 .set("required", true)
270 .set("requiredProperties", set("m"))
271 .set("title", "n")
272 .set("type", "o")
273 .set("uniqueItems", true)
274 .set("xml", xml().setName("p"))
275 .set("x1", "x1a")
276 .set("x2", null)
277 )
278 .props("additionalProperties{type},allOf,default,description,discriminator,enum,example,exclusiveMaximum,exclusiveMinimum,externalDocs{url},format,items{type},maximum,maxItems,maxLength,maxProperties,minimum,minItems,minLength,minProperties,multipleOf,pattern,properties{x1{type}},readOnly,ref,required,requiredProperties,title,type,uniqueItems,xml{name},x1,x2")
279 .vals("{a},[{\"type\":\"b\"}],c,d,e,[f],g,true,true,{h},i,{j},1,2,3,4,5,6,7,8,9,k,{{x2}},true,l,true,[m],n,o,true,{p},x1a,<null>")
280 .json("{'$ref':'l',additionalProperties:{type:'a'},allOf:[{type:'b'}],'default':'c',description:'d',discriminator:'e','enum':['f'],example:'g',exclusiveMaximum:true,exclusiveMinimum:true,externalDocs:{url:'h'},format:'i',items:{type:'j'},maxItems:2,maxLength:3,maxProperties:4,maximum:1,minItems:6,minLength:7,minProperties:8,minimum:5,multipleOf:9,pattern:'k',properties:{x1:{type:'x2'}},readOnly:true,required:true,requiredProperties:['m'],title:'n',type:'o',uniqueItems:true,x1:'x1a',xml:{name:'p'}}")
281 .string("{'$ref':'l','additionalProperties':{'type':'a'},'allOf':[{'type':'b'}],'default':'c','description':'d','discriminator':'e','enum':['f'],'example':'g','exclusiveMaximum':true,'exclusiveMinimum':true,'externalDocs':{'url':'h'},'format':'i','items':{'type':'j'},'maxItems':2,'maxLength':3,'maxProperties':4,'maximum':1,'minItems':6,'minLength':7,'minProperties':8,'minimum':5,'multipleOf':9,'pattern':'k','properties':{'x1':{'type':'x2'}},'readOnly':true,'required':true,'requiredProperties':['m'],'title':'n','type':'o','uniqueItems':true,'x1':'x1a','xml':{'name':'p'}}".replace('\'', '"'))
282 ;
283
284 @Test void c01_gettersAndSetters() {
285 TESTER.assertGettersAndSetters();
286 }
287
288 @Test void c02_copy() {
289 TESTER.assertCopy();
290 }
291
292 @Test void c03_toJson() {
293 TESTER.assertToJson();
294 }
295
296 @Test void c04_fromJson() {
297 TESTER.assertFromJson();
298 }
299
300 @Test void c05_roundTrip() {
301 TESTER.assertRoundTrip();
302 }
303
304 @Test void c06_toString() {
305 TESTER.assertToString();
306 }
307
308 @Test void c07_keySet() {
309 assertList(TESTER.bean().keySet(), "$ref", "additionalProperties", "allOf", "default", "description", "discriminator", "enum", "example", "exclusiveMaximum", "exclusiveMinimum", "externalDocs", "format", "items", "maxItems", "maxLength", "maxProperties", "maximum", "minItems", "minLength", "minProperties", "minimum", "multipleOf", "pattern", "properties", "readOnly", "required", "requiredProperties", "title", "type", "uniqueItems", "xml", "x1", "x2");
310 }
311
312 @Test void c08_get() {
313 assertMapped(
314 TESTER.bean(), (obj,prop) -> obj.get(prop, Object.class),
315 "additionalProperties{type},allOf{#{type}},default,description,discriminator,enum,example,exclusiveMaximum,exclusiveMinimum,externalDocs{url},format,items{type},maximum,maxItems,maxLength,maxProperties,minimum,minItems,minLength,minProperties,multipleOf,pattern,properties{x1{type}},readOnly,$ref,required,requiredProperties,title,type,uniqueItems,xml{name},x1,x2",
316 "{a},{[{b}]},c,d,e,[f],g,true,true,{h},i,{j},1,2,3,4,5,6,7,8,9,k,{{x2}},true,l,true,[m],n,o,true,{p},x1a,<null>"
317 );
318 }
319
320 @Test void c09_getTypes() {
321 assertMapped(
322 TESTER.bean(), (obj,prop) -> cns(obj.get(prop, Object.class)),
323 "additionalProperties,allOf,default,description,discriminator,enum,example,exclusiveMaximum,exclusiveMinimum,externalDocs,format,items,maximum,maxItems,maxLength,maxProperties,minimum,minItems,minLength,minProperties,multipleOf,pattern,properties,readOnly,$ref,required,requiredProperties,title,type,uniqueItems,xml,x1,x2",
324 "SchemaInfo,LinkedHashSet,String,String,String,LinkedHashSet,String,Boolean,Boolean,ExternalDocumentation,String,Items,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,Integer,String,LinkedHashMap,Boolean,String,Boolean,LinkedHashSet,String,String,Boolean,Xml,String,<null>"
325 );
326 }
327
328 @Test void c10_nullPropertyValue() {
329 assertThrows(IllegalArgumentException.class, ()->bean().get(null));
330 assertThrows(IllegalArgumentException.class, ()->bean().get(null, String.class));
331 assertThrows(IllegalArgumentException.class, ()->bean().set(null, "a"));
332 }
333 }
334
335 @Nested class D_refs extends TestBase {
336
337 @Test void d01_resolveRefs_basic() {
338 var swagger = swagger()
339 .addDefinition("Pet", JsonMap.of("type", "object", "title", "Pet"))
340 .addDefinition("Pets", JsonMap.of("type", "array", "items", JsonMap.of("$ref", "#/definitions/Pet")));
341
342 assertBean(
343 schemaInfo().setRef("#/definitions/Pet").resolveRefs(swagger, new ArrayDeque<>(), 10),
344 "type,title",
345 "object,Pet"
346 );
347 }
348
349 @Test void d02_resolveRefs_nested() {
350 var swagger = swagger()
351 .addDefinition("Pet", JsonMap.of("type", "object", "title", "Pet"))
352 .addDefinition("Pets", JsonMap.of("type", "array", "items", JsonMap.of("$ref", "#/definitions/Pet")));
353
354 assertBean(
355 schemaInfo().setRef("#/definitions/Pets").resolveRefs(swagger, new ArrayDeque<>(), 10),
356 "type,items{type,title}",
357 "array,{object,Pet}"
358 );
359 }
360
361 @Test void d03_resolveRefs_maxDepth() {
362 var swagger = swagger()
363 .addDefinition("Pet", JsonMap.of("type", "object", "title", "Pet"))
364 .addDefinition("Pets", JsonMap.of("type", "array", "items", JsonMap.of("$ref", "#/definitions/Pet")));
365
366 assertBean(
367 schemaInfo().setRef("#/definitions/Pets").resolveRefs(swagger, new ArrayDeque<>(), 1),
368 "type,items{ref}",
369 "array,{#/definitions/Pet}"
370 );
371 }
372
373 @Test void d04_resolveRefs_circular() {
374 var swagger = swagger()
375 .addDefinition("A", JsonMap.of("type", "object", "title", "A", "properties", JsonMap.of("b", JsonMap.of("$ref", "#/definitions/B"))))
376 .addDefinition("B", JsonMap.of("type", "object", "title", "B", "properties", JsonMap.of("a", JsonMap.of("$ref", "#/definitions/A"))));
377
378 assertBean(
379 schemaInfo().setRef("#/definitions/A").resolveRefs(swagger, new ArrayDeque<>(), 10),
380 "type,title,properties{b{type,title,properties{a{ref}}}}",
381 "object,A,{{object,B,{{#/definitions/A}}}}"
382 );
383 }
384
385 @Test void d05_resolveRefs_properties() {
386 var swagger = swagger()
387 .addDefinition("Pet", JsonMap.of("type", "object", "title", "Pet"));
388
389 assertBean(
390 schemaInfo().setType("object").addProperty("pet", schemaInfo().setRef("#/definitions/Pet")).resolveRefs(swagger, new ArrayDeque<>(), 10),
391 "type,properties{pet{type,title}}",
392 "object,{{object,Pet}}"
393 );
394 }
395
396 @Test void d06_resolveRefs_additionalProperties() {
397 var swagger = swagger()
398 .addDefinition("Pet", JsonMap.of("type", "object", "title", "Pet"));
399
400 assertBean(
401 schemaInfo().setType("object").setAdditionalProperties(schemaInfo().setRef("#/definitions/Pet")).resolveRefs(swagger, new ArrayDeque<>(), 10),
402 "type,additionalProperties{type,title}",
403 "object,{object,Pet}"
404 );
405 }
406 }
407
408
409
410
411
412 private static SchemaInfo bean() {
413 return schemaInfo();
414 }
415 }