Mercurial > hg > monetdb-java
comparison tests/UrlTester.java @ 834:5aa19bbed0d6 monetdbs
Comments and formatting
author | Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com> |
---|---|
date | Wed, 13 Dec 2023 15:39:47 +0100 (17 months ago) |
parents | 9f6fe96c0ead |
children | 839d76eeb4ae |
comparison
equal
deleted
inserted
replaced
813:a71afa48f269 | 834:5aa19bbed0d6 |
---|---|
3 import java.io.*; | 3 import java.io.*; |
4 import java.net.URISyntaxException; | 4 import java.net.URISyntaxException; |
5 import java.util.ArrayList; | 5 import java.util.ArrayList; |
6 | 6 |
7 public class UrlTester { | 7 public class UrlTester { |
8 final String filename; | 8 final String filename; |
9 final int verbose; | 9 final int verbose; |
10 final BufferedReader reader; | 10 final BufferedReader reader; |
11 int lineno = 0; | 11 int lineno = 0; |
12 int testCount = 0; | 12 int testCount = 0; |
13 Target target = null; | 13 Target target = null; |
14 Target.Validated validated = null; | 14 Target.Validated validated = null; |
15 | 15 |
16 public UrlTester(String filename, BufferedReader reader, int verbose) { | 16 public UrlTester(String filename, BufferedReader reader, int verbose) { |
17 this.filename = filename; | 17 this.filename = filename; |
18 this.verbose = verbose; | 18 this.verbose = verbose; |
19 this.reader = reader; | 19 this.reader = reader; |
20 } | 20 } |
21 | 21 |
22 public UrlTester(String filename, int verbose) throws IOException { | 22 public UrlTester(String filename, int verbose) throws IOException { |
23 this.filename = filename; | 23 this.filename = filename; |
24 this.verbose = verbose; | 24 this.verbose = verbose; |
25 this.reader = new BufferedReader(new FileReader(filename)); | 25 this.reader = new BufferedReader(new FileReader(filename)); |
26 } | 26 } |
27 | 27 |
28 public static void main(String[] args) throws IOException { | 28 public static void main(String[] args) throws IOException { |
29 ArrayList<String> filenames = new ArrayList<>(); | 29 ArrayList<String> filenames = new ArrayList<>(); |
30 int verbose = 0; | 30 int verbose = 0; |
31 for (String arg : args) { | 31 for (String arg : args) { |
32 switch (arg) { | 32 switch (arg) { |
33 case "-vvv": | 33 case "-vvv": |
34 verbose++; | 34 verbose++; |
35 case "-vv": | 35 case "-vv": |
36 verbose++; | 36 verbose++; |
37 case "-v": | 37 case "-v": |
38 verbose++; | 38 verbose++; |
39 break; | 39 break; |
40 case "-h": | 40 case "-h": |
41 case "--help": | 41 case "--help": |
42 exitUsage(null); | 42 exitUsage(null); |
43 break; | 43 break; |
44 default: | 44 default: |
45 if (!arg.startsWith("-")) { | 45 if (!arg.startsWith("-")) { |
46 filenames.add(arg); | 46 filenames.add(arg); |
47 } else { | 47 } else { |
48 exitUsage("Unexpected argument: " + arg); | 48 exitUsage("Unexpected argument: " + arg); |
49 } | 49 } |
50 break; | 50 break; |
51 } | 51 } |
52 } | 52 } |
53 | 53 |
54 runUnitTests(); | 54 runUnitTests(); |
55 | 55 |
56 try { | 56 try { |
57 if (filenames.isEmpty()) { | 57 if (filenames.isEmpty()) { |
58 runAllTests(); | 58 runAllTests(); |
59 } else { | 59 } else { |
60 for (String filename : filenames) { | 60 for (String filename : filenames) { |
61 new UrlTester(filename, verbose).run(); | 61 new UrlTester(filename, verbose).run(); |
62 } | 62 } |
63 } | 63 } |
64 } catch (Failure e) { | 64 } catch (Failure e) { |
65 System.err.println("Test failed: " + e.getMessage()); | 65 System.err.println("Test failed: " + e.getMessage()); |
66 System.exit(1); | 66 System.exit(1); |
67 } | 67 } |
68 } | 68 } |
69 | 69 |
70 private static void exitUsage(String message) { | 70 private static void exitUsage(String message) { |
71 if (message != null) { | 71 if (message != null) { |
72 System.err.println(message); | 72 System.err.println(message); |
73 } | 73 } |
74 System.err.println("Usage: UrlTester OPTIONS [FILENAME..]"); | 74 System.err.println("Usage: UrlTester OPTIONS [FILENAME..]"); |
75 System.err.println("Options:"); | 75 System.err.println("Options:"); |
76 System.err.println(" -v Be more verbose"); | 76 System.err.println(" -v Be more verbose"); |
77 System.err.println(" -h --help Show this help"); | 77 System.err.println(" -h --help Show this help"); |
78 int status = message == null ? 0 : 1; | 78 int status = message == null ? 0 : 1; |
79 System.exit(status); | 79 System.exit(status); |
80 } | 80 } |
81 | 81 |
82 public static UrlTester forResource(String resourceName, int verbose) throws FileNotFoundException { | 82 public static UrlTester forResource(String resourceName, int verbose) throws FileNotFoundException { |
83 InputStream stream = UrlTester.class.getResourceAsStream(resourceName); | 83 InputStream stream = UrlTester.class.getResourceAsStream(resourceName); |
84 if (stream == null) { | 84 if (stream == null) { |
85 throw new FileNotFoundException("Resource " + resourceName); | 85 throw new FileNotFoundException("Resource " + resourceName); |
86 } | 86 } |
87 BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); | 87 BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); |
88 return new UrlTester(resourceName, reader, verbose); | 88 return new UrlTester(resourceName, reader, verbose); |
89 } | 89 } |
90 | 90 |
91 public static void runAllTests() throws IOException, Failure { | 91 public static void runAllTests() throws IOException, Failure { |
92 runUnitTests(); | 92 runUnitTests(); |
93 UrlTester.forResource("/tests.md", 0).run(); | 93 UrlTester.forResource("/tests.md", 0).run(); |
94 UrlTester.forResource("/javaspecific.md", 0).run(); | 94 UrlTester.forResource("/javaspecific.md", 0).run(); |
95 } | 95 } |
96 | 96 |
97 public static void runUnitTests() { | 97 public static void runUnitTests() { |
98 testDefaults(); | 98 testDefaults(); |
99 testParameters(); | 99 testParameters(); |
100 } | 100 } |
101 | 101 |
102 private static void testDefaults() { | 102 private static void testDefaults() { |
103 Target target = new Target(); | 103 Target target = new Target(); |
104 | 104 |
105 for (Parameter parm : Parameter.values()) { | 105 for (Parameter parm : Parameter.values()) { |
106 Object expected = parm.getDefault(); | 106 Object expected = parm.getDefault(); |
107 if (expected == null) | 107 if (expected == null) |
108 continue; | 108 continue; |
109 Object actual = target.getObject(parm); | 109 Object actual = target.getObject(parm); |
110 if (!expected.equals(actual)) { | 110 if (!expected.equals(actual)) { |
111 throw new RuntimeException("Default for " + parm.name + " expected to be <" + expected + "> but is <" + actual + ">"); | 111 throw new RuntimeException("Default for " + parm.name + " expected to be <" + expected + "> but is <" + actual + ">"); |
112 } | 112 } |
113 } | 113 } |
114 } | 114 } |
115 | 115 |
116 private static void testParameters() { | 116 private static void testParameters() { |
117 for (Parameter parm : Parameter.values()) { | 117 for (Parameter parm : Parameter.values()) { |
118 Parameter found = Parameter.forName(parm.name); | 118 Parameter found = Parameter.forName(parm.name); |
119 if (parm != found) { | 119 if (parm != found) { |
120 String foundStr = found != null ? found.name : "null"; | 120 String foundStr = found != null ? found.name : "null"; |
121 throw new RuntimeException("Looking up <" + parm.name + ">, found <" + foundStr); | 121 throw new RuntimeException("Looking up <" + parm.name + ">, found <" + foundStr); |
122 } | 122 } |
123 } | 123 } |
124 } | 124 } |
125 | 125 |
126 public void run() throws Failure, IOException { | 126 public void run() throws Failure, IOException { |
127 try { | 127 try { |
128 processFile(); | 128 processFile(); |
129 } catch (Failure e) { | 129 } catch (Failure e) { |
130 if (e.getFilename() == null) { | 130 if (e.getFilename() == null) { |
131 e.setFilename(filename); | 131 e.setFilename(filename); |
132 e.setLineno(lineno); | 132 e.setLineno(lineno); |
133 throw e; | 133 throw e; |
134 } | 134 } |
135 } | 135 } |
136 } | 136 } |
137 | 137 |
138 private void processFile() throws IOException, Failure { | 138 private void processFile() throws IOException, Failure { |
139 while (true) { | 139 while (true) { |
140 String line = reader.readLine(); | 140 String line = reader.readLine(); |
141 if (line == null) | 141 if (line == null) |
142 break; | 142 break; |
143 lineno++; | 143 lineno++; |
144 processLine(line); | 144 processLine(line); |
145 } | 145 } |
146 if (verbose >= 1) { | 146 if (verbose >= 1) { |
147 System.out.println(); | 147 System.out.println(); |
148 System.out.println("Ran " + testCount + " tests in " + lineno + " lines"); | 148 System.out.println("Ran " + testCount + " tests in " + lineno + " lines"); |
149 } | 149 } |
150 } | 150 } |
151 | 151 |
152 private void processLine(String line) throws Failure { | 152 private void processLine(String line) throws Failure { |
153 line = line.replaceFirst("\\s+$", ""); // remove trailing | 153 line = line.replaceFirst("\\s+$", ""); // remove trailing |
154 if (target == null && line.equals("```test")) { | 154 if (target == null && line.equals("```test")) { |
155 if (verbose >= 2) { | 155 if (verbose >= 2) { |
156 if (testCount > 0) { | 156 if (testCount > 0) { |
157 System.out.println(); | 157 System.out.println(); |
158 } | 158 } |
159 System.out.println("\u25B6 " + filename + ":" + lineno); | 159 System.out.println("\u25B6 " + filename + ":" + lineno); |
160 } | 160 } |
161 target = new Target(); | 161 target = new Target(); |
162 testCount++; | 162 testCount++; |
163 return; | 163 return; |
164 } | 164 } |
165 if (target != null) { | 165 if (target != null) { |
166 if (line.equals("```")) { | 166 if (line.equals("```")) { |
167 stopProcessing(); | 167 stopProcessing(); |
168 return; | 168 return; |
169 } | 169 } |
170 handleCommand(line); | 170 handleCommand(line); |
171 } | 171 } |
172 } | 172 } |
173 | 173 |
174 private void stopProcessing() { | 174 private void stopProcessing() { |
175 target = null; | 175 target = null; |
176 validated = null; | 176 validated = null; |
177 } | 177 } |
178 | 178 |
179 private void handleCommand(String line) throws Failure { | 179 private void handleCommand(String line) throws Failure { |
180 if (verbose >= 3) { | 180 if (verbose >= 3) { |
181 System.out.println(line); | 181 System.out.println(line); |
182 } | 182 } |
183 if (line.isEmpty()) | 183 if (line.isEmpty()) |
184 return; | 184 return; |
185 | 185 |
186 String[] parts = line.split("\\s+", 2); | 186 String[] parts = line.split("\\s+", 2); |
187 String command = parts[0]; | 187 String command = parts[0]; |
188 switch (command.toUpperCase()) { | 188 switch (command.toUpperCase()) { |
189 case "ONLY": | 189 case "ONLY": |
190 handleOnly(true, parts[1]); | 190 handleOnly(true, parts[1]); |
191 return; | 191 return; |
192 case "NOT": | 192 case "NOT": |
193 handleOnly(false, parts[1]); | 193 handleOnly(false, parts[1]); |
194 return; | 194 return; |
195 case "PARSE": | 195 case "PARSE": |
196 handleParse(parts[1], null); | 196 handleParse(parts[1], null); |
197 return; | 197 return; |
198 case "ACCEPT": | 198 case "ACCEPT": |
199 handleParse(parts[1], true); | 199 handleParse(parts[1], true); |
200 return; | 200 return; |
201 case "REJECT": | 201 case "REJECT": |
202 handleParse(parts[1], false); | 202 handleParse(parts[1], false); |
203 return; | 203 return; |
204 case "SET": | 204 case "SET": |
205 handleSet(parts[1]); | 205 handleSet(parts[1]); |
206 return; | 206 return; |
207 case "EXPECT": | 207 case "EXPECT": |
208 handleExpect(parts[1]); | 208 handleExpect(parts[1]); |
209 return; | 209 return; |
210 default: | 210 default: |
211 throw new Failure("Unexpected command: " + command); | 211 throw new Failure("Unexpected command: " + command); |
212 } | 212 } |
213 | 213 |
214 } | 214 } |
215 | 215 |
216 private void handleOnly(boolean mustBePresent, String rest) throws Failure { | 216 private void handleOnly(boolean mustBePresent, String rest) throws Failure { |
217 boolean found = false; | 217 boolean found = false; |
218 for (String part : rest.split("\\s+")) { | 218 for (String part : rest.split("\\s+")) { |
219 if (part.equals("jdbc")) { | 219 if (part.equals("jdbc")) { |
220 found = true; | 220 found = true; |
221 break; | 221 break; |
222 } | 222 } |
223 } | 223 } |
224 if (found != mustBePresent) { | 224 if (found != mustBePresent) { |
225 // do not further process this block | 225 // do not further process this block |
226 stopProcessing(); | 226 stopProcessing(); |
227 } | 227 } |
228 } | 228 } |
229 | 229 |
230 private int findEqualSign(String rest) throws Failure { | 230 private int findEqualSign(String rest) throws Failure { |
231 int index = rest.indexOf('='); | 231 int index = rest.indexOf('='); |
232 if (index < -1) | 232 if (index < -1) |
233 throw new Failure("Expected to find a '='"); | 233 throw new Failure("Expected to find a '='"); |
234 return index; | 234 return index; |
235 } | 235 } |
236 | 236 |
237 private String splitKey(String rest) throws Failure { | 237 private String splitKey(String rest) throws Failure { |
238 int index = findEqualSign(rest); | 238 int index = findEqualSign(rest); |
239 return rest.substring(0, index); | 239 return rest.substring(0, index); |
240 } | 240 } |
241 | 241 |
242 private String splitValue(String rest) throws Failure { | 242 private String splitValue(String rest) throws Failure { |
243 int index = findEqualSign(rest); | 243 int index = findEqualSign(rest); |
244 return rest.substring(index + 1); | 244 return rest.substring(index + 1); |
245 } | 245 } |
246 | 246 |
247 private void handleSet(String rest) throws Failure { | 247 private void handleSet(String rest) throws Failure { |
248 validated = null; | 248 validated = null; |
249 String key = splitKey(rest); | 249 String key = splitKey(rest); |
250 String value = splitValue(rest); | 250 String value = splitValue(rest); |
251 | 251 |
252 try { | 252 try { |
253 target.setString(key, value); | 253 target.setString(key, value); |
254 } catch (ValidationError e) { | 254 } catch (ValidationError e) { |
255 throw new Failure(e.getMessage()); | 255 throw new Failure(e.getMessage()); |
256 } | 256 } |
257 } | 257 } |
258 | 258 |
259 private void handleParse(String rest, Boolean shouldSucceed) throws Failure { | 259 private void handleParse(String rest, Boolean shouldSucceed) throws Failure { |
260 URISyntaxException parseError = null; | 260 URISyntaxException parseError = null; |
261 ValidationError validationError = null; | 261 ValidationError validationError = null; |
262 | 262 |
263 validated = null; | 263 validated = null; |
264 try { | 264 try { |
265 target.barrier(); | 265 target.barrier(); |
266 MonetUrlParser.parse(target, rest); | 266 MonetUrlParser.parse(target, rest); |
267 } catch (URISyntaxException e) { | 267 } catch (URISyntaxException e) { |
268 parseError = e; | 268 parseError = e; |
269 } catch (ValidationError e) { | 269 } catch (ValidationError e) { |
270 validationError = e; | 270 validationError = e; |
271 } | 271 } |
272 | 272 |
273 if (parseError == null && validationError == null) { | 273 if (parseError == null && validationError == null) { |
274 try { | 274 try { |
275 tryValidate(); | 275 tryValidate(); |
276 } catch (ValidationError e) { | 276 } catch (ValidationError e) { |
277 validationError = e; | 277 validationError = e; |
278 } | 278 } |
279 } | 279 } |
280 | 280 |
281 if (shouldSucceed == Boolean.FALSE) { | 281 if (shouldSucceed == Boolean.FALSE) { |
282 if (parseError != null || validationError != null) | 282 if (parseError != null || validationError != null) |
283 return; // happy | 283 return; // happy |
284 else | 284 else |
285 throw new Failure("URL unexpectedly parsed and validated"); | 285 throw new Failure("URL unexpectedly parsed and validated"); |
286 } | 286 } |
287 | 287 |
288 if (parseError != null) | 288 if (parseError != null) |
289 throw new Failure("Parse error: " + parseError); | 289 throw new Failure("Parse error: " + parseError); |
290 if (validationError != null && shouldSucceed == Boolean.TRUE) | 290 if (validationError != null && shouldSucceed == Boolean.TRUE) |
291 throw new Failure("Validation error: " + validationError); | 291 throw new Failure("Validation error: " + validationError); |
292 } | 292 } |
293 | 293 |
294 private void handleExpect(String rest) throws Failure { | 294 private void handleExpect(String rest) throws Failure { |
295 String key = splitKey(rest); | 295 String key = splitKey(rest); |
296 String expectedString = splitValue(rest); | 296 String expectedString = splitValue(rest); |
297 | 297 |
298 Object actual = null; | 298 Object actual = null; |
299 try { | 299 try { |
300 actual = extract(key); | 300 actual = extract(key); |
301 } catch (ValidationError e) { | 301 } catch (ValidationError e) { |
302 throw new Failure(e.getMessage()); | 302 throw new Failure(e.getMessage()); |
303 } | 303 } |
304 | 304 |
305 Object expected; | 305 Object expected; |
306 try { | 306 try { |
307 if (actual instanceof Boolean) | 307 if (actual instanceof Boolean) |
308 expected = ParameterType.Bool.parse(key, expectedString); | 308 expected = ParameterType.Bool.parse(key, expectedString); |
309 else if (actual instanceof Integer) | 309 else if (actual instanceof Integer) |
310 expected = ParameterType.Int.parse(key, expectedString); | 310 expected = ParameterType.Int.parse(key, expectedString); |
311 else | 311 else |
312 expected = expectedString; | 312 expected = expectedString; |
313 } catch (ValidationError e) { | 313 } catch (ValidationError e) { |
314 String typ = actual.getClass().getName(); | 314 String typ = actual.getClass().getName(); |
315 throw new Failure("Cannot convert expected value <" + expectedString + "> to " + typ + ": " + e.getMessage()); | 315 throw new Failure("Cannot convert expected value <" + expectedString + "> to " + typ + ": " + e.getMessage()); |
316 } | 316 } |
317 | 317 |
318 if (actual.equals(expected)) | 318 if (actual.equals(expected)) |
319 return; | 319 return; |
320 throw new Failure("Expected " + key + "=<" + expectedString + ">, found <" + actual + ">"); | 320 throw new Failure("Expected " + key + "=<" + expectedString + ">, found <" + actual + ">"); |
321 } | 321 } |
322 | 322 |
323 private Target.Validated tryValidate() throws ValidationError { | 323 private Target.Validated tryValidate() throws ValidationError { |
324 if (validated == null) | 324 if (validated == null) |
325 validated = target.validate(); | 325 validated = target.validate(); |
326 return validated; | 326 return validated; |
327 } | 327 } |
328 | 328 |
329 private Object extract(String key) throws ValidationError, Failure { | 329 private Object extract(String key) throws ValidationError, Failure { |
330 switch (key) { | 330 switch (key) { |
331 case "valid": | 331 case "valid": |
332 try { | 332 try { |
333 tryValidate(); | 333 tryValidate(); |
334 } catch (ValidationError e) { | 334 } catch (ValidationError e) { |
335 return Boolean.FALSE; | 335 return Boolean.FALSE; |
336 } | 336 } |
337 return Boolean.TRUE; | 337 return Boolean.TRUE; |
338 | 338 |
339 case "connect_scan": | 339 case "connect_scan": |
340 return tryValidate().connectScan(); | 340 return tryValidate().connectScan(); |
341 case "connect_port": | 341 case "connect_port": |
342 return tryValidate().connectPort(); | 342 return tryValidate().connectPort(); |
343 case "connect_unix": | 343 case "connect_unix": |
344 return tryValidate().connectUnix(); | 344 return tryValidate().connectUnix(); |
345 case "connect_tcp": | 345 case "connect_tcp": |
346 return tryValidate().connectTcp(); | 346 return tryValidate().connectTcp(); |
347 case "connect_tls_verify": | 347 case "connect_tls_verify": |
348 switch (tryValidate().connectVerify()) { | 348 switch (tryValidate().connectVerify()) { |
349 case None: | 349 case None: |
350 return ""; | 350 return ""; |
351 case Cert: | 351 case Cert: |
352 return "cert"; | 352 return "cert"; |
353 case Hash: | 353 case Hash: |
354 return "hash"; | 354 return "hash"; |
355 case System: | 355 case System: |
356 return "system"; | 356 return "system"; |
357 default: | 357 default: |
358 throw new IllegalStateException("unreachable"); | 358 throw new IllegalStateException("unreachable"); |
359 } | 359 } |
360 case "connect_certhash_digits": | 360 case "connect_certhash_digits": |
361 return tryValidate().connectCertHashDigits(); | 361 return tryValidate().connectCertHashDigits(); |
362 case "connect_binary": | 362 case "connect_binary": |
363 return tryValidate().connectBinary(); | 363 return tryValidate().connectBinary(); |
364 case "connect_clientkey": | 364 case "connect_clientkey": |
365 return tryValidate().connectClientKey(); | 365 return tryValidate().connectClientKey(); |
366 case "connect_clientcert": | 366 case "connect_clientcert": |
367 return tryValidate().connectClientCert(); | 367 return tryValidate().connectClientCert(); |
368 | 368 |
369 default: | 369 default: |
370 Parameter parm = Parameter.forName(key); | 370 Parameter parm = Parameter.forName(key); |
371 if (parm != null) | 371 if (parm != null) |
372 return target.getObject(parm); | 372 return target.getObject(parm); |
373 else | 373 else |
374 throw new Failure("Unknown attribute: " + key); | 374 throw new Failure("Unknown attribute: " + key); |
375 } | 375 } |
376 } | 376 } |
377 | 377 |
378 public static class Failure extends Exception { | 378 public static class Failure extends Exception { |
379 private String filename = null; | 379 private String filename = null; |
380 private int lineno = -1; | 380 private int lineno = -1; |
381 | 381 |
382 public Failure(String message) { | 382 public Failure(String message) { |
383 super(message); | 383 super(message); |
384 } | 384 } |
385 | 385 |
386 @Override | 386 @Override |
387 public String getMessage() { | 387 public String getMessage() { |
388 StringBuilder buffer = new StringBuilder(); | 388 StringBuilder buffer = new StringBuilder(); |
389 if (filename != null) { | 389 if (filename != null) { |
390 buffer.append(filename).append(":"); | 390 buffer.append(filename).append(":"); |
391 if (lineno >= 0) | 391 if (lineno >= 0) |
392 buffer.append(lineno).append(":"); | 392 buffer.append(lineno).append(":"); |
393 } | 393 } |
394 buffer.append(super.getMessage()); | 394 buffer.append(super.getMessage()); |
395 return buffer.toString(); | 395 return buffer.toString(); |
396 } | 396 } |
397 | 397 |
398 public String getFilename() { | 398 public String getFilename() { |
399 return filename; | 399 return filename; |
400 } | 400 } |
401 | 401 |
402 public void setFilename(String filename) { | 402 public void setFilename(String filename) { |
403 this.filename = filename; | 403 this.filename = filename; |
404 } | 404 } |
405 | 405 |
406 public int getLineno() { | 406 public int getLineno() { |
407 return lineno; | 407 return lineno; |
408 } | 408 } |
409 | 409 |
410 public void setLineno(int lineno) { | 410 public void setLineno(int lineno) { |
411 this.lineno = lineno; | 411 this.lineno = lineno; |
412 } | 412 } |
413 } | 413 } |
414 } | 414 } |