Skip to content

Commit d42bd26

Browse files
addArrayValues: Skip "tooLarge" failure case if infeasible
1 parent 012b113 commit d42bd26

3 files changed

Lines changed: 365 additions & 6 deletions

File tree

tcases-lib/src/main/java/org/cornutum/tcases/resolve/Schemas.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public Schemas( ExecutionNotifier<?> context)
4040
}
4141

4242
/**
43-
* Returns a schena that describes values that do not belong to the values described by the given schema.
43+
* Returns a schema that describes values that do not belong to the values described by the given schema.
4444
*/
4545
public static Schema not( Schema schema)
4646
{
@@ -501,6 +501,78 @@ public static Integer maxLengthRequired( Schema schema)
501501
.orElse( patternMax);
502502
}
503503

504+
/**
505+
* If the given schema value domain is bounded, returns the maximum number of values allowed.
506+
* Otherwise, returns <CODE>Optional.empty()</CODE>.
507+
*/
508+
public static Optional<Integer> domainSize( Schema schema)
509+
{
510+
Integer domainSize;
511+
512+
if( schema == null)
513+
{
514+
domainSize = null;
515+
}
516+
else if( schema.getConstant() != null)
517+
{
518+
domainSize = 1;
519+
}
520+
else if( schema.getEnum() != null)
521+
{
522+
domainSize = schema.getEnum().size();
523+
}
524+
else
525+
{
526+
switch( schema.getType())
527+
{
528+
case INTEGER:
529+
case NUMBER:
530+
{
531+
domainSize =
532+
(schema.getMinimum() == null || schema.getMaximum() == null)
533+
? null
534+
: maxBoundedNumbers( schema);
535+
break;
536+
}
537+
538+
case BOOLEAN:
539+
{
540+
domainSize = 2;
541+
break;
542+
}
543+
544+
default:
545+
{
546+
domainSize = null;
547+
break;
548+
}
549+
}
550+
}
551+
552+
return Optional.ofNullable( domainSize);
553+
}
554+
555+
/**
556+
* For a bounded numeric schema, returns the maximum number of values allowed.
557+
*/
558+
private static int maxBoundedNumbers( Schema schema)
559+
{
560+
int maxValues;
561+
BigDecimal multipleOf;
562+
BigDecimal nextMultiple;
563+
564+
for( maxValues = 0,
565+
nextMultiple = schema.getMinimum(),
566+
multipleOf = Optional.ofNullable( schema.getMultipleOf()).orElse( unitOf( schema));
567+
568+
nextMultiple.compareTo( schema.getMaximum()) <= 0;
569+
570+
maxValues++,
571+
nextMultiple = nextMultiple.add( multipleOf));
572+
573+
return maxValues;
574+
}
575+
504576
/**
505577
* Returns the unit value for the number range defined by the given schema.
506578
*/

tcases-lib/src/main/java/org/cornutum/tcases/resolve/TestCaseSchemaResolver.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,18 @@ private void addArrayValues( Stream.Builder<VarValueDef> values, Schema schema)
295295
}
296296

297297
int aboveMax = maxItems + 1;
298-
values.add(
299-
VarValueDefBuilder.with( "tooLarge")
300-
.type( FAILURE)
301-
.schema( SchemaBuilder.with( schema).minItems( aboveMax).maxItems( null).build())
302-
.build());
298+
boolean aboveMaxInfeasible =
299+
Optional.ofNullable( schema.getUniqueItems()).orElse( false)
300+
&& Schemas.domainSize( schema.getItems()).map( maxValues -> maxValues < aboveMax).orElse( false);
301+
302+
if( !aboveMaxInfeasible)
303+
{
304+
values.add(
305+
VarValueDefBuilder.with( "tooLarge")
306+
.type( FAILURE)
307+
.schema( SchemaBuilder.with( schema).minItems( aboveMax).maxItems( null).build())
308+
.build());
309+
}
303310
}
304311

305312
if( Optional.ofNullable( schema.getUniqueItems()).orElse( false)

tcases-lib/src/test/java/org/cornutum/tcases/resolve/VarSchemaValuesTest.java

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,286 @@ public void whenMaxItemsNegative()
178178
assertThat( "Values", values, containsMembers( VarValueDefMatcher::new, expected));
179179
}
180180

181+
@Test
182+
public void whenConstItemsTooLargeInfeasible()
183+
{
184+
// Given...
185+
TestCaseSchemaResolver resolver = getResolver();
186+
187+
Schema schema =
188+
SchemaBuilder.type( "array")
189+
.uniqueItems( true)
190+
.minItems( 0)
191+
.maxItems( 1)
192+
.items( SchemaBuilder.type( "boolean").constant( true).build())
193+
.build();
194+
195+
// When...
196+
List<VarValueDef> values = resolver.valuesForSchema( schema).collect( toList());
197+
198+
// Then...
199+
VarValueDef[] expected =
200+
new VarValueDef[]
201+
{
202+
VarValueDefBuilder.with( "minimumSize")
203+
.schema(
204+
SchemaBuilder.with( schema)
205+
.maxItems( 0)
206+
.build())
207+
.build(),
208+
209+
VarValueDefBuilder.with( "maximumSize")
210+
.schema(
211+
SchemaBuilder.with( schema)
212+
.minItems( 1)
213+
.build())
214+
.build(),
215+
216+
VarValueDefBuilder.with( "wrongItems")
217+
.type( FAILURE)
218+
.schema(
219+
SchemaBuilder.with( schema)
220+
.items( Schemas.not( schema.getItems()))
221+
.build())
222+
.build()
223+
};
224+
225+
assertThat( "Values", values, containsMembers( VarValueDefMatcher::new, expected));
226+
}
227+
228+
@Test
229+
public void whenEnumItemsTooLargeInfeasible()
230+
{
231+
// Given...
232+
TestCaseSchemaResolver resolver = getResolver();
233+
234+
Schema schema =
235+
SchemaBuilder.type( "array")
236+
.uniqueItems( true)
237+
.minItems( 1)
238+
.maxItems( 2)
239+
.items( SchemaBuilder.type( "string").enums( "hello", "world").build())
240+
.build();
241+
242+
// When...
243+
List<VarValueDef> values = resolver.valuesForSchema( schema).collect( toList());
244+
245+
// Then...
246+
VarValueDef[] expected =
247+
new VarValueDef[]
248+
{
249+
VarValueDefBuilder.with( "minimumSize")
250+
.schema(
251+
SchemaBuilder.with( schema)
252+
.maxItems( 1)
253+
.build())
254+
.build(),
255+
256+
VarValueDefBuilder.with( "tooSmall")
257+
.type( FAILURE)
258+
.schema(
259+
SchemaBuilder.with( schema)
260+
.minItems( 0)
261+
.maxItems( 0)
262+
.build())
263+
.build(),
264+
265+
VarValueDefBuilder.with( "maximumSize")
266+
.schema(
267+
SchemaBuilder.with( schema)
268+
.minItems( 2)
269+
.build())
270+
.build(),
271+
272+
VarValueDefBuilder.with( "notUnique")
273+
.type( FAILURE)
274+
.schema(
275+
SchemaBuilder.with( schema)
276+
.minItems( 2)
277+
.uniqueItems( false)
278+
.build())
279+
.build(),
280+
281+
VarValueDefBuilder.with( "wrongItems")
282+
.type( FAILURE)
283+
.schema(
284+
SchemaBuilder.with( schema)
285+
.items( Schemas.not( schema.getItems()))
286+
.build())
287+
.build()
288+
};
289+
290+
assertThat( "Values", values, containsMembers( VarValueDefMatcher::new, expected));
291+
}
292+
293+
@Test
294+
public void whenBooleanItemsTooLargeInfeasible()
295+
{
296+
// Given...
297+
TestCaseSchemaResolver resolver = getResolver();
298+
299+
Schema schema =
300+
SchemaBuilder.type( "array")
301+
.uniqueItems( true)
302+
.maxItems( 2)
303+
.items( SchemaBuilder.type( "boolean").build())
304+
.build();
305+
306+
// When...
307+
List<VarValueDef> values = resolver.valuesForSchema( schema).collect( toList());
308+
309+
// Then...
310+
VarValueDef[] expected =
311+
new VarValueDef[]
312+
{
313+
VarValueDefBuilder.with( "empty")
314+
.schema(
315+
SchemaBuilder.type( "array")
316+
.maxItems( 0)
317+
.items( null)
318+
.build())
319+
.build(),
320+
321+
VarValueDefBuilder.with( "maximumSize")
322+
.schema(
323+
SchemaBuilder.with( schema)
324+
.minItems( 2)
325+
.build())
326+
.build(),
327+
328+
VarValueDefBuilder.with( "notUnique")
329+
.type( FAILURE)
330+
.schema(
331+
SchemaBuilder.with( schema)
332+
.minItems( 2)
333+
.uniqueItems( false)
334+
.build())
335+
.build(),
336+
337+
VarValueDefBuilder.with( "wrongItems")
338+
.type( FAILURE)
339+
.schema(
340+
SchemaBuilder.with( schema)
341+
.items( Schemas.not( schema.getItems()))
342+
.build())
343+
.build()
344+
};
345+
346+
assertThat( "Values", values, containsMembers( VarValueDefMatcher::new, expected));
347+
}
348+
349+
@Test
350+
public void whenIntegerItemsTooLargeInfeasible()
351+
{
352+
// Given...
353+
TestCaseSchemaResolver resolver = getResolver();
354+
355+
Schema schema =
356+
SchemaBuilder.type( "array")
357+
.uniqueItems( true)
358+
.maxItems( 3)
359+
.items( SchemaBuilder.type( "integer").minimum( -1).maximum( 1).build())
360+
.build();
361+
362+
// When...
363+
List<VarValueDef> values = resolver.valuesForSchema( schema).collect( toList());
364+
365+
// Then...
366+
VarValueDef[] expected =
367+
new VarValueDef[]
368+
{
369+
VarValueDefBuilder.with( "empty")
370+
.schema(
371+
SchemaBuilder.type( "array")
372+
.maxItems( 0)
373+
.items( null)
374+
.build())
375+
.build(),
376+
377+
VarValueDefBuilder.with( "maximumSize")
378+
.schema(
379+
SchemaBuilder.with( schema)
380+
.minItems( 3)
381+
.build())
382+
.build(),
383+
384+
VarValueDefBuilder.with( "notUnique")
385+
.type( FAILURE)
386+
.schema(
387+
SchemaBuilder.with( schema)
388+
.minItems( 2)
389+
.uniqueItems( false)
390+
.build())
391+
.build(),
392+
393+
VarValueDefBuilder.with( "wrongItems")
394+
.type( FAILURE)
395+
.schema(
396+
SchemaBuilder.with( schema)
397+
.items( Schemas.not( schema.getItems()))
398+
.build())
399+
.build()
400+
};
401+
402+
assertThat( "Values", values, containsMembers( VarValueDefMatcher::new, expected));
403+
}
404+
405+
@Test
406+
public void whenNumberItemsTooLargeInfeasible()
407+
{
408+
// Given...
409+
TestCaseSchemaResolver resolver = getResolver();
410+
411+
Schema schema =
412+
SchemaBuilder.type( "array")
413+
.uniqueItems( true)
414+
.maxItems( 9)
415+
.items( SchemaBuilder.type( "number").minimum( "-2.0").maximum( "2.0").multipleOf( "0.5").build())
416+
.build();
417+
418+
// When...
419+
List<VarValueDef> values = resolver.valuesForSchema( schema).collect( toList());
420+
421+
// Then...
422+
VarValueDef[] expected =
423+
new VarValueDef[]
424+
{
425+
VarValueDefBuilder.with( "empty")
426+
.schema(
427+
SchemaBuilder.type( "array")
428+
.maxItems( 0)
429+
.items( null)
430+
.build())
431+
.build(),
432+
433+
VarValueDefBuilder.with( "maximumSize")
434+
.schema(
435+
SchemaBuilder.with( schema)
436+
.minItems( 9)
437+
.build())
438+
.build(),
439+
440+
VarValueDefBuilder.with( "notUnique")
441+
.type( FAILURE)
442+
.schema(
443+
SchemaBuilder.with( schema)
444+
.minItems( 2)
445+
.uniqueItems( false)
446+
.build())
447+
.build(),
448+
449+
VarValueDefBuilder.with( "wrongItems")
450+
.type( FAILURE)
451+
.schema(
452+
SchemaBuilder.with( schema)
453+
.items( Schemas.not( schema.getItems()))
454+
.build())
455+
.build()
456+
};
457+
458+
assertThat( "Values", values, containsMembers( VarValueDefMatcher::new, expected));
459+
}
460+
181461
@Test
182462
public void whenMinItemsNegative()
183463
{

0 commit comments

Comments
 (0)