1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.http.remote;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.http.HttpParts.*;
21 import static org.junit.jupiter.api.Assertions.*;
22
23 import java.io.*;
24 import java.math.*;
25 import java.util.*;
26 import java.util.concurrent.atomic.*;
27
28 import org.apache.http.*;
29 import org.apache.juneau.*;
30 import org.apache.juneau.annotation.*;
31 import org.apache.juneau.collections.*;
32 import org.apache.juneau.http.annotation.*;
33 import org.apache.juneau.http.annotation.Header;
34 import org.apache.juneau.http.part.*;
35 import org.apache.juneau.internal.*;
36 import org.apache.juneau.rest.RestRequest;
37 import org.apache.juneau.rest.annotation.*;
38 import org.apache.juneau.rest.client.*;
39 import org.apache.juneau.rest.mock.*;
40 import org.apache.juneau.uon.*;
41 import org.apache.juneau.urlencoding.*;
42 import org.apache.juneau.utest.utils.*;
43 import org.junit.jupiter.api.*;
44
45 class Remote_FormDataAnnotation_Test extends TestBase {
46
47 public static class Bean {
48 public int f;
49 public static Bean create() {
50 var b = new Bean();
51 b.f = 1;
52 return b;
53 }
54 }
55
56 public static class Bean2 extends Bean {
57 public static Bean2 create() {
58 var b = new Bean2();
59 b.f = 1;
60 return b;
61 }
62 @Override
63 public String toString() {
64 return UrlEncodingSerializer.DEFAULT.toString(this);
65 }
66 }
67
68
69
70
71
72 @Rest
73 public static class A {
74 @RestPost
75 public String a(@FormData("*") JsonMap m, @Header("Content-Type") String ct) {
76 assertEquals("application/x-www-form-urlencoded", ct);
77 return m.toString();
78 }
79 }
80
81 @Remote
82 public interface A1 {
83 @RemotePost(path="a") String x1(@FormData("x") int b);
84 @RemotePost(path="a") String x2(@FormData("x") float b);
85 @RemotePost(path="a") String x3(@FormData("x") Bean b);
86 @RemotePost(path="a") String x4(@FormData("*") Bean b);
87 @RemotePost(path="a") String x5(@FormData Bean b);
88 @RemotePost(path="a") String x6(@FormData("x") Bean[] b);
89 @RemotePost(path="a") String x7(@FormData("x") @Schema(cf="uon") Bean[] b);
90 @RemotePost(path="a") String x8(@FormData("x") List<Bean> b);
91 @RemotePost(path="a") String x9(@FormData("x") @Schema(cf="uon") List<Bean> b);
92 @RemotePost(path="a") String x10(@FormData("x") Map<String,Bean> b);
93 @RemotePost(path="a") String x11(@FormData("*") Map<String,Bean> b);
94 @RemotePost(path="a") String x12(@FormData Map<String,Bean> b);
95 @RemotePost(path="a") String x13(@FormData("x") @Schema(f="uon") Map<String,Bean> b);
96 @RemotePost(path="a") String x14(@FormData @Schema(f="uon") Map<String,Bean> b);
97 @RemotePost(path="a") String x15(@FormData("*") Reader b);
98 @RemotePost(path="a") String x16(@FormData Reader b);
99 @RemotePost(path="a") String x17(@FormData("*") InputStream b);
100 @RemotePost(path="a") String x18(@FormData InputStream b);
101 @RemotePost(path="a") String x19(@FormData("*") PartList b);
102 @RemotePost(path="a") String x20(@FormData PartList b);
103 @RemotePost(path="a") String x21(@FormData NameValuePair b);
104 @RemotePost(path="a") String x22(@FormData String b);
105 @RemotePost(path="a") String x23(@FormData InputStream b);
106 @RemotePost(path="a") String x24(@FormData Reader b);
107 @RemotePost(path="a") String x25(@FormData Bean2 b);
108 @RemotePost(path="a") String x26(@FormData List<NameValuePair> b);
109 }
110
111 @Test void a01_objectTypes() {
112 var x = MockRestClient.build(A.class).getRemote(A1.class);
113 assertEquals("{x:'1'}",x.x1(1));
114 assertEquals("{x:'1.0'}",x.x2(1));
115 assertEquals("{x:'f=1'}",x.x3(Bean.create()));
116 assertEquals("{f:'1'}",x.x4(Bean.create()));
117 assertEquals("{f:'1'}",x.x5(Bean.create()));
118 assertEquals("{x:'f=1,f=1'}",x.x6(new Bean[]{Bean.create(),Bean.create()}));
119 assertEquals("{x:'@((f=1),(f=1))'}",x.x7(new Bean[]{Bean.create(),Bean.create()}));
120 assertEquals("{x:'f=1,f=1'}",x.x8(alist(Bean.create(),Bean.create())));
121 assertEquals("{x:'@((f=1),(f=1))'}",x.x9(alist(Bean.create(),Bean.create())));
122 assertEquals("{x:'k1=f\\\\=1'}",x.x10(map("k1",Bean.create())));
123 assertEquals("{k1:'f=1'}",x.x11(map("k1",Bean.create())));
124 assertEquals("{k1:'f=1'}",x.x12(map("k1",Bean.create())));
125 assertEquals("{x:'k1=f\\\\=1'}",x.x13(map("k1",Bean.create())));
126 assertEquals("{k1:'f=1'}",x.x14(map("k1",Bean.create())));
127 assertEquals("{x:'1'}",x.x15(reader("x=1")));
128 assertEquals("{x:'1'}",x.x16(reader("x=1")));
129 assertEquals("{x:'1'}",x.x17(inputStream("x=1")));
130 assertEquals("{x:'1'}",x.x18(inputStream("x=1")));
131 assertEquals("{foo:'bar'}",x.x19(parts("foo","bar")));
132 assertEquals("{foo:'bar'}",x.x20(parts("foo","bar")));
133 assertEquals("{foo:'bar'}",x.x21(part("foo","bar")));
134 assertEquals("{foo:'bar'}",x.x22("foo=bar"));
135 assertEquals("{}",x.x22(null));
136 assertEquals("{foo:'bar'}",x.x23(inputStream("foo=bar")));
137 assertEquals("{foo:'bar'}",x.x24(reader("foo=bar")));
138 assertEquals("{f:'1'}",x.x25(Bean2.create()));
139 assertEquals("{foo:'bar'}",x.x26(alist(part("foo","bar"))));
140 }
141
142
143
144
145
146 @Rest
147 public static class B {
148 @RestOp
149 public String post(@FormData("*") JsonMap m) {
150 return m.toString();
151 }
152 }
153
154 @Remote
155 public interface B1 {
156 @RemoteOp(path="/") String postX1(@FormData("x") @Schema(df="foo") String b);
157 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(df="foo",aev=true) String b);
158 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(df="") String b);
159 @RemoteOp(path="/") String postX4(@FormData("x") @Schema(df="",aev=true) String b);
160 }
161
162 @Test void b01_default_allowEmptyValue() {
163 var x = remote(B.class,B1.class);
164 assertEquals("{x:'foo'}",x.postX1(null));
165 assertThrowsWithMessage(Exception.class, "Empty value not allowed.", ()->x.postX1(""));
166 assertEquals("{x:'foo'}",x.postX2(null));
167 assertEquals("{x:''}",x.postX2(""));
168 assertEquals("{x:''}",x.postX3(null));
169 assertThrowsWithMessage(Exception.class, "Empty value not allowed.", ()->x.postX3(""));
170 assertEquals("{x:''}",x.postX4(null));
171 assertEquals("{x:''}",x.postX4(""));
172 }
173
174
175
176
177
178 @Rest
179 public static class C {
180 @RestPost
181 public String a(@FormData("*") JsonMap m) {
182 return m.toString();
183 }
184 @RestPost
185 public Reader b(@Content Reader b) {
186 return b;
187 }
188 }
189
190 @Remote
191 public interface C1 {
192 @RemoteOp(path="/a") String postX1(@FormData("x") String...b);
193 @RemoteOp(path="/b") String postX2(@FormData("x") String...b);
194 @RemoteOp(path="/a") String postX3(@FormData("x") @Schema(cf="csv") String...b);
195 @RemoteOp(path="/b") String postX4(@FormData("x") @Schema(cf="csv") String...b);
196 @RemoteOp(path="/a") String postX5(@FormData("x") @Schema(cf="ssv") String...b);
197 @RemoteOp(path="/b") String postX6(@FormData("x") @Schema(cf="ssv") String...b);
198 @RemoteOp(path="/a") String postX7(@FormData("x") @Schema(cf="tsv") String...b);
199 @RemoteOp(path="/b") String postX8(@FormData("x") @Schema(cf="tsv") String...b);
200 @RemoteOp(path="/a") String postX9(@FormData("x") @Schema(cf="pipes") String...b);
201 @RemoteOp(path="/b") String postX10(@FormData("x") @Schema(cf="pipes") String...b);
202 @RemoteOp(path="/a") String postX11(@FormData("x") @Schema(cf="multi") String...b);
203 @RemoteOp(path="/b") String postX12(@FormData("x") @Schema(cf="multi") String...b);
204 @RemoteOp(path="/a") String postX13(@FormData("x") @Schema(cf="uon") String...b);
205 @RemoteOp(path="/b") String postX14(@FormData("x") @Schema(cf="uon") String...b);
206 }
207
208 @Test void c01_collectionFormat() {
209 var x = remote(C.class,C1.class);
210 assertEquals("{x:'foo,bar'}",x.postX1("foo","bar"));
211 assertEquals("x=foo%2Cbar",x.postX2("foo","bar"));
212 assertEquals("{x:'foo,bar'}",x.postX3("foo","bar"));
213 assertEquals("x=foo%2Cbar",x.postX4("foo","bar"));
214 assertEquals("{x:'foo bar'}",x.postX5("foo","bar"));
215 assertEquals("x=foo+bar",x.postX6("foo","bar"));
216 assertEquals("{x:'foo\\tbar'}",x.postX7("foo","bar"));
217 assertEquals("x=foo%09bar",x.postX8("foo","bar"));
218 assertEquals("{x:'foo|bar'}",x.postX9("foo","bar"));
219 assertEquals("x=foo%7Cbar",x.postX10("foo","bar"));
220 assertEquals("{x:'foo,bar'}",x.postX11("foo","bar"));
221 assertEquals("x=foo%2Cbar",x.postX12("foo","bar"));
222 assertEquals("{x:'@(foo,bar)'}",x.postX13("foo","bar"));
223 assertEquals("x=%40%28foo%2Cbar%29",x.postX14("foo","bar"));
224 }
225
226
227
228
229
230 @Rest
231 public static class D {
232 @RestOp
233 public String post(@FormData("*") JsonMap m) {
234 return m.toString();
235 }
236 }
237
238 @Remote
239 public interface D1 {
240 @RemoteOp(path="/") String postX1(@FormData("x") @Schema(min="1",max="10") int b);
241 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) int b);
242 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) int b);
243 @RemoteOp(path="/") String postX4(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) int b);
244 @RemoteOp(path="/") String postX5(@FormData("x") @Schema(min="1",max="10") short b);
245 @RemoteOp(path="/") String postX6(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) short b);
246 @RemoteOp(path="/") String postX7(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) short b);
247 @RemoteOp(path="/") String postX8(@FormData("x") @Schema(min="1",max="10") long b);
248 @RemoteOp(path="/") String postX9(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) long b);
249 @RemoteOp(path="/") String postX10(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) long b);
250 @RemoteOp(path="/") String postX11(@FormData("x") @Schema(min="1",max="10") float b);
251 @RemoteOp(path="/") String postX12(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) float b);
252 @RemoteOp(path="/") String postX13(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) float b);
253 @RemoteOp(path="/") String postX14(@FormData("x") @Schema(min="1",max="10") double b);
254 @RemoteOp(path="/") String postX15(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) double b);
255 @RemoteOp(path="/") String postX16(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) double b);
256 @RemoteOp(path="/") String postX17(@FormData("x") @Schema(min="1",max="10") byte b);
257 @RemoteOp(path="/") String postX18(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) byte b);
258 @RemoteOp(path="/") String postX19(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) byte b);
259 @RemoteOp(path="/") String postX20(@FormData("x") @Schema(min="1",max="10") AtomicInteger b);
260 @RemoteOp(path="/") String postX21(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) AtomicInteger b);
261 @RemoteOp(path="/") String postX22(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) AtomicInteger b);
262 @RemoteOp(path="/") String postX23(@FormData("x") @Schema(min="1",max="10") BigDecimal b);
263 @RemoteOp(path="/") String postX24(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) BigDecimal b);
264 @RemoteOp(path="/") String postX25(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) BigDecimal b);
265 @RemoteOp(path="/") String postX26(@FormData("x") @Schema(min="1",max="10") Integer b);
266 @RemoteOp(path="/") String postX27(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) Integer b);
267 @RemoteOp(path="/") String postX28(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) Integer b);
268 @RemoteOp(path="/") String postX29(@FormData("x") @Schema(min="1",max="10") Short b);
269 @RemoteOp(path="/") String postX30(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) Short b);
270 @RemoteOp(path="/") String postX31(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) Short b);
271 @RemoteOp(path="/") String postX32(@FormData("x") @Schema(min="1",max="10") Long b);
272 @RemoteOp(path="/") String postX33(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) Long b);
273 @RemoteOp(path="/") String postX34(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) Long b);
274 @RemoteOp(path="/") String postX35(@FormData("x") @Schema(min="1",max="10") Float b);
275 @RemoteOp(path="/") String postX36(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) Float b);
276 @RemoteOp(path="/") String postX37(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) Float b);
277 @RemoteOp(path="/") String postX38(@FormData("x") @Schema(min="1",max="10") Double b);
278 @RemoteOp(path="/") String postX39(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) Double b);
279 @RemoteOp(path="/") String postX40(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) Double b);
280 @RemoteOp(path="/") String postX41(@FormData("x") @Schema(min="1",max="10") Byte b);
281 @RemoteOp(path="/") String postX42(@FormData("x") @Schema(min="1",max="10",emin=false,emax=false) Byte b);
282 @RemoteOp(path="/") String postX43(@FormData("x") @Schema(min="1",max="10",emin=true,emax=true) Byte b);
283 }
284
285 @Test void d01_min_max_emin_emax() {
286 var x = remote(D.class,D1.class);
287 assertEquals("{x:'1'}",x.postX1(1));
288 assertEquals("{x:'10'}",x.postX1(10));
289 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX1(0));
290 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX1(11));
291 assertEquals("{x:'1'}",x.postX2(1));
292 assertEquals("{x:'10'}",x.postX2(10));
293 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX2(0));
294 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX2(11));
295 assertEquals("{x:'2'}",x.postX3(2));
296 assertEquals("{x:'9'}",x.postX3(9));
297 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX3(1));
298 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX3(10));
299 assertEquals("{x:'1'}",x.postX5((short)1));
300 assertEquals("{x:'10'}",x.postX5((short)10));
301 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX5((short)0));
302 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX5((short)11));
303 assertEquals("{x:'1'}",x.postX6((short)1));
304 assertEquals("{x:'10'}",x.postX6((short)10));
305 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX6((short)0));
306 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX6((short)11));
307 assertEquals("{x:'2'}",x.postX7((short)2));
308 assertEquals("{x:'9'}",x.postX7((short)9));
309 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX7((short)1));
310 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX7((short)10));
311 assertEquals("{x:'1'}",x.postX8(1L));
312 assertEquals("{x:'10'}",x.postX8(10L));
313 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX8(0L));
314 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX8(11L));
315 assertEquals("{x:'1'}",x.postX9(1L));
316 assertEquals("{x:'10'}",x.postX9(10L));
317 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX9(0L));
318 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX9(11L));
319 assertEquals("{x:'2'}",x.postX10(2L));
320 assertEquals("{x:'9'}",x.postX10(9L));
321 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX10(1L));
322 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX10(10L));
323 assertEquals("{x:'1.0'}",x.postX11(1f));
324 assertEquals("{x:'10.0'}",x.postX11(10f));
325 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX11(0.9f));
326 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX11(10.1f));
327 assertEquals("{x:'1.0'}",x.postX12(1f));
328 assertEquals("{x:'10.0'}",x.postX12(10f));
329 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX12(0.9f));
330 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX12(10.1f));
331 assertEquals("{x:'1.1'}",x.postX13(1.1f));
332 assertEquals("{x:'9.9'}",x.postX13(9.9f));
333 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX13(1f));
334 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX13(10f));
335 assertEquals("{x:'1.0'}",x.postX14(1d));
336 assertEquals("{x:'10.0'}",x.postX14(10d));
337 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX14(0.9d));
338 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX14(10.1d));
339 assertEquals("{x:'1.0'}",x.postX15(1d));
340 assertEquals("{x:'10.0'}",x.postX15(10d));
341 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX15(0.9d));
342 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX15(10.1d));
343 assertEquals("{x:'1.1'}",x.postX16(1.1d));
344 assertEquals("{x:'9.9'}",x.postX16(9.9d));
345 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX16(1d));
346 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX16(10d));
347 assertEquals("{x:'1'}",x.postX17((byte)1));
348 assertEquals("{x:'10'}",x.postX17((byte)10));
349 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX17((byte)0));
350 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX17((byte)11));
351 assertEquals("{x:'1'}",x.postX18((byte)1));
352 assertEquals("{x:'10'}",x.postX18((byte)10));
353 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX18((byte)0));
354 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX18((byte)11));
355 assertEquals("{x:'2'}",x.postX19((byte)2));
356 assertEquals("{x:'9'}",x.postX19((byte)9));
357 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX19((byte)1));
358 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX19((byte)10));
359 assertEquals("{x:'1'}",x.postX20(new AtomicInteger(1)));
360 assertEquals("{x:'10'}",x.postX20(new AtomicInteger(10)));
361 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX20(new AtomicInteger(0)));
362 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX20(new AtomicInteger(11)));
363 assertEquals("{x:'1'}",x.postX21(new AtomicInteger(1)));
364 assertEquals("{x:'10'}",x.postX21(new AtomicInteger(10)));
365 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX21(new AtomicInteger(0)));
366 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX21(new AtomicInteger(11)));
367 assertEquals("{x:'2'}",x.postX22(new AtomicInteger(2)));
368 assertEquals("{x:'9'}",x.postX22(new AtomicInteger(9)));
369 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX22(new AtomicInteger(1)));
370 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX22(new AtomicInteger(10)));
371 assertEquals("{x:'1'}",x.postX23(new BigDecimal(1)));
372 assertEquals("{x:'10'}",x.postX23(new BigDecimal(10)));
373 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX23(new BigDecimal(0)));
374 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX23(new BigDecimal(11)));
375 assertEquals("{x:'1'}",x.postX24(new BigDecimal(1)));
376 assertEquals("{x:'10'}",x.postX24(new BigDecimal(10)));
377 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX24(new BigDecimal(0)));
378 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX24(new BigDecimal(11)));
379 assertEquals("{x:'2'}",x.postX25(new BigDecimal(2)));
380 assertEquals("{x:'9'}",x.postX25(new BigDecimal(9)));
381 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX25(new BigDecimal(1)));
382 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX25(new BigDecimal(10)));
383 assertEquals("{x:'1'}",x.postX26(1));
384 assertEquals("{x:'10'}",x.postX26(10));
385 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX26(0));
386 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX26(11));
387 assertEquals("{}",x.postX26(null));
388 assertEquals("{x:'1'}",x.postX27(1));
389 assertEquals("{x:'10'}",x.postX27(10));
390 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX27(0));
391 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX27(11));
392 assertEquals("{}",x.postX27(null));
393 assertEquals("{x:'2'}",x.postX28(2));
394 assertEquals("{x:'9'}",x.postX28(9));
395 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX28(1));
396 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX28(10));
397 assertEquals("{}",x.postX28(null));
398 assertEquals("{x:'1'}",x.postX29((short)1));
399 assertEquals("{x:'10'}",x.postX29((short)10));
400 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX29((short)0));
401 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX29((short)11));
402 assertEquals("{}",x.postX29(null));
403 assertEquals("{x:'1'}",x.postX30((short)1));
404 assertEquals("{x:'10'}",x.postX30((short)10));
405 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX30((short)0));
406 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX30((short)11));
407 assertEquals("{}",x.postX30(null));
408 assertEquals("{x:'2'}",x.postX31((short)2));
409 assertEquals("{x:'9'}",x.postX31((short)9));
410 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX31((short)1));
411 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX31((short)10));
412 assertEquals("{}",x.postX31(null));
413 assertEquals("{x:'1'}",x.postX32(1L));
414 assertEquals("{x:'10'}",x.postX32(10L));
415 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX32(0L));
416 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX32(11L));
417 assertEquals("{}",x.postX32(null));
418 assertEquals("{x:'1'}",x.postX33(1L));
419 assertEquals("{x:'10'}",x.postX33(10L));
420 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX33(0L));
421 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX33(11L));
422 assertEquals("{}",x.postX33(null));
423 assertEquals("{x:'2'}",x.postX34(2L));
424 assertEquals("{x:'9'}",x.postX34(9L));
425 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX34(1L));
426 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX34(10L));
427 assertEquals("{}",x.postX34(null));
428 assertEquals("{x:'1.0'}",x.postX35(1f));
429 assertEquals("{x:'10.0'}",x.postX35(10f));
430 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX35(0.9f));
431 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX35(10.1f));
432 assertEquals("{}",x.postX35(null));
433 assertEquals("{x:'1.0'}",x.postX36(1f));
434 assertEquals("{x:'10.0'}",x.postX36(10f));
435 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX36(0.9f));
436 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX36(10.1f));
437 assertEquals("{}",x.postX36(null));
438 assertEquals("{x:'1.1'}",x.postX37(1.1f));
439 assertEquals("{x:'9.9'}",x.postX37(9.9f));
440 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX37(1f));
441 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX37(10f));
442 assertEquals("{}",x.postX37(null));
443 assertEquals("{x:'1.0'}",x.postX38(1d));
444 assertEquals("{x:'10.0'}",x.postX38(10d));
445 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX38(0.9d));
446 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX38(10.1d));
447 assertEquals("{}",x.postX38(null));
448 assertEquals("{x:'1.0'}",x.postX39(1d));
449 assertEquals("{x:'10.0'}",x.postX39(10d));
450 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX39(0.9d));
451 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX39(10.1d));
452 assertEquals("{}",x.postX39(null));
453 assertEquals("{x:'1.1'}",x.postX40(1.1d));
454 assertEquals("{x:'9.9'}",x.postX40(9.9d));
455 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX40(1d));
456 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX40(10d));
457 assertEquals("{}",x.postX40(null));
458 assertEquals("{x:'1'}",x.postX41((byte)1));
459 assertEquals("{x:'10'}",x.postX41((byte)10));
460 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX41((byte)0));
461 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX41((byte)11));
462 assertEquals("{}",x.postX41(null));
463 assertEquals("{x:'1'}",x.postX42((byte)1));
464 assertEquals("{x:'10'}",x.postX42((byte)10));
465 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX42((byte)0));
466 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX42((byte)11));
467 assertEquals("{}",x.postX42(null));
468 assertEquals("{x:'2'}",x.postX43((byte)2));
469 assertEquals("{x:'9'}",x.postX43((byte)9));
470 assertThrowsWithMessage(Exception.class, "Minimum value not met.", ()->x.postX43((byte)1));
471 assertThrowsWithMessage(Exception.class, "Maximum value exceeded.", ()->x.postX43((byte)10));
472 assertEquals("{}",x.postX43(null));
473 }
474
475
476
477
478
479 @Rest
480 public static class E {
481 @RestOp
482 public String post(@FormData("*") JsonMap m) {
483 return m.toString();
484 }
485 }
486
487 @Remote
488 public interface E1 {
489 @RemoteOp(path="/") String postX1(@FormData("x") @Schema(cf="pipes", mini=1,maxi=2) String...b);
490 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(items=@Items(cf="pipes", mini=1,maxi=2)) String[]...b);
491 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(cf="pipes",ui=false) String...b);
492 @RemoteOp(path="/") String postX4(@FormData("x") @Schema(items=@Items(cf="pipes",ui=false)) String[]...b);
493 @RemoteOp(path="/") String postX5(@FormData("x") @Schema(cf="pipes",ui=true) String...b);
494 @RemoteOp(path="/") String postX6(@FormData("x") @Schema(items=@Items(cf="pipes",ui=true)) String[]...b);
495 }
496
497 @Test void e01_mini_maxi_ui() {
498 var x = remote(E.class,E1.class);
499 assertEquals("{x:'1'}",x.postX1("1"));
500 assertEquals("{x:'1|2'}",x.postX1("1","2"));
501 assertThrowsWithMessage(Exception.class, "Minimum number of items not met.", x::postX1);
502 assertThrowsWithMessage(Exception.class, "Maximum number of items exceeded.", ()->x.postX1("1","2","3"));
503 assertEquals("{x:null}",x.postX1((String)null));
504 assertEquals("{x:'1'}",x.postX2(new String[]{"1"}));
505 assertEquals("{x:'1|2'}",x.postX2(new String[]{"1","2"}));
506 assertThrowsWithMessage(Exception.class, "Minimum number of items not met.", ()->x.postX2(new String[]{}));
507 assertThrowsWithMessage(Exception.class, "Maximum number of items exceeded.", ()->x.postX2(new String[]{"1","2","3"}));
508 assertEquals("{x:null}",x.postX2(new String[]{null}));
509 assertEquals("{x:'1|1'}",x.postX3("1","1"));
510 assertEquals("{x:'1|1'}",x.postX4(new String[]{"1","1"}));
511 assertEquals("{x:'1|2'}",x.postX5("1","2"));
512 assertThrowsWithMessage(Exception.class, "Duplicate items not allowed.", ()->x.postX5("1","1"));
513 assertEquals("{x:'1|2'}",x.postX6(new String[]{"1","2"}));
514 assertThrowsWithMessage(Exception.class, "Duplicate items not allowed.", ()->x.postX6(new String[]{"1","1"}));
515 }
516
517
518
519
520
521 @Rest
522 public static class F {
523 @RestOp
524 public String post(@FormData("*") JsonMap m) {
525 return m.toString();
526 }
527 }
528
529 @Remote
530 public interface F1 {
531 @RemoteOp(path="/") String postX1(@FormData("x") @Schema(minl=2,maxl=3) String b);
532 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(cf="pipes",items=@Items(minl=2,maxl=3)) String...b);
533 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(e={"foo"}) String b);
534 @RemoteOp(path="/") String postX4(@FormData("x") @Schema(cf="pipes",items=@Items(e={"foo"})) String...b);
535 @RemoteOp(path="/") String postX5(@FormData("x") @Schema(p="foo\\d{1,3}") String b);
536 @RemoteOp(path="/") String postX6(@FormData("x") @Schema(cf="pipes",items=@Items(p="foo\\d{1,3}")) String...b);
537 }
538
539 @Test void f01_minl_maxl_enum_pattern() {
540 var x = remote(F.class,F1.class);
541 assertEquals("{x:'12'}",x.postX1("12"));
542 assertEquals("{x:'123'}",x.postX1("123"));
543 assertThrowsWithMessage(Exception.class, "Minimum length of value not met.", ()->x.postX1("1"));
544 assertThrowsWithMessage(Exception.class, "Maximum length of value exceeded.", ()->x.postX1("1234"));
545 assertEquals("{}",x.postX1(null));
546 assertEquals("{x:'12|34'}",x.postX2("12","34"));
547 assertEquals("{x:'123|456'}",x.postX2("123","456"));
548 assertThrowsWithMessage(Exception.class, "Minimum length of value not met.", ()->x.postX2("1","2"));
549 assertThrowsWithMessage(Exception.class, "Maximum length of value exceeded.", ()->x.postX2("1234","5678"));
550 assertEquals("{x:'12|null'}",x.postX2("12",null));
551 assertEquals("{x:'foo'}",x.postX3("foo"));
552 assertThrowsWithMessage(Exception.class, "Value does not match one of the expected values. Must be one of the following: foo", ()->x.postX3("bar"));
553 assertEquals("{}",x.postX3(null));
554 assertEquals("{x:'foo'}",x.postX4("foo"));
555 assertThrowsWithMessage(Exception.class, "Value does not match one of the expected values. Must be one of the following: foo", ()->x.postX4("bar"));
556 assertEquals("{x:null}",x.postX4((String)null));
557 assertEquals("{x:'foo123'}",x.postX5("foo123"));
558 assertThrowsWithMessage(Exception.class, "Value does not match expected pattern. Must match pattern: foo\\d{1,3}", ()->x.postX5("bar"));
559 assertEquals("{}",x.postX5(null));
560 assertEquals("{x:'foo123'}",x.postX6("foo123"));
561 assertThrowsWithMessage(Exception.class, "Value does not match expected pattern. Must match pattern: foo\\d{1,3}", ()->x.postX6("foo"));
562 assertEquals("{x:null}",x.postX6((String)null));
563 }
564
565
566
567
568
569 @Rest
570 public static class G {
571 @RestOp
572 public String post(@FormData("*") JsonMap m) {
573 return m.toString();
574 }
575 }
576
577 @Remote
578 public interface G1 {
579 @RemoteOp(path="/") String postX1(@FormData("x") @Schema(mo="2") int b);
580 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(mo="2") short b);
581 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(mo="2") long b);
582 @RemoteOp(path="/") String postX4(@FormData("x") @Schema(mo="2") float b);
583 @RemoteOp(path="/") String postX5(@FormData("x") @Schema(mo="2") double b);
584 @RemoteOp(path="/") String postX6(@FormData("x") @Schema(mo="2") byte b);
585 @RemoteOp(path="/") String postX7(@FormData("x") @Schema(mo="2") AtomicInteger b);
586 @RemoteOp(path="/") String postX8(@FormData("x") @Schema(mo="2") BigDecimal b);
587 @RemoteOp(path="/") String postX9(@FormData("x") @Schema(mo="2") Integer b);
588 @RemoteOp(path="/") String postX10(@FormData("x") @Schema(mo="2") Short b);
589 @RemoteOp(path="/") String postX11(@FormData("x") @Schema(mo="2") Long b);
590 @RemoteOp(path="/") String postX12(@FormData("x") @Schema(mo="2") Float b);
591 @RemoteOp(path="/") String postX13(@FormData("x") @Schema(mo="2") Double b);
592 @RemoteOp(path="/") String postX14(@FormData("x") @Schema(mo="2") Byte b);
593 }
594
595 @Test void g01_multipleOf() {
596 var x = remote(G.class,G1.class);
597 assertEquals("{x:'4'}",x.postX1(4));
598 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX1(5));
599 assertEquals("{x:'4'}",x.postX2((short)4));
600 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX2((short)5));
601 assertEquals("{x:'4'}",x.postX3(4));
602 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX3(5));
603 assertEquals("{x:'4.0'}",x.postX4(4));
604 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX4(5));
605 assertEquals("{x:'4.0'}",x.postX5(4));
606 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX5(5));
607 assertEquals("{x:'4'}",x.postX6((byte)4));
608 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX6((byte)5));
609 assertEquals("{x:'4'}",x.postX7(new AtomicInteger(4)));
610 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX7(new AtomicInteger(5)));
611 assertEquals("{x:'4'}",x.postX8(new BigDecimal(4)));
612 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX8(new BigDecimal(5)));
613 assertEquals("{x:'4'}",x.postX9(4));
614 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX9(5));
615 assertEquals("{x:'4'}",x.postX10((short)4));
616 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX10((short)5));
617 assertEquals("{x:'4'}",x.postX11(4L));
618 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX11(5L));
619 assertEquals("{x:'4.0'}",x.postX12(4f));
620 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX12(5f));
621 assertEquals("{x:'4.0'}",x.postX13(4d));
622 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX13(5d));
623 assertEquals("{x:'4'}",x.postX14((byte)4));
624 assertThrowsWithMessage(Exception.class, "Multiple-of not met.", ()->x.postX14((byte)5));
625 }
626
627
628
629
630
631 @Rest
632 public static class H {
633 @RestOp
634 public String post(@FormData("*") JsonMap m) {
635 return m.toString();
636 }
637 }
638
639 @Remote
640 public interface H1 {
641 @RemoteOp(path="/") String postX1(@FormData("x") String b);
642 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(r=false) String b);
643 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(r=true) String b);
644 }
645
646 @Test void h01_required() {
647 var x = remote(H.class,H1.class);
648 assertEquals("{}",x.postX1(null));
649 assertEquals("{}",x.postX2(null));
650 assertEquals("{x:'1'}",x.postX3("1"));
651 assertThrowsWithMessage(Exception.class, "Required value not provided.", ()->x.postX3(null));
652 }
653
654
655
656
657
658 @Rest
659 public static class I {
660 @RestOp
661 public String post(@FormData("*") JsonMap m) {
662 return m.toString();
663 }
664 }
665
666 @Remote
667 public interface I1 {
668 @RemoteOp(path="/") String postX1(@FormData("x") @Schema(aev=true) String b);
669 @RemoteOp(path="/") String postX2(@FormData("x") @Schema(aev=true,sie=false) String b);
670 @RemoteOp(path="/") String postX3(@FormData("x") @Schema(sie=true) String b);
671 }
672
673 @Test void i01_skipIfEmpty() {
674 var x = remote(I.class,I1.class);
675 assertEquals("{x:''}",x.postX1(""));
676 assertEquals("{x:''}",x.postX2(""));
677 assertEquals("{}",x.postX3(""));
678 }
679
680
681
682
683
684 @Rest
685 public static class J {
686 @RestOp
687 public String post(@FormData("*") JsonMap m) {
688 return m.toString();
689 }
690 }
691
692 @Remote
693 public interface J1 {
694 @RemoteOp(path="/") String postX1(@FormData(name="x",serializer=FakeWriterSerializer.X.class) String b);
695 }
696
697 @Test void j01_serializer() {
698 var x = remote(J.class,J1.class);
699 assertEquals("{x:'xXx'}",x.postX1("X"));
700 }
701
702
703
704
705
706 @Rest(parsers=UrlEncodingParser.class)
707 public static class K {
708 @RestOp
709 public String post(RestRequest req) throws Exception {
710 return req.getFormParams().toString();
711 }
712 }
713
714
715
716
717
718 @Remote(path="/")
719 public interface K1 {
720 @RemoteOp(path="/") String postX1(@Request K1a rb);
721 @RemoteOp(path="/") String postX2(@Request(serializer=FakeWriterSerializer.X.class) K1a rb);
722 }
723
724 public static class K1a {
725 @FormData public String getA() { return "a1"; }
726 @FormData("b") public String getX1() { return "b1"; }
727 @FormData("c") public String getX2() { return "c1"; }
728 @FormData("e") @Schema(aev=true) public String getX4() { return ""; }
729 @FormData("f") public String getX5() { return null; }
730 @FormData("g") public String getX6() { return "true"; }
731 @FormData("h") public String getX7() { return "123"; }
732 @FormData("i1") @Schema(sie=true) public String getX8() { return "foo"; }
733 @FormData("i2") @Schema(sie=true) public String getX9() { return ""; }
734 @FormData("i3") @Schema(sie=true) public String getX10() { return null; }
735 }
736
737 @Test void k01_requestBean_simpleVals() {
738 var x1 = remote(K.class,K1.class);
739 var x2 = client(K.class).partSerializer(UonSerializer.class).build().getRemote(K1.class);
740 assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'true',h:'123',i1:'foo'}",x1.postX1(new K1a()));
741 assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'\\'true\\'',h:'\\'123\\'',i1:'foo'}",x2.postX1(new K1a()));
742 assertEquals("{a:'xa1x',b:'xb1x',c:'xc1x',e:'xx',g:'xtruex',h:'x123x',i1:'xfoox'}",x2.postX2(new K1a()));
743 }
744
745
746
747
748
749 @Remote(path="/")
750 public interface K2 {
751 @RemoteOp(path="/") String postX1(@Request K2a rb);
752 @RemoteOp(path="/") String postX2(@Request(serializer=FakeWriterSerializer.X.class) K2a rb);
753 }
754
755 public static class K2a {
756 @FormData public Map<String,Object> getA() { return CollectionUtils.mapBuilder(String.class,Object.class).add("a1","v1").add("a2",123).add("a3",null).add("a4","").build(); }
757 @FormData("*") public Map<String,Object> getB() { return map("b1","true","b2","123","b3","null"); }
758 @FormData("*") @Schema(aev=true) public Map<String,Object> getC() { return CollectionUtils.mapBuilder(String.class,Object.class).add("c1","v1").add("c2",123).add("c3",null).add("c4","").build(); }
759 @FormData("*") public Map<String,Object> getD() { return null; }
760 }
761
762 @Test void k02_requestBean_maps() {
763 var x1 = remote(K.class,K2.class);
764 var x2 = client(K.class).partSerializer(UonSerializer.class).build().getRemote(K2.class);
765 assertEquals("{a:'a1=v1,a2=123,a3=null,a4=',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:''}",x1.postX1(new K2a()));
766 assertEquals("{a:'(a1=v1,a2=123,a3=null,a4=\\'\\')',b1:'\\'true\\'',b2:'\\'123\\'',b3:'\\'null\\'',c1:'v1',c2:'123',c4:''}",x2.postX1(new K2a()));
767 assertEquals("{a:'x{a1=v1, a2=123, a3=null, a4=}x',b1:'xtruex',b2:'x123x',b3:'xnullx',c1:'xv1x',c2:'x123x',c4:'xx'}",x2.postX2(new K2a()));
768 }
769
770
771
772
773
774 @Remote(path="/")
775 public interface K3 {
776 @RemoteOp(path="/") String postX1(@Request K3a rb);
777 @RemoteOp(path="/") String postX2(@Request(serializer=FakeWriterSerializer.X.class) K3a rb);
778 }
779
780 public static class K3a {
781 @FormData public PartList getA() { return parts("a1","v1","a2","123","a3",null,"a4",""); }
782 @FormData("*") public PartList getB() { return parts("b1","true","b2","123","b3","null"); }
783 @FormData("*") public PartList getC() { return parts("c1","v1","c2","123","c3",null,"c4",""); }
784 @FormData("*") public PartList getD() { return null; }
785 @FormData public NameValuePair[] getE() { return parts("e1","v1","e2","123","e3",null,"e4","").getAll(); }
786 }
787
788 @Test void k03_requestBean_nameValuePairs() {
789 var x1 = remote(K.class,K3.class);
790 var x2 = client(K.class).partSerializer(UonSerializer.class).build().getRemote(K3.class);
791 assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x1.postX1(new K3a()));
792 assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x2.postX1(new K3a()));
793 assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x2.postX2(new K3a()));
794 }
795
796
797
798
799
800 @Remote(path="/")
801 public interface K4 {
802 String post(@Request C04_Bean rb);
803 }
804
805 public static class C04_Bean {
806 @FormData("*") public StringBuilder getA() { return new StringBuilder("foo=bar&baz=qux"); }
807 }
808
809 @Test void k04_requestBean_charSequence() {
810 var x = remote(K.class,K4.class);
811 assertEquals("{foo:'bar',baz:'qux'}",x.post(new C04_Bean()));
812 }
813
814
815
816
817
818 @Remote(path="/")
819 public interface K5 {
820 String post(@Request K5a rb);
821 }
822
823 public static class K5a {
824 @FormData("*") public Reader getA() { return reader("foo=bar&baz=qux"); }
825 }
826
827 @Test void k05_requestBean_reader() {
828 var x = remote(K.class,K5.class);
829 assertEquals("{foo:'bar',baz:'qux'}",x.post(new K5a()));
830 }
831
832
833
834
835
836 @Remote(path="/")
837 public interface K6 {
838 @RemoteOp(path="/") String postX1(@Request K6a rb);
839 @RemoteOp(path="/") String postX2(@Request(serializer=FakeWriterSerializer.X.class) K6a rb);
840 }
841
842 public static class K6a {
843 @FormData public List<Object> getA() { return alist("foo","","true","123","null",true,123,null); }
844 @FormData("b") public List<Object> getX1() { return alist("foo","","true","123","null",true,123,null); }
845 @FormData(name="c",serializer=FakeWriterSerializer.X.class) public List<Object> getX2() { return alist("foo","","true","123","null",true,123,null); }
846 @FormData("d") @Schema(aev=true) public List<Object> getX3() { return alist(); }
847 @FormData("e") public List<Object> getX4() { return null; }
848 @FormData("f") public Object[] getX5() { return new Object[]{"foo","","true","123","null",true,123,null}; }
849 @FormData(name="g",serializer=FakeWriterSerializer.X.class) public Object[] getX6() { return new Object[]{"foo","","true","123","null",true,123,null}; }
850 @FormData("h") @Schema(aev=true) public Object[] getX7() { return new Object[]{}; }
851 @FormData("i") public Object[] getX8() { return null; }
852 }
853
854 @Test void k06_requestBean_collections() {
855 var x1 = remote(K.class,K6.class);
856 var x2 = client(K.class).partSerializer(UonSerializer.class).build().getRemote(K6.class);
857 assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}", x1.postX1(new K6a()));
858 assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}", x2.postX1(new K6a()));
859 assertEquals("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}", x2.postX2(new K6a()));
860 }
861
862
863
864
865
866 private static NameValuePair part(String name, Object val) {
867 return basicPart(name,val);
868 }
869
870 private static PartList parts(String...pairs) {
871 return partList(pairs);
872 }
873
874 private static RestClient.Builder client(Class<?> c) {
875 return MockRestClient.create(c);
876 }
877
878 private static <T> T remote(Class<?> rest,Class<T> t) {
879 return MockRestClient.build(rest).getRemote(t);
880 }
881 }