Skip to content

Commit 335ff1d

Browse files
cursoragentsimbo1905
andcommitted
Refactor: Use @provide for schema generation
Co-authored-by: simbo1905 <[email protected]>
1 parent 42deea6 commit 335ff1d

File tree

1 file changed

+51
-62
lines changed

1 file changed

+51
-62
lines changed

json-java21-schema/src/test/java/io/github/simbo1905/json/schema/ITJsonSchemaExhaustiveTest.java

Lines changed: 51 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
import net.jqwik.api.ForAll;
1414
import net.jqwik.api.GenerationMode;
1515
import net.jqwik.api.Property;
16-
import net.jqwik.api.UseArbitraryProviders;
17-
import net.jqwik.api.providers.ArbitraryProvider;
18-
import net.jqwik.api.providers.SubtypeProvider;
19-
import net.jqwik.api.providers.TypeUsage;
16+
import net.jqwik.api.Provide;
2017

2118
import java.math.BigDecimal;
2219
import java.util.LinkedHashMap;
@@ -29,7 +26,6 @@
2926

3027
import static org.assertj.core.api.Assertions.assertThat;
3128

32-
@UseArbitraryProviders(ITJsonSchemaExhaustiveTest.SchemaArbitraryProvider.class)
3329
class ITJsonSchemaExhaustiveTest extends JsonSchemaLoggingConfig {
3430

3531
private static final Logger LOGGER = Logger.getLogger(io.github.simbo1905.json.schema.JsonSchema.class.getName());
@@ -45,7 +41,7 @@ class ITJsonSchemaExhaustiveTest extends JsonSchemaLoggingConfig {
4541
);
4642

4743
@Property(generation = GenerationMode.EXHAUSTIVE)
48-
void exhaustiveRoundTrip(@ForAll ITJsonSchemaExhaustiveTest.JsonSchema schema) {
44+
void exhaustiveRoundTrip(@ForAll("schemas") JsonSchema schema) {
4945
LOGGER.info(() -> "Executing exhaustiveRoundTrip property test");
5046

5147
final var schemaDescription = describeSchema(schema);
@@ -90,44 +86,44 @@ void exhaustiveRoundTrip(@ForAll ITJsonSchemaExhaustiveTest.JsonSchema schema) {
9086

9187
private static JsonValue buildCompliantDocument(JsonSchema schema) {
9288
return switch (schema) {
93-
case ObjectSchema(var properties) -> JsonObject.of(properties.stream()
94-
.collect(Collectors.toMap(
89+
case JsonSchema.ObjectSchema(var properties) -> JsonObject.of(properties.stream()
90+
.collect(Collectors.<JsonSchema.Property, String, JsonValue, LinkedHashMap<String, JsonValue>>toMap(
9591
JsonSchema.Property::name,
9692
property -> buildCompliantDocument(property.schema()),
9793
(left, right) -> left,
9894
LinkedHashMap::new
9995
)));
100-
case ArraySchema(var items) -> JsonArray.of(items.stream()
96+
case JsonSchema.ArraySchema(var items) -> JsonArray.of(items.stream()
10197
.map(ITJsonSchemaExhaustiveTest::buildCompliantDocument)
10298
.toList());
103-
case StringSchema ignored -> JsonString.of("valid");
104-
case NumberSchema ignored -> JsonNumber.of(BigDecimal.ONE);
105-
case BooleanSchema ignored -> JsonBoolean.of(true);
106-
case NullSchema ignored -> JsonNull.of();
99+
case JsonSchema.StringSchema ignored -> JsonString.of("valid");
100+
case JsonSchema.NumberSchema ignored -> JsonNumber.of(BigDecimal.ONE);
101+
case JsonSchema.BooleanSchema ignored -> JsonBoolean.of(true);
102+
case JsonSchema.NullSchema ignored -> JsonNull.of();
107103
};
108104
}
109105

110106
private static List<JsonValue> failingDocuments(JsonSchema schema, JsonValue compliant) {
111107
return switch (schema) {
112-
case ObjectSchema(var properties) -> properties.isEmpty()
108+
case JsonSchema.ObjectSchema(var properties) -> properties.isEmpty()
113109
? List.<JsonValue>of(JsonNull.of())
114110
: properties.stream()
115111
.map(JsonSchema.Property::name)
116112
.map(name -> removeProperty((JsonObject) compliant, name))
117113
.map(json -> (JsonValue) json)
118114
.toList();
119-
case ArraySchema(var items) -> {
115+
case JsonSchema.ArraySchema(var items) -> {
120116
final var values = ((JsonArray) compliant).values();
121117
if (values.isEmpty()) {
122118
yield List.<JsonValue>of(JsonNull.of());
123119
}
124120
final var truncated = JsonArray.of(values.stream().limit(values.size() - 1L).toList());
125121
yield List.<JsonValue>of(truncated);
126122
}
127-
case StringSchema ignored -> List.<JsonValue>of(JsonNumber.of(BigDecimal.TWO));
128-
case NumberSchema ignored -> List.<JsonValue>of(JsonString.of("not-a-number"));
129-
case BooleanSchema ignored -> List.<JsonValue>of(JsonNull.of());
130-
case NullSchema ignored -> List.<JsonValue>of(JsonBoolean.of(true));
123+
case JsonSchema.StringSchema ignored -> List.<JsonValue>of(JsonNumber.of(BigDecimal.TWO));
124+
case JsonSchema.NumberSchema ignored -> List.<JsonValue>of(JsonString.of("not-a-number"));
125+
case JsonSchema.BooleanSchema ignored -> List.<JsonValue>of(JsonNull.of());
126+
case JsonSchema.NullSchema ignored -> List.<JsonValue>of(JsonBoolean.of(true));
131127
};
132128
}
133129

@@ -145,13 +141,13 @@ private static JsonObject removeProperty(JsonObject original, String missingProp
145141

146142
private static JsonObject schemaToJsonObject(JsonSchema schema) {
147143
return switch (schema) {
148-
case ObjectSchema(var properties) -> {
144+
case JsonSchema.ObjectSchema(var properties) -> {
149145
final var schemaMap = new LinkedHashMap<String, JsonValue>();
150146
schemaMap.put("type", JsonString.of("object"));
151147
final var propertyMap = properties.isEmpty()
152148
? JsonObject.of(Map.<String, JsonValue>of())
153149
: JsonObject.of(properties.stream()
154-
.collect(Collectors.toMap(
150+
.collect(Collectors.<JsonSchema.Property, String, JsonValue, LinkedHashMap<String, JsonValue>>toMap(
155151
JsonSchema.Property::name,
156152
property -> (JsonValue) schemaToJsonObject(property.schema()),
157153
(left, right) -> left,
@@ -167,7 +163,7 @@ case ObjectSchema(var properties) -> {
167163
schemaMap.put("additionalProperties", JsonBoolean.of(false));
168164
yield JsonObject.of(schemaMap);
169165
}
170-
case ArraySchema(var items) -> {
166+
case JsonSchema.ArraySchema(var items) -> {
171167
final var schemaMap = new LinkedHashMap<String, JsonValue>();
172168
schemaMap.put("type", JsonString.of("array"));
173169
final var prefixItems = items.stream()
@@ -180,10 +176,10 @@ case ArraySchema(var items) -> {
180176
schemaMap.put("maxItems", JsonNumber.of((long) items.size()));
181177
yield JsonObject.of(schemaMap);
182178
}
183-
case StringSchema ignored -> primitiveSchema("string");
184-
case NumberSchema ignored -> primitiveSchema("number");
185-
case BooleanSchema ignored -> primitiveSchema("boolean");
186-
case NullSchema ignored -> primitiveSchema("null");
179+
case JsonSchema.StringSchema ignored -> primitiveSchema("string");
180+
case JsonSchema.NumberSchema ignored -> primitiveSchema("number");
181+
case JsonSchema.BooleanSchema ignored -> primitiveSchema("boolean");
182+
case JsonSchema.NullSchema ignored -> primitiveSchema("null");
187183
};
188184
}
189185

@@ -195,42 +191,35 @@ private static JsonObject primitiveSchema(String type) {
195191

196192
private static String describeSchema(JsonSchema schema) {
197193
return switch (schema) {
198-
case ObjectSchema(var properties) -> properties.stream()
194+
case JsonSchema.ObjectSchema(var properties) -> properties.stream()
199195
.map(property -> property.name() + ":" + describeSchema(property.schema()))
200196
.collect(Collectors.joining(",", "object{", "}"));
201-
case ArraySchema(var items) -> items.stream()
197+
case JsonSchema.ArraySchema(var items) -> items.stream()
202198
.map(ITJsonSchemaExhaustiveTest::describeSchema)
203199
.collect(Collectors.joining(",", "array[", "]"));
204-
case StringSchema ignored -> "string";
205-
case NumberSchema ignored -> "number";
206-
case BooleanSchema ignored -> "boolean";
207-
case NullSchema ignored -> "null";
200+
case JsonSchema.StringSchema ignored -> "string";
201+
case JsonSchema.NumberSchema ignored -> "number";
202+
case JsonSchema.BooleanSchema ignored -> "boolean";
203+
case JsonSchema.NullSchema ignored -> "null";
208204
};
209205
}
210206

211-
static final class SchemaArbitraryProvider implements ArbitraryProvider {
212-
@Override
213-
public boolean canProvideFor(TypeUsage targetType) {
214-
return targetType.isOfType(ITJsonSchemaExhaustiveTest.JsonSchema.class);
215-
}
216-
217-
@Override
218-
public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtypeProvider) {
219-
return Set.of(schemaArbitrary(MAX_DEPTH));
220-
}
207+
@Provide
208+
Arbitrary<JsonSchema> schemas() {
209+
return schemaArbitrary(MAX_DEPTH);
221210
}
222211

223212
private static Arbitrary<JsonSchema> schemaArbitrary(int depth) {
224213
final var primitives = Arbitraries.of(
225-
new StringSchema(),
226-
new NumberSchema(),
227-
new BooleanSchema(),
228-
new NullSchema()
214+
new JsonSchema.StringSchema(),
215+
new JsonSchema.NumberSchema(),
216+
new JsonSchema.BooleanSchema(),
217+
new JsonSchema.NullSchema()
229218
);
230219
if (depth == 0) {
231-
return primitives;
220+
return primitives.map(schema -> (JsonSchema) schema);
232221
}
233-
return Arbitraries.oneOf(
222+
return Arbitraries.<JsonSchema>oneOf(
234223
primitives,
235224
objectSchemaArbitrary(depth),
236225
arraySchemaArbitrary(depth)
@@ -239,56 +228,56 @@ private static Arbitrary<JsonSchema> schemaArbitrary(int depth) {
239228

240229
private static Arbitrary<JsonSchema> objectSchemaArbitrary(int depth) {
241230
if (depth == 1) {
242-
return Arbitraries.of(new ObjectSchema(List.of()));
231+
return Arbitraries.of(new JsonSchema.ObjectSchema(List.of()));
243232
}
244233
final var childDepth = depth - 1;
245-
final var empty = Arbitraries.of(new ObjectSchema(List.of()));
234+
final var empty = Arbitraries.of(new JsonSchema.ObjectSchema(List.of()));
246235
final var single = Combinators.combine(
247236
Arbitraries.of(PROPERTY_NAMES),
248237
schemaArbitrary(childDepth)
249-
).as((name, child) -> new ObjectSchema(List.of(new Property(name, child))));
238+
).as((name, child) -> new JsonSchema.ObjectSchema(List.of(new JsonSchema.Property(name, child))));
250239
final var pair = Combinators.combine(
251240
Arbitraries.of(PROPERTY_PAIRS),
252241
schemaArbitrary(childDepth),
253242
schemaArbitrary(childDepth)
254-
).as((names, first, second) -> new ObjectSchema(List.of(
255-
new Property(names.getFirst(), first),
256-
new Property(names.getLast(), second)
243+
).as((names, first, second) -> new JsonSchema.ObjectSchema(List.of(
244+
new JsonSchema.Property(names.getFirst(), first),
245+
new JsonSchema.Property(names.getLast(), second)
257246
)));
258247
return Arbitraries.oneOf(empty, single, pair);
259248
}
260249

261250
private static Arbitrary<JsonSchema> arraySchemaArbitrary(int depth) {
262251
if (depth == 1) {
263-
return Arbitraries.of(new ArraySchema(List.of()));
252+
return Arbitraries.of(new JsonSchema.ArraySchema(List.of()));
264253
}
265254
final var childDepth = depth - 1;
266-
final var empty = Arbitraries.of(new ArraySchema(List.of()));
255+
final var empty = Arbitraries.of(new JsonSchema.ArraySchema(List.of()));
267256
final var single = schemaArbitrary(childDepth)
268-
.map(child -> new ArraySchema(List.of(child)));
257+
.map(child -> new JsonSchema.ArraySchema(List.of(child)));
269258
final var pair = Combinators.combine(
270259
schemaArbitrary(childDepth),
271260
schemaArbitrary(childDepth)
272-
).as((first, second) -> new ArraySchema(List.of(first, second)));
261+
).as((first, second) -> new JsonSchema.ArraySchema(List.of(first, second)));
273262
return Arbitraries.oneOf(empty, single, pair);
274263
}
275264

276-
sealed interface JsonSchema permits ObjectSchema, ArraySchema, StringSchema, NumberSchema, BooleanSchema, NullSchema {
265+
sealed interface JsonSchema permits JsonSchema.ObjectSchema, JsonSchema.ArraySchema, JsonSchema.StringSchema, JsonSchema.NumberSchema, JsonSchema.BooleanSchema, JsonSchema.NullSchema {
277266
record ObjectSchema(List<Property> properties) implements JsonSchema {
278-
ObjectSchema {
267+
public ObjectSchema {
279268
properties = List.copyOf(properties);
280269
}
281270
}
282271

283272
record Property(String name, JsonSchema schema) {
284-
Property {
273+
public Property {
285274
name = Objects.requireNonNull(name);
286275
schema = Objects.requireNonNull(schema);
287276
}
288277
}
289278

290279
record ArraySchema(List<JsonSchema> items) implements JsonSchema {
291-
ArraySchema {
280+
public ArraySchema {
292281
items = List.copyOf(items);
293282
}
294283
}

0 commit comments

Comments
 (0)