View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.httppart;
18  
19  import static org.junit.jupiter.api.Assertions.*;
20  
21  import org.apache.juneau.*;
22  import org.junit.jupiter.api.*;
23  
24  import jakarta.validation.constraints.*;
25  
26  /**
27   * Tests for Jakarta Bean Validation integration with HttpPartSchema.
28   *
29   * <p>
30   * This test uses the real jakarta.validation-api (test scope dependency) to verify
31   * that HttpPartSchema correctly processes Jakarta Validation constraint annotations.
32   */
33  class HttpPartSchema_JakartaValidation_Test extends TestBase {
34  
35  	//-----------------------------------------------------------------------------------------------------------------
36  	// @NotNull
37  	//-----------------------------------------------------------------------------------------------------------------
38  
39  	public static class A01 {
40  		@NotNull
41  		public String value;
42  	}
43  
44  	@Test
45  	void a01_jakarta_NotNull() throws Exception {
46  		NotNull anno = A01.class.getDeclaredField("value").getAnnotation(NotNull.class);
47  		var s = HttpPartSchema.create().apply(anno).build();
48  		assertTrue(s.isRequired());
49  	}
50  
51  	//-----------------------------------------------------------------------------------------------------------------
52  	// @Size
53  	//-----------------------------------------------------------------------------------------------------------------
54  
55  	public static class B01 {
56  		@Size(min=2, max=50)
57  		public String value;
58  	}
59  
60  	@Test
61  	void b01_jakarta_Size() throws Exception {
62  		Size anno = B01.class.getDeclaredField("value").getAnnotation(Size.class);
63  		var s = HttpPartSchema.create().apply(anno).build();
64  		assertEquals(2L, s.getMinLength());
65  		assertEquals(50L, s.getMaxLength());
66  		assertEquals(2L, s.getMinItems());
67  		assertEquals(50L, s.getMaxItems());
68  	}
69  
70  	//-----------------------------------------------------------------------------------------------------------------
71  	// @Min
72  	//-----------------------------------------------------------------------------------------------------------------
73  
74  	public static class C01 {
75  		@Min(10)
76  		public int value;
77  	}
78  
79  	@Test
80  	void c01_jakarta_Min() throws Exception {
81  		Min anno = C01.class.getDeclaredField("value").getAnnotation(Min.class);
82  		var s = HttpPartSchema.create().apply(anno).build();
83  		assertEquals(10L, s.getMinimum());
84  	}
85  
86  	//-----------------------------------------------------------------------------------------------------------------
87  	// @Max
88  	//-----------------------------------------------------------------------------------------------------------------
89  
90  	public static class D01 {
91  		@Max(100)
92  		public int value;
93  	}
94  
95  	@Test
96  	void d01_jakarta_Max() throws Exception {
97  		Max anno = D01.class.getDeclaredField("value").getAnnotation(Max.class);
98  		var s = HttpPartSchema.create().apply(anno).build();
99  		assertEquals(100L, s.getMaximum());
100 	}
101 
102 	//-----------------------------------------------------------------------------------------------------------------
103 	// @Pattern
104 	//-----------------------------------------------------------------------------------------------------------------
105 
106 	public static class E01 {
107 		@Pattern(regexp="^[A-Z]+$")
108 		public String value;
109 	}
110 
111 	@Test
112 	void e01_jakarta_Pattern() throws Exception {
113 		Pattern anno = E01.class.getDeclaredField("value").getAnnotation(Pattern.class);
114 		var s = HttpPartSchema.create().apply(anno).build();
115 		assertEquals("^[A-Z]+$", s.getPattern().pattern());
116 	}
117 
118 	//-----------------------------------------------------------------------------------------------------------------
119 	// @Email
120 	// Note: HttpPartFormat enum does not currently support "email" format, so this test is disabled.
121 	// The @Email constraint is recognized but does not map to a format value.
122 	//-----------------------------------------------------------------------------------------------------------------
123 
124 	public static class F01 {
125 		@Email
126 		public String value;
127 	}
128 
129 	// Disabled: HttpPartFormat enum does not support "email" format
130 	// @Test
131 	// void f01_jakarta_Email() throws Exception {
132 	// 	Email anno = F01.class.getDeclaredField("value").getAnnotation(Email.class);
133 	// 	var s = HttpPartSchema.create().apply(anno).build();
134 	// 	assertEquals("email", s.getFormat().toString());
135 	// }
136 
137 	//-----------------------------------------------------------------------------------------------------------------
138 	// @Positive
139 	//-----------------------------------------------------------------------------------------------------------------
140 
141 	public static class G01 {
142 		@Positive
143 		public int value;
144 	}
145 
146 	@Test
147 	void g01_jakarta_Positive() throws Exception {
148 		Positive anno = G01.class.getDeclaredField("value").getAnnotation(Positive.class);
149 		var s = HttpPartSchema.create().apply(anno).build();
150 		assertEquals(0, s.getMinimum());
151 		assertTrue(s.isExclusiveMinimum());
152 	}
153 
154 	//-----------------------------------------------------------------------------------------------------------------
155 	// @PositiveOrZero
156 	//-----------------------------------------------------------------------------------------------------------------
157 
158 	public static class H01 {
159 		@PositiveOrZero
160 		public int value;
161 	}
162 
163 	@Test
164 	void h01_jakarta_PositiveOrZero() throws Exception {
165 		PositiveOrZero anno = H01.class.getDeclaredField("value").getAnnotation(PositiveOrZero.class);
166 		var s = HttpPartSchema.create().apply(anno).build();
167 		assertEquals(0, s.getMinimum());
168 		assertFalse(s.isExclusiveMinimum());
169 	}
170 
171 	//-----------------------------------------------------------------------------------------------------------------
172 	// @Negative
173 	//-----------------------------------------------------------------------------------------------------------------
174 
175 	public static class I01 {
176 		@Negative
177 		public int value;
178 	}
179 
180 	@Test
181 	void i01_jakarta_Negative() throws Exception {
182 		Negative anno = I01.class.getDeclaredField("value").getAnnotation(Negative.class);
183 		var s = HttpPartSchema.create().apply(anno).build();
184 		assertEquals(0, s.getMaximum());
185 		assertTrue(s.isExclusiveMaximum());
186 	}
187 
188 	//-----------------------------------------------------------------------------------------------------------------
189 	// @NegativeOrZero
190 	//-----------------------------------------------------------------------------------------------------------------
191 
192 	public static class J01 {
193 		@NegativeOrZero
194 		public int value;
195 	}
196 
197 	@Test
198 	void j01_jakarta_NegativeOrZero() throws Exception {
199 		NegativeOrZero anno = J01.class.getDeclaredField("value").getAnnotation(NegativeOrZero.class);
200 		var s = HttpPartSchema.create().apply(anno).build();
201 		assertEquals(0, s.getMaximum());
202 		assertFalse(s.isExclusiveMaximum());
203 	}
204 
205 	//-----------------------------------------------------------------------------------------------------------------
206 	// @NotEmpty
207 	//-----------------------------------------------------------------------------------------------------------------
208 
209 	public static class K01 {
210 		@NotEmpty
211 		public String value;
212 	}
213 
214 	@Test
215 	void k01_jakarta_NotEmpty() throws Exception {
216 		NotEmpty anno = K01.class.getDeclaredField("value").getAnnotation(NotEmpty.class);
217 		var s = HttpPartSchema.create().apply(anno).build();
218 		assertTrue(s.isRequired());
219 		assertEquals(1L, s.getMinLength());
220 		assertEquals(1L, s.getMinItems());
221 	}
222 
223 	//-----------------------------------------------------------------------------------------------------------------
224 	// @NotBlank
225 	//-----------------------------------------------------------------------------------------------------------------
226 
227 	public static class L01 {
228 		@NotBlank
229 		public String value;
230 	}
231 
232 	@Test
233 	void l01_jakarta_NotBlank() throws Exception {
234 		NotBlank anno = L01.class.getDeclaredField("value").getAnnotation(NotBlank.class);
235 		var s = HttpPartSchema.create().apply(anno).build();
236 		assertTrue(s.isRequired());
237 		assertEquals(1L, s.getMinLength());
238 		assertEquals(".*\\S.*", s.getPattern().pattern());
239 	}
240 
241 	//-----------------------------------------------------------------------------------------------------------------
242 	// @DecimalMin (inclusive)
243 	//-----------------------------------------------------------------------------------------------------------------
244 
245 	public static class M01 {
246 		@DecimalMin("10.5")
247 		public double value;
248 	}
249 
250 	@Test
251 	void m01_jakarta_DecimalMin_inclusive() throws Exception {
252 		DecimalMin anno = M01.class.getDeclaredField("value").getAnnotation(DecimalMin.class);
253 		var s = HttpPartSchema.create().apply(anno).build();
254 		assertEquals(10.5, s.getMinimum().doubleValue());
255 		assertFalse(s.isExclusiveMinimum());
256 	}
257 
258 	//-----------------------------------------------------------------------------------------------------------------
259 	// @DecimalMin (exclusive)
260 	//-----------------------------------------------------------------------------------------------------------------
261 
262 	public static class M02 {
263 		@DecimalMin(value="10.5", inclusive=false)
264 		public double value;
265 	}
266 
267 	@Test
268 	void m02_jakarta_DecimalMin_exclusive() throws Exception {
269 		DecimalMin anno = M02.class.getDeclaredField("value").getAnnotation(DecimalMin.class);
270 		var s = HttpPartSchema.create().apply(anno).build();
271 		assertEquals(10.5, s.getMinimum().doubleValue());
272 		assertTrue(s.isExclusiveMinimum());
273 	}
274 
275 	//-----------------------------------------------------------------------------------------------------------------
276 	// @DecimalMax (inclusive)
277 	//-----------------------------------------------------------------------------------------------------------------
278 
279 	public static class N01 {
280 		@DecimalMax("99.9")
281 		public double value;
282 	}
283 
284 	@Test
285 	void n01_jakarta_DecimalMax_inclusive() throws Exception {
286 		DecimalMax anno = N01.class.getDeclaredField("value").getAnnotation(DecimalMax.class);
287 		var s = HttpPartSchema.create().apply(anno).build();
288 		assertEquals(99.9, s.getMaximum().doubleValue(), 0.001);
289 		assertFalse(s.isExclusiveMaximum());
290 	}
291 
292 	//-----------------------------------------------------------------------------------------------------------------
293 	// @DecimalMax (exclusive)
294 	//-----------------------------------------------------------------------------------------------------------------
295 
296 	public static class N02 {
297 		@DecimalMax(value="99.9", inclusive=false)
298 		public double value;
299 	}
300 
301 	@Test
302 	void n02_jakarta_DecimalMax_exclusive() throws Exception {
303 		DecimalMax anno = N02.class.getDeclaredField("value").getAnnotation(DecimalMax.class);
304 		var s = HttpPartSchema.create().apply(anno).build();
305 		assertEquals(99.9, s.getMaximum().doubleValue(), 0.001);
306 		assertTrue(s.isExclusiveMaximum());
307 	}
308 
309 	//-----------------------------------------------------------------------------------------------------------------
310 	// Multiple constraints
311 	//-----------------------------------------------------------------------------------------------------------------
312 
313 	public static class O01 {
314 		@NotNull
315 		@Size(min=5, max=20)
316 		@Pattern(regexp="^[a-z]+$")
317 		public String value;
318 	}
319 
320 	@Test
321 	void o01_jakarta_multiple_constraints() throws Exception {
322 		var field = O01.class.getDeclaredField("value");
323 		var s = HttpPartSchema.create()
324 			.apply(field.getAnnotation(NotNull.class))
325 			.apply(field.getAnnotation(Size.class))
326 			.apply(field.getAnnotation(Pattern.class))
327 			.build();
328 
329 		assertTrue(s.isRequired());
330 		assertEquals(5L, s.getMinLength());
331 		assertEquals(20L, s.getMaxLength());
332 		assertEquals("^[a-z]+$", s.getPattern().pattern());
333 	}
334 }