1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.httppart;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.commons.utils.CollectionUtils.*;
21 import static org.apache.juneau.commons.utils.StringUtils.*;
22 import static org.apache.juneau.junit.bct.BctAssertions.*;
23 import static org.junit.jupiter.api.Assertions.*;
24
25 import java.util.*;
26
27 import org.apache.juneau.*;
28 import org.apache.juneau.annotation.*;
29 import org.apache.juneau.commons.reflect.*;
30 import org.apache.juneau.http.annotation.*;
31 import org.junit.jupiter.api.*;
32
33 class HttpPartSchema_Path_Test extends TestBase {
34
35
36
37
38 @Test void a01_basic() {
39 assertDoesNotThrow(()->HttpPartSchema.create().build());
40 }
41
42
43
44
45
46 @Path("x")
47 public static class A01 {}
48
49 @Test void a01_value() {
50 var s = HttpPartSchema.create().applyAll(Path.class, A01.class).build();
51 assertEquals("x", s.getName());
52 }
53
54 @Path("x")
55 @Schema(
56 t="number",
57 f="int32",
58 cf="csv",
59 max="1",
60 min="2",
61 mo="3",
62 p="4",
63 maxl=1,
64 minl=2,
65 emax=true,
66 emin=true,
67 d={"b1","b2"},
68 items=@Items($ref="d1"),
69 e="e1,e2,e3"
70 )
71 public static class A02 {}
72
73 @Test void a02_basic_onClass() {
74 assertBean(
75 HttpPartSchema.create().applyAll(Path.class, A02.class).noValidate().build(),
76 "name,type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,exclusiveMaximum,exclusiveMinimum,enum",
77 "x,NUMBER,INT32,CSV,1,2,3,4,1,2,true,true,[e1,e2,e3]"
78 );
79 }
80
81 public static class A03 {
82 public void a(
83 @Path("x")
84 @Schema(
85 t="number",
86 f="int32",
87 cf="csv",
88 max="1",
89 min="2",
90 mo="3",
91 p="4",
92 maxl=1,
93 minl=2,
94 emax=true,
95 emin=true,
96 d={"b1","b2"},
97 items=@Items($ref="d1"),
98 e="e1,e2,e3"
99 )
100 String x
101 ) {
102
103 }
104 }
105
106 @Test void a03_basic_onParameter() throws Exception {
107 var mpi = MethodInfo.of(A03.class.getMethod("a", String.class)).getParameter(0);
108 assertBean(
109 HttpPartSchema.create().applyAll(Path.class, mpi).noValidate().build(),
110 "name,type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,exclusiveMaximum,exclusiveMinimum,enum",
111 "x,NUMBER,INT32,CSV,1,2,3,4,1,2,true,true,[e1,e2,e3]"
112 );
113 }
114
115 public static class A04 {
116 public void a(
117 @Path("y")
118 @Schema(
119 t="integer",
120 f="int64",
121 cf="ssv",
122 max="5",
123 min="6",
124 mo="7",
125 p="8",
126 maxl=5,
127 minl=6,
128 emax=false,
129 emin=false,
130 d={"b3","b3"},
131 items=@Items($ref="d2"),
132 e="e4,e5,e6"
133 )
134 A01 x
135 ) {
136
137 }
138 }
139
140 @Test void a04_basic_onParameterAndClass() throws Exception {
141 var mpi = MethodInfo.of(A04.class.getMethod("a", A01.class)).getParameter(0);
142 assertBean(
143 HttpPartSchema.create().applyAll(Path.class, mpi).noValidate().build(),
144 "name,type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,exclusiveMaximum,exclusiveMinimum,enum",
145 "y,INTEGER,INT64,SSV,5,6,7,8,5,6,false,false,[e4,e5,e6]"
146 );
147 }
148
149 @Path("x")
150 @Schema(
151 items=@Items(
152 t="number",
153 f="int32",
154 cf="csv",
155 max="1",
156 min="2",
157 mo="3",
158 p="4",
159 maxl=1,
160 minl=2,
161 maxi=3,
162 mini=4,
163 emax=true,
164 emin=true,
165 ui=true,
166 df={"c1","c2"},
167 e="e1,e2",
168 items=@SubItems(
169 t="integer",
170 f="int64",
171 cf="ssv",
172 max="5",
173 min="6",
174 mo="7",
175 p="8",
176 maxl=5,
177 minl=6,
178 maxi=7,
179 mini=8,
180 emax=false,
181 emin=false,
182 ui=false,
183 df={"c3","c4"},
184 e="e3,e4",
185 items={
186 "type:'string',",
187 "format:'float',",
188 "collectionFormat:'tsv',",
189 "maximum:'9',",
190 "minimum:'10',",
191 "multipleOf:'11',",
192 "pattern:'12',",
193 "maxLength:9,",
194 "minLength:10,",
195 "maxItems:11,",
196 "minItems:12,",
197 "exclusiveMaximum:true,",
198 "exclusiveMinimum:true,",
199 "uniqueItems:true,",
200 "default:'c5\\nc6',",
201 "enum:['e5','e6'],",
202 "items:{",
203 "type:'array',",
204 "format:'double',",
205 "collectionFormat:'pipes',",
206 "maximum:'13',",
207 "minimum:'14',",
208 "multipleOf:'15',",
209 "pattern:'16',",
210 "maxLength:13,",
211 "minLength:14,",
212 "maxItems:15,",
213 "minItems:16,",
214 "exclusiveMaximum:false,",
215 "exclusiveMinimum:false,",
216 "uniqueItems:false,",
217 "default:'c7\\nc8',",
218 "enum:['e7','e8']",
219 "}"
220 }
221 )
222 )
223 )
224 public static class A05 {}
225
226 @Test void a05_basic_nestedItems_onClass() {
227 var s = HttpPartSchema.create().applyAll(Path.class, A05.class).noValidate().build();
228 assertEquals("x", s.getName());
229
230 var items = s.getItems();
231 assertBean(
232 items,
233 "type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,maxItems,minItems,exclusiveMaximum,exclusiveMinimum,uniqueItems,enum,default",
234 "NUMBER,INT32,CSV,1,2,3,4,1,2,3,4,true,true,true,[e1,e2],c1\nc2"
235 );
236
237 items = items.getItems();
238 assertBean(
239 items,
240 "type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,maxItems,minItems,exclusiveMaximum,exclusiveMinimum,uniqueItems,enum,default",
241 "INTEGER,INT64,SSV,5,6,7,8,5,6,7,8,false,false,false,[e3,e4],c3\nc4"
242 );
243
244 items = items.getItems();
245 assertBean(
246 items,
247 "type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,maxItems,minItems,exclusiveMaximum,exclusiveMinimum,uniqueItems,enum,default",
248 "STRING,FLOAT,TSV,9,10,11,12,9,10,11,12,true,true,true,[e5,e6],c5\nc6"
249 );
250
251 items = items.getItems();
252 assertBean(
253 items,
254 "type,format,collectionFormat,maximum,minimum,multipleOf,pattern,maxLength,minLength,maxItems,minItems,exclusiveMaximum,exclusiveMinimum,uniqueItems,enum,default",
255 "ARRAY,DOUBLE,PIPES,13,14,15,16,13,14,15,16,false,false,false,[e7,e8],c7\nc8"
256 );
257 }
258
259
260
261
262
263 @Path @Schema(p="x.*")
264 public static class B02a {}
265
266 @Test void b02a_pattern() throws Exception {
267 var s = HttpPartSchema.create().applyAll(Path.class, B02a.class).build();
268 s.validateInput("x");
269 s.validateInput("xx");
270 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match expected pattern. Must match pattern: x.*", ()->s.validateInput("y"));
271 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match expected pattern. Must match pattern: x.*", ()->s.validateInput("yx"));
272
273 assertThrowsWithMessage(SchemaValidationException.class, "Empty value not allowed.", ()->s.validateInput(""));
274 }
275
276 @Path @Schema(minl=2, maxl=3)
277 public static class B03a {}
278
279 @Test void b03a_length() throws Exception {
280 var s = HttpPartSchema.create().applyAll(Path.class, B03a.class).build();
281 s.validateInput("12");
282 s.validateInput("123");
283 s.validateInput(null);
284 assertThrowsWithMessage(SchemaValidationException.class, "Minimum length of value not met.", ()->s.validateInput("1"));
285 assertThrowsWithMessage(SchemaValidationException.class, "Maximum length of value exceeded.", ()->s.validateInput("1234"));
286 }
287
288 @Path
289 @Schema(
290 items=@Items(
291 minl=2, maxl=3,
292 items=@SubItems(
293 minl=3, maxl=4,
294 items={
295 "minLength:4,maxLength:5,",
296 "items:{minLength:5,maxLength:6}"
297 }
298 )
299 )
300 )
301 public static class B03b {}
302
303 @Test void b03b_length_items() throws Exception {
304 var s = HttpPartSchema.create().applyAll(Path.class, B03b.class).build();
305
306 s.getItems().validateInput("12");
307 s.getItems().getItems().validateInput("123");
308 s.getItems().getItems().getItems().validateInput("1234");
309 s.getItems().getItems().getItems().getItems().validateInput("12345");
310
311 s.getItems().validateInput("123");
312 s.getItems().getItems().validateInput("1234");
313 s.getItems().getItems().getItems().validateInput("12345");
314 s.getItems().getItems().getItems().getItems().validateInput("123456");
315
316 s.getItems().validateInput(null);
317 s.getItems().getItems().validateInput(null);
318 s.getItems().getItems().getItems().validateInput(null);
319 s.getItems().getItems().getItems().getItems().validateInput(null);
320
321 assertThrowsWithMessage(SchemaValidationException.class, "Minimum length of value not met.", ()->s.getItems().validateInput("1"));
322 assertThrowsWithMessage(SchemaValidationException.class, "Minimum length of value not met.", ()->s.getItems().getItems().validateInput("12"));
323 assertThrowsWithMessage(SchemaValidationException.class, "Minimum length of value not met.", ()->s.getItems().getItems().getItems().validateInput("123"));
324 assertThrowsWithMessage(SchemaValidationException.class, "Minimum length of value not met.", ()->s.getItems().getItems().getItems().getItems().validateInput("1234"));
325
326 assertThrowsWithMessage(SchemaValidationException.class, "Maximum length of value exceeded.", ()->s.getItems().validateInput("1234"));
327 assertThrowsWithMessage(SchemaValidationException.class, "Maximum length of value exceeded.", ()->s.getItems().getItems().validateInput("12345"));
328 assertThrowsWithMessage(SchemaValidationException.class, "Maximum length of value exceeded.", ()->s.getItems().getItems().getItems().validateInput("123456"));
329 assertThrowsWithMessage(SchemaValidationException.class, "Maximum length of value exceeded.", ()->s.getItems().getItems().getItems().getItems().validateInput("1234567"));
330 }
331
332 @Path @Schema(e="X,Y")
333 public static class B04a {}
334
335 @Test void b04a_enum() throws Exception {
336 var s = HttpPartSchema.create().applyAll(Path.class, B04a.class).build();
337 s.validateInput("X");
338 s.validateInput("Y");
339 s.validateInput(null);
340 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: X, Y", ()->s.validateInput("Z"));
341 }
342
343 @Path @Schema(e=" X , Y ")
344 public static class B04b {}
345
346 @Test void b04b_enum() throws Exception {
347 var s = HttpPartSchema.create().applyAll(Path.class, B04b.class).build();
348 s.validateInput("X");
349 s.validateInput("Y");
350 s.validateInput(null);
351 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: X, Y", ()->s.validateInput("Z"));
352 }
353
354 @Path @Schema(e="X,Y")
355 public static class B04c {}
356
357 @Test void b04c_enum_json() throws Exception {
358 var s = HttpPartSchema.create().applyAll(Path.class, B04c.class).build();
359 s.validateInput("X");
360 s.validateInput("Y");
361 s.validateInput(null);
362 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: X, Y", ()->s.validateInput("Z"));
363 }
364
365 @Path
366 @Schema(
367 items=@Items(
368 e="W",
369 items=@SubItems(
370 e="X",
371 items={
372 "enum:['Y'],",
373 "items:{enum:['Z']}"
374 }
375 )
376 )
377 )
378 public static class B04d {}
379
380 @Test void b04d_enum_items() throws Exception {
381 var s = HttpPartSchema.create().applyAll(Path.class, B04d.class).build();
382
383 s.getItems().validateInput("W");
384 s.getItems().getItems().validateInput("X");
385 s.getItems().getItems().getItems().validateInput("Y");
386 s.getItems().getItems().getItems().getItems().validateInput("Z");
387
388 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: W", ()->s.getItems().validateInput("V"));
389 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: X", ()->s.getItems().getItems().validateInput("V"));
390 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: Y", ()->s.getItems().getItems().getItems().validateInput("V"));
391 assertThrowsWithMessage(SchemaValidationException.class, "Value does not match one of the expected values. Must be one of the following: Z", ()->s.getItems().getItems().getItems().getItems().validateInput("V"));
392 }
393
394
395
396
397
398 @Path @Schema(min="10", max="100")
399 public static class C01a {}
400
401 @Test void c01a_minmax_ints() throws Exception {
402 var s = HttpPartSchema.create().applyAll(Path.class, C01a.class).build();
403 s.validateOutput(10, BeanContext.DEFAULT);
404 s.validateOutput(100, BeanContext.DEFAULT);
405 s.validateOutput(null, BeanContext.DEFAULT);
406 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.validateOutput(9, BeanContext.DEFAULT));
407 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.validateOutput(101, BeanContext.DEFAULT));
408 }
409
410 @Path
411 @Schema(
412 items=@Items(
413 min="10", max="100",
414 items=@SubItems(
415 min="100", max="1000",
416 items={
417 "minimum:1000,maximum:10000,",
418 "items:{minimum:10000,maximum:100000}"
419 }
420 )
421 )
422 )
423 public static class C01b {}
424
425 @Test void c01b_minmax_ints_items() throws Exception {
426 var s = HttpPartSchema.create().applyAll(Path.class, C01b.class).build();
427
428 s.getItems().validateOutput(10, BeanContext.DEFAULT);
429 s.getItems().getItems().validateOutput(100, BeanContext.DEFAULT);
430 s.getItems().getItems().getItems().validateOutput(1000, BeanContext.DEFAULT);
431 s.getItems().getItems().getItems().getItems().validateOutput(10000, BeanContext.DEFAULT);
432
433 s.getItems().validateOutput(100, BeanContext.DEFAULT);
434 s.getItems().getItems().validateOutput(1000, BeanContext.DEFAULT);
435 s.getItems().getItems().getItems().validateOutput(10000, BeanContext.DEFAULT);
436 s.getItems().getItems().getItems().getItems().validateOutput(100000, BeanContext.DEFAULT);
437
438 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().validateOutput(9, BeanContext.DEFAULT));
439 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().validateOutput(99, BeanContext.DEFAULT));
440 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().validateOutput(999, BeanContext.DEFAULT));
441 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(9999, BeanContext.DEFAULT));
442
443 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().validateOutput(101, BeanContext.DEFAULT));
444 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().validateOutput(1001, BeanContext.DEFAULT));
445 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().validateOutput(10001, BeanContext.DEFAULT));
446 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().getItems().validateOutput(100001, BeanContext.DEFAULT));
447 }
448
449 @Path
450 @Schema(min="10", max="100", emin=true, emax=true)
451 public static class C02a {}
452
453 @Test void c02a_minmax_exclusive() throws Exception {
454 var s = HttpPartSchema.create().applyAll(Path.class, C02a.class).build();
455 s.validateOutput(11, BeanContext.DEFAULT);
456 s.validateOutput(99, BeanContext.DEFAULT);
457 s.validateOutput(null, BeanContext.DEFAULT);
458 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.validateOutput(10, BeanContext.DEFAULT));
459 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.validateOutput(100, BeanContext.DEFAULT));
460 }
461
462 @Path
463 @Schema(
464 items=@Items(
465 min="10", max="100", emin=true, emax=true,
466 items=@SubItems(
467 min="100", max="1000", emin=true, emax=true,
468 items={
469 "minimum:1000,maximum:10000,exclusiveMinimum:true,exclusiveMaximum:true,",
470 "items:{minimum:10000,maximum:100000,exclusiveMinimum:true,exclusiveMaximum:true}"
471 }
472 )
473 )
474 )
475 public static class C02b {}
476
477 @Test void c02b_minmax_exclusive_items() throws Exception {
478 var s = HttpPartSchema.create().applyAll(Path.class, C02b.class).build();
479
480 s.getItems().validateOutput(11, BeanContext.DEFAULT);
481 s.getItems().getItems().validateOutput(101, BeanContext.DEFAULT);
482 s.getItems().getItems().getItems().validateOutput(1001, BeanContext.DEFAULT);
483 s.getItems().getItems().getItems().getItems().validateOutput(10001, BeanContext.DEFAULT);
484
485 s.getItems().validateOutput(99, BeanContext.DEFAULT);
486 s.getItems().getItems().validateOutput(999, BeanContext.DEFAULT);
487 s.getItems().getItems().getItems().validateOutput(9999, BeanContext.DEFAULT);
488 s.getItems().getItems().getItems().getItems().validateOutput(99999, BeanContext.DEFAULT);
489
490 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().validateOutput(10, BeanContext.DEFAULT));
491 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().validateOutput(100, BeanContext.DEFAULT));
492 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().validateOutput(1000, BeanContext.DEFAULT));
493 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(10000, BeanContext.DEFAULT));
494
495 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().validateOutput(100, BeanContext.DEFAULT));
496 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().validateOutput(1000, BeanContext.DEFAULT));
497 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().validateOutput(10000, BeanContext.DEFAULT));
498 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().getItems().validateOutput(100000, BeanContext.DEFAULT));
499 }
500
501 @Path
502 @Schema(min="10.1", max="100.1")
503 public static class C03a {}
504
505 @Test void c03_minmax_floats() throws Exception {
506 var s = HttpPartSchema.create().applyAll(Path.class, C03a.class).build();
507 s.validateOutput(10.1f, BeanContext.DEFAULT);
508 s.validateOutput(100.1f, BeanContext.DEFAULT);
509 s.validateOutput(null, BeanContext.DEFAULT);
510 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.validateOutput(10f, BeanContext.DEFAULT));
511 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.validateOutput(100.2f, BeanContext.DEFAULT));
512 }
513
514 @Path
515 @Schema(
516 items=@Items(
517 min="10.1", max="100.1",
518 items=@SubItems(
519 min="100.1", max="1000.1",
520 items={
521 "minimum:1000.1,maximum:10000.1,",
522 "items:{minimum:10000.1,maximum:100000.1}"
523 }
524 )
525 )
526 )
527 public static class C03b {}
528
529 @Test void c03b_minmax_floats_items() throws Exception {
530 var s = HttpPartSchema.create().applyAll(Path.class, C03b.class).build();
531
532 s.getItems().validateOutput(10.1f, BeanContext.DEFAULT);
533 s.getItems().getItems().validateOutput(100.1f, BeanContext.DEFAULT);
534 s.getItems().getItems().getItems().validateOutput(1000.1f, BeanContext.DEFAULT);
535 s.getItems().getItems().getItems().getItems().validateOutput(10000.1f, BeanContext.DEFAULT);
536
537 s.getItems().validateOutput(100.1f, BeanContext.DEFAULT);
538 s.getItems().getItems().validateOutput(1000.1f, BeanContext.DEFAULT);
539 s.getItems().getItems().getItems().validateOutput(10000.1f, BeanContext.DEFAULT);
540 s.getItems().getItems().getItems().getItems().validateOutput(100000.1f, BeanContext.DEFAULT);
541
542 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().validateOutput(10f, BeanContext.DEFAULT));
543 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().validateOutput(100f, BeanContext.DEFAULT));
544 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().validateOutput(1000f, BeanContext.DEFAULT));
545 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(10000f, BeanContext.DEFAULT));
546
547 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().validateOutput(100.2f, BeanContext.DEFAULT));
548 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().validateOutput(1000.2f, BeanContext.DEFAULT));
549 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().validateOutput(10000.2f, BeanContext.DEFAULT));
550 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().getItems().validateOutput(100000.2f, BeanContext.DEFAULT));
551 }
552
553 @Path
554 @Schema(min="10.1", max="100.1", emin=true, emax=true)
555 public static class C04a {}
556
557 @Test void c04a_minmax_floats_exclusive() throws Exception {
558 var s = HttpPartSchema.create().applyAll(Path.class, C04a.class).build();
559 s.validateOutput(10.2f, BeanContext.DEFAULT);
560 s.validateOutput(100f, BeanContext.DEFAULT);
561 s.validateOutput(null, BeanContext.DEFAULT);
562 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.validateOutput(10.1f, BeanContext.DEFAULT));
563 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.validateOutput(100.1f, BeanContext.DEFAULT));
564 }
565
566 @Path
567 @Schema(
568 items=@Items(
569 min="10.1", max="100.1", emin=true, emax=true,
570 items=@SubItems(
571 min="100.1", max="1000.1", emin=true, emax=true,
572 items={
573 "minimum:1000.1,maximum:10000.1,exclusiveMinimum:true,exclusiveMaximum:true,",
574 "items:{minimum:10000.1,maximum:100000.1,exclusiveMinimum:true,exclusiveMaximum:true}"
575 }
576 )
577 )
578 )
579 public static class C04b {}
580
581 @Test void c04b_minmax_floats_exclusive_items() throws Exception {
582 var s = HttpPartSchema.create().applyAll(Path.class, C04b.class).build();
583
584 s.getItems().validateOutput(10.2f, BeanContext.DEFAULT);
585 s.getItems().getItems().validateOutput(100.2f, BeanContext.DEFAULT);
586 s.getItems().getItems().getItems().validateOutput(1000.2f, BeanContext.DEFAULT);
587 s.getItems().getItems().getItems().getItems().validateOutput(10000.2f, BeanContext.DEFAULT);
588
589 s.getItems().validateOutput(100f, BeanContext.DEFAULT);
590 s.getItems().getItems().validateOutput(1000f, BeanContext.DEFAULT);
591 s.getItems().getItems().getItems().validateOutput(10000f, BeanContext.DEFAULT);
592 s.getItems().getItems().getItems().getItems().validateOutput(100000f, BeanContext.DEFAULT);
593
594 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().validateOutput(10.1f, BeanContext.DEFAULT));
595 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().validateOutput(100.1f, BeanContext.DEFAULT));
596 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().validateOutput(1000.1f, BeanContext.DEFAULT));
597 assertThrowsWithMessage(SchemaValidationException.class, "Minimum value not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(10000.1f, BeanContext.DEFAULT));
598
599 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().validateOutput(100.1f, BeanContext.DEFAULT));
600 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().validateOutput(1000.1f, BeanContext.DEFAULT));
601 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().validateOutput(10000.1f, BeanContext.DEFAULT));
602 assertThrowsWithMessage(SchemaValidationException.class, "Maximum value exceeded.", ()->s.getItems().getItems().getItems().getItems().validateOutput(100000.1f, BeanContext.DEFAULT));
603 }
604
605 @Path
606 @Schema(mo="10")
607 public static class C05a {}
608
609 @Test void c05a_multipleOf() throws Exception {
610 var s = HttpPartSchema.create().applyAll(Path.class, C05a.class).build();
611 s.validateOutput(0, BeanContext.DEFAULT);
612 s.validateOutput(10, BeanContext.DEFAULT);
613 s.validateOutput(20, BeanContext.DEFAULT);
614 s.validateOutput(10f, BeanContext.DEFAULT);
615 s.validateOutput(20f, BeanContext.DEFAULT);
616 s.validateOutput(null, BeanContext.DEFAULT);
617 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.validateOutput(11, BeanContext.DEFAULT));
618 }
619
620 @Path
621 @Schema(
622 items=@Items(
623 mo="10",
624 items=@SubItems(
625 mo="100",
626 items={
627 "multipleOf:1000,",
628 "items:{multipleOf:10000}"
629 }
630 )
631 )
632 )
633 public static class C05b {}
634
635 @Test void c05b_multipleOf_items() throws Exception {
636 var s = HttpPartSchema.create().applyAll(Path.class, C05b.class).build();
637
638 s.getItems().validateOutput(0, BeanContext.DEFAULT);
639 s.getItems().getItems().validateOutput(0, BeanContext.DEFAULT);
640 s.getItems().getItems().getItems().validateOutput(0, BeanContext.DEFAULT);
641 s.getItems().getItems().getItems().getItems().validateOutput(0, BeanContext.DEFAULT);
642
643 s.getItems().validateOutput(10, BeanContext.DEFAULT);
644 s.getItems().getItems().validateOutput(100, BeanContext.DEFAULT);
645 s.getItems().getItems().getItems().validateOutput(1000, BeanContext.DEFAULT);
646 s.getItems().getItems().getItems().getItems().validateOutput(10000, BeanContext.DEFAULT);
647
648 s.getItems().validateOutput(20, BeanContext.DEFAULT);
649 s.getItems().getItems().validateOutput(200, BeanContext.DEFAULT);
650 s.getItems().getItems().getItems().validateOutput(2000, BeanContext.DEFAULT);
651 s.getItems().getItems().getItems().getItems().validateOutput(20000, BeanContext.DEFAULT);
652
653 s.getItems().validateOutput(10f, BeanContext.DEFAULT);
654 s.getItems().getItems().validateOutput(100f, BeanContext.DEFAULT);
655 s.getItems().getItems().getItems().validateOutput(1000f, BeanContext.DEFAULT);
656 s.getItems().getItems().getItems().getItems().validateOutput(10000f, BeanContext.DEFAULT);
657
658 s.getItems().validateOutput(20f, BeanContext.DEFAULT);
659 s.getItems().getItems().validateOutput(200f, BeanContext.DEFAULT);
660 s.getItems().getItems().getItems().validateOutput(2000f, BeanContext.DEFAULT);
661 s.getItems().getItems().getItems().getItems().validateOutput(20000f, BeanContext.DEFAULT);
662
663 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().validateOutput(11, BeanContext.DEFAULT));
664 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().getItems().validateOutput(101, BeanContext.DEFAULT));
665 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().getItems().getItems().validateOutput(1001, BeanContext.DEFAULT));
666 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(10001, BeanContext.DEFAULT));
667 }
668
669 @Path
670 @Schema(mo="10.1")
671 public static class C06a {}
672
673 @Test void c06a_multipleOf_floats() throws Exception {
674 var s = HttpPartSchema.create().applyAll(Path.class, C06a.class).build();
675 s.validateOutput(0, BeanContext.DEFAULT);
676 s.validateOutput(10.1f, BeanContext.DEFAULT);
677 s.validateOutput(20.2f, BeanContext.DEFAULT);
678 s.validateOutput(null, BeanContext.DEFAULT);
679 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.validateOutput(10.2f, BeanContext.DEFAULT));
680 }
681
682 @Path
683 @Schema(
684 items=@Items(
685 mo="10.1",
686 items=@SubItems(
687 mo="100.1",
688 items={
689 "multipleOf:1000.1,",
690 "items:{multipleOf:10000.1}"
691 }
692 )
693 )
694 )
695 public static class C06b {}
696
697 @Test void c06b_multipleOf_floats_items() throws Exception {
698 var s = HttpPartSchema.create().applyAll(Path.class, C06b.class).build();
699
700 s.getItems().validateOutput(0, BeanContext.DEFAULT);
701 s.getItems().getItems().validateOutput(0, BeanContext.DEFAULT);
702 s.getItems().getItems().getItems().validateOutput(0, BeanContext.DEFAULT);
703 s.getItems().getItems().getItems().getItems().validateOutput(0, BeanContext.DEFAULT);
704
705 s.getItems().validateOutput(10.1f, BeanContext.DEFAULT);
706 s.getItems().getItems().validateOutput(100.1f, BeanContext.DEFAULT);
707 s.getItems().getItems().getItems().validateOutput(1000.1f, BeanContext.DEFAULT);
708 s.getItems().getItems().getItems().getItems().validateOutput(10000.1f, BeanContext.DEFAULT);
709
710 s.getItems().validateOutput(20.2f, BeanContext.DEFAULT);
711 s.getItems().getItems().validateOutput(200.2f, BeanContext.DEFAULT);
712 s.getItems().getItems().getItems().validateOutput(2000.2f, BeanContext.DEFAULT);
713 s.getItems().getItems().getItems().getItems().validateOutput(20000.2f, BeanContext.DEFAULT);
714
715 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().validateOutput(10.2f, BeanContext.DEFAULT));
716 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().getItems().validateOutput(100.2f, BeanContext.DEFAULT));
717 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().getItems().getItems().validateOutput(1000.2f, BeanContext.DEFAULT));
718 assertThrowsWithMessage(SchemaValidationException.class, "Multiple-of not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(10000.2f, BeanContext.DEFAULT));
719 }
720
721
722
723
724
725 @Path
726 @Schema(
727 items=@Items(
728 uniqueItems=true,
729 items=@SubItems(
730 uniqueItems=true,
731 items={
732 "uniqueItems:true,",
733 "items:{uniqueItems:true}"
734 }
735 )
736 )
737
738 )
739 public static class D01 {}
740
741 @Test void d01a_uniqueItems_arrays() throws Exception {
742 var s = HttpPartSchema.create().applyAll(Path.class, D01.class).build();
743
744 var good = split("a,b");
745 var bad = split("a,a");
746
747 s.getItems().validateOutput(good, BeanContext.DEFAULT);
748 s.getItems().getItems().validateOutput(good, BeanContext.DEFAULT);
749 s.getItems().getItems().getItems().validateOutput(good, BeanContext.DEFAULT);
750 s.getItems().getItems().getItems().getItems().validateOutput(good, BeanContext.DEFAULT);
751 s.getItems().validateOutput(null, BeanContext.DEFAULT);
752
753 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().validateOutput(bad, BeanContext.DEFAULT));
754 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().getItems().validateOutput(bad, BeanContext.DEFAULT));
755 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().getItems().getItems().validateOutput(bad, BeanContext.DEFAULT));
756 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().getItems().getItems().getItems().validateOutput(bad, BeanContext.DEFAULT));
757 }
758
759 @Test void d01b_uniqueItems_collections() throws Exception {
760 var s = HttpPartSchema.create().applyAll(Path.class, D01.class).build();
761
762 List<String>
763 good = l("a","b"),
764 bad = l("a","a");
765
766 s.getItems().validateOutput(good, BeanContext.DEFAULT);
767 s.getItems().getItems().validateOutput(good, BeanContext.DEFAULT);
768 s.getItems().getItems().getItems().validateOutput(good, BeanContext.DEFAULT);
769 s.getItems().getItems().getItems().getItems().validateOutput(good, BeanContext.DEFAULT);
770 s.getItems().validateOutput(null, BeanContext.DEFAULT);
771
772 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().validateOutput(bad, BeanContext.DEFAULT));
773 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().getItems().validateOutput(bad, BeanContext.DEFAULT));
774 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().getItems().getItems().validateOutput(bad, BeanContext.DEFAULT));
775 assertThrowsWithMessage(SchemaValidationException.class, "Duplicate items not allowed.", ()->s.getItems().getItems().getItems().getItems().validateOutput(bad, BeanContext.DEFAULT));
776 }
777
778 @Path
779 @Schema(
780 items=@Items(
781 minItems=1, maxItems=2,
782 items=@SubItems(
783 minItems=2, maxItems=3,
784 items={
785 "minItems:3,maxItems:4,",
786 "items:{minItems:4,maxItems:5}"
787 }
788 )
789 )
790
791 )
792 public static class D02 {}
793
794 @Test void d02a_minMaxItems_arrays() throws Exception {
795 var s = HttpPartSchema.create().applyAll(Path.class, D02.class).build();
796
797 s.getItems().validateOutput(split("1"), BeanContext.DEFAULT);
798 s.getItems().getItems().validateOutput(split("1,2"), BeanContext.DEFAULT);
799 s.getItems().getItems().getItems().validateOutput(split("1,2,3"), BeanContext.DEFAULT);
800 s.getItems().getItems().getItems().getItems().validateOutput(split("1,2,3,4"), BeanContext.DEFAULT);
801
802 s.getItems().validateOutput(split("1,2"), BeanContext.DEFAULT);
803 s.getItems().getItems().validateOutput(split("1,2,3"), BeanContext.DEFAULT);
804 s.getItems().getItems().getItems().validateOutput(split("1,2,3,4"), BeanContext.DEFAULT);
805 s.getItems().getItems().getItems().getItems().validateOutput(split("1,2,3,4,5"), BeanContext.DEFAULT);
806
807 assertThrowsWithMessage(SchemaValidationException.class, "Minimum number of items not met.", ()->s.getItems().validateOutput(new String[0], BeanContext.DEFAULT));
808 assertThrowsWithMessage(SchemaValidationException.class, "Minimum number of items not met.", ()->s.getItems().getItems().validateOutput(split("1"), BeanContext.DEFAULT));
809 assertThrowsWithMessage(SchemaValidationException.class, "Minimum number of items not met.", ()->s.getItems().getItems().getItems().validateOutput(split("1,2"), BeanContext.DEFAULT));
810 assertThrowsWithMessage(SchemaValidationException.class, "Minimum number of items not met.", ()->s.getItems().getItems().getItems().getItems().validateOutput(split("1,2,3"), BeanContext.DEFAULT));
811
812 assertThrowsWithMessage(SchemaValidationException.class, "Maximum number of items exceeded.", ()->s.getItems().validateOutput(split("1,2,3"), BeanContext.DEFAULT));
813 assertThrowsWithMessage(SchemaValidationException.class, "Maximum number of items exceeded.", ()->s.getItems().getItems().validateOutput(split("1,2,3,4"), BeanContext.DEFAULT));
814 assertThrowsWithMessage(SchemaValidationException.class, "Maximum number of items exceeded.", ()->s.getItems().getItems().getItems().validateOutput(split("1,2,3,4,5"), BeanContext.DEFAULT));
815 assertThrowsWithMessage(SchemaValidationException.class, "Maximum number of items exceeded.", ()->s.getItems().getItems().getItems().getItems().validateOutput(split("1,2,3,4,5,6"), BeanContext.DEFAULT));
816 }
817
818
819
820
821
822 @Path(name="x")
823 public static class E01 {}
824
825 @Test void e01_required_noDefault() {
826 var s = HttpPartSchema.create().applyAll(Path.class, E01.class).build();
827
828 assertTrue(s.isRequired());
829 }
830
831 @Path(name="x", def="defaultValue")
832 public static class E02 {}
833
834 @Test void e02_notRequired_withDefault() {
835 var s = HttpPartSchema.create().applyAll(Path.class, E02.class).build();
836
837 assertFalse(s.isRequired());
838 assertEquals("defaultValue", s.getDefault());
839 }
840
841 @Path(name="x", def="")
842 public static class E03 {}
843
844 @Test void e03_notRequired_withEmptyDefault() {
845 var s = HttpPartSchema.create().applyAll(Path.class, E03.class).build();
846
847 assertFalse(s.isRequired());
848 assertEquals("", s.getDefault());
849 }
850
851 public static class E04 {
852 public void a(
853 @Path(name = "logger", def = "") String loggerName,
854 @Path(name = "level", def = "INFO") String levelName
855 ) {
856
857 }
858 }
859
860 @Test void e04_multiplePathParamsWithDefaults() throws Exception {
861 var loggerParam = MethodInfo.of(E04.class.getMethod("a", String.class, String.class)).getParameter(0);
862 var levelParam = MethodInfo.of(E04.class.getMethod("a", String.class, String.class)).getParameter(1);
863
864 var loggerSchema = HttpPartSchema.create().applyAll(Path.class, loggerParam).build();
865 var levelSchema = HttpPartSchema.create().applyAll(Path.class, levelParam).build();
866
867
868 assertFalse(loggerSchema.isRequired());
869 assertFalse(levelSchema.isRequired());
870
871
872 assertEquals("", loggerSchema.getDefault());
873 assertEquals("INFO", levelSchema.getDefault());
874
875
876 assertEquals("logger", loggerSchema.getName());
877 assertEquals("level", levelSchema.getName());
878
879
880
881 assertDoesNotThrow(() -> loggerSchema.validateInput("test"));
882 assertDoesNotThrow(() -> levelSchema.validateInput("DEBUG"));
883 }
884
885 @Path(value="/remainder")
886 public static class E05 {}
887
888 @Test void e05_pathRemainder_notRequired() {
889 var s = HttpPartSchema.create().applyAll(Path.class, E05.class).build();
890
891 assertFalse(s.isRequired());
892 }
893 }