xref: /aosp_15_r20/external/json-schema-validator/src/test/java/com/networknt/schema/Issue575Test.java (revision 78c4dd6aa35290980cdcd1623a7e337e8d021c7c)
1 package com.networknt.schema;
2 
3 import com.fasterxml.jackson.core.JsonProcessingException;
4 import com.fasterxml.jackson.databind.ObjectMapper;
5 import org.junit.jupiter.api.Assertions;
6 import org.junit.jupiter.api.BeforeAll;
7 import org.junit.jupiter.params.ParameterizedTest;
8 import org.junit.jupiter.params.provider.Arguments;
9 import org.junit.jupiter.params.provider.MethodSource;
10 
11 import java.io.InputStream;
12 import java.util.Set;
13 import java.util.stream.Stream;
14 
15 /**
16  * This project uses a dependency (com.ethlo.time:itu) to validate time representations. Version 1.51 of this library
17  * has a problem dealing with certain time zones having a negative offset; for example "-2:30" (Newfoundland time, NDT).
18  * Moving to version 1.7.0 of this library resolves the issue.
19  *
20  * This test class confirms that valid negative offsets do not result in a JSON validation error if the ITU library is
21  * updated to version 1.7.0 or later.
22  */
23 public class Issue575Test {
24     private static JsonSchema schema;
25 
26     @BeforeAll
init()27     static void init() {
28         JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909);
29         String schemaPath = "/schema/issue575-2019-09.json";
30         InputStream schemaInputStream = Issue575Test.class.getResourceAsStream(schemaPath);
31         schema = factory.getSchema(schemaInputStream);
32     }
33 
validTimeZoneOffsets()34     public static Stream<Arguments> validTimeZoneOffsets() {
35         String json1 = "{\"testDateTime\":\"2022-05-18T08:27:53-05:00\"}";         // America/New_York
36         String json2 = "{\"testDateTime\":\"2022-05-18T08:27:53-04:00\"}";         // America/New_York (DST)
37         String json3 = "{\"testDateTime\":\"2022-05-18T08:27:53-03:30\"}";         // America/St_Johns
38         String json4 = "{\"testDateTime\":\"2022-05-18T08:27:53-02:30\"}";         // America/St_Johns (DST)
39         String json5 = "{\"testDateTime\":\"2022-05-18T08:27:53+02:00\"}";         // Africa/Cairo
40         String json6 = "{\"testDateTime\":\"2022-05-18T08:27:53+03:30\"}";         // Asia/Tehran
41         String json7 = "{\"testDateTime\":\"2022-05-18T08:27:53+04:30\"}";         // Asia/Tehran (DST)
42         String json8 = "{\"testDateTime\":\"2022-05-18T08:27:53+04:00\"}";         // Asia/Dubai
43         String json9 = "{\"testDateTime\":\"2022-05-18T08:27:53+05:00\"}";         // Indian/Maldives
44         String json10 = "{\"testDateTime\":\"2022-05-18T08:27:53+05:30\"}";        // Asia/Kolkata
45         String json11 = "{\"testDateTime\":\"2022-05-18T08:27:53+10:00\"}";        // Australia/Sydney
46         String json12 = "{\"testDateTime\":\"2022-05-18T08:27:53+11:00\"}";        // Australia/Sydney (DST)
47         String json13 = "{\"testDateTime\":\"2022-05-18T08:27:53+14:00\"}";        // Pacific/Kiritimati
48         String json14 = "{\"testDateTime\":\"2022-05-18T18:45:32.123-05:00\"}";    // America/New_York
49         String json15 = "{\"testDateTime\":\"2022-05-18T18:45:32.123456-05:00\"}"; // America/New_York
50         String json16 = "{\"testDateTime\":\"2022-05-18T08:27:53Z\"}";             // UTC
51         String json17 = "{\"testDateTime\":\"2022-05-18T08:27:53+00:00\"}";        // UTC
52 
53         return Stream.of(
54                 Arguments.of(json1),
55                 Arguments.of(json2),
56                 Arguments.of(json3),
57                 Arguments.of(json4),
58                 Arguments.of(json5),
59                 Arguments.of(json6),
60                 Arguments.of(json7),
61                 Arguments.of(json8),
62                 Arguments.of(json9),
63                 Arguments.of(json10),
64                 Arguments.of(json11),
65                 Arguments.of(json12),
66                 Arguments.of(json13),
67                 Arguments.of(json14),
68                 Arguments.of(json15),
69                 Arguments.of(json16),
70                 Arguments.of(json17)
71         );
72     }
73 
74     /**
75      * Confirms that valid time zone offsets do not result in a JSON validation error.
76      *
77      * @param jsonObject a sample JSON payload to test
78      */
79     @ParameterizedTest
80     @MethodSource("validTimeZoneOffsets")
testValidTimeZoneOffsets(String jsonObject)81     void testValidTimeZoneOffsets(String jsonObject) throws JsonProcessingException {
82         Set<ValidationMessage> errors = schema.validate(new ObjectMapper().readTree(jsonObject));
83         Assertions.assertTrue(errors.isEmpty());
84     }
85 
invalidTimeRepresentations()86     public static Stream<Arguments> invalidTimeRepresentations() {
87         // Invalid JSON payload: 30 days in April
88         String json1 = "{\"testDateTime\":\"2022-04-31T08:27:53+05:00\"}";
89         // Invalid JSON payload: Invalid date/time separator
90         String json2 = "{\"testDateTime\":\"2022-05-18X08:27:53+05:00\"}";
91         // Invalid JSON payload: Time zone details are missing
92         String json3 = "{\"testDateTime\":\"2022-05-18T08:27:53\"}";
93         // Invalid JSON payload: seconds missing from time
94         String json4 = "{\"testDateTime\":\"2022-05-18T11:23Z\"}";
95         // Invalid JSON payload: Text instead of date-time value
96         String json5 = "{\"testDateTime\":\"Orlando\"}";
97         // Invalid JSON payload: A time zone offset of +23:00 is not valid
98         String json6 = "{\"testDateTime\":\"2022-05-18T08:27:53+23:00\"}";
99         // Invalid JSON payload: A time zone offset of -23:00 is not valid
100         String json7 = "{\"testDateTime\":\"2022-05-18T08:27:53-23:00\"}";
101         // Invalid JSON payload: com.ethlo.time:itu does not allow offset -00:00 (Valid per RFC3339 section 4.3. but prohibited in ISO-8601)
102         String json8 = "{\"testDateTime\":\"2022-05-18T08:27:53-00:00\"}";
103 
104         return Stream.of(
105                 Arguments.of(json1),
106                 Arguments.of(json2),
107                 Arguments.of(json3),
108                 Arguments.of(json4),
109                 Arguments.of(json5),
110                 Arguments.of(json6),
111                 Arguments.of(json7),
112                 Arguments.of(json8)
113         );
114     }
115 
116     /**
117      * Confirms that invalid time representations result in one or more a JSON validation errors.
118      *
119      * @param jsonObject a sample JSON payload to test
120      */
121     @ParameterizedTest
122     @MethodSource("invalidTimeRepresentations")
testInvalidTimeRepresentations(String jsonObject)123     void testInvalidTimeRepresentations(String jsonObject) throws JsonProcessingException {
124         Set<ValidationMessage> errors = schema.validate(new ObjectMapper().readTree(jsonObject), OutputFormat.DEFAULT, (executionContext, validationContext) -> {
125             executionContext.getExecutionConfig().setFormatAssertionsEnabled(true);
126         });
127         Assertions.assertFalse(errors.isEmpty());
128     }
129 }
130