@@ -54,21 +54,20 @@ defmodule RockSolid.Strategy do
5454 end
5555
5656 defp gen ( % { "type" => "integer" } = schema , _ ) do
57- [ min: Schemas.Number . min_value ( schema ) , max: Schemas.Number . max_value ( schema ) ]
58- |> Keyword . filter ( fn { _ , v } -> not is_nil ( v ) end )
59- |> MoreStreamData . more_integer ( )
57+ StreamData . frequency ( [
58+ { 90 , regular_integer ( schema ) } ,
59+ { 5 , close_to_max ( schema ) } ,
60+ { 5 , close_to_min ( schema ) }
61+ ] )
6062 |> filter_value ( schema [ "exclusiveMinimum" ] )
6163 |> filter_value ( schema [ "exclusiveMaximum" ] )
6264 end
6365
64- defp gen ( % { "type" => "number" } = schema , _ ) do
65- [
66- min: Schemas.Number . min_value ( schema ) ,
67- max: Schemas.Number . max_value ( schema ) ,
68- exclude_min?: Map . has_key? ( schema , "exclusiveMinimum" ) ,
69- exclude_max?: Map . has_key? ( schema , "exclusiveMaximum" )
70- ]
71- |> MoreStreamData . more_float ( )
66+ defp gen ( % { "type" => "number" } = schema , opts ) do
67+ StreamData . frequency ( [
68+ { 50 , gen ( float_to_int ( schema ) , opts ) } ,
69+ { 50 , gen_float ( schema ) }
70+ ] )
7271 end
7372
7473 # pattern always takes priority above format, because format is not stanarized
@@ -91,10 +90,17 @@ defmodule RockSolid.Strategy do
9190 end
9291
9392 defp gen ( % { "type" => "string" } = schema , opts ) do
94- StreamData . string (
95- Keyword . fetch! ( opts , :string_kind ) ,
96- to_keyword ( schema , min_length: "minLength" , max_length: "maxLength" )
97- )
93+ string_opts = to_keyword ( schema , min_length: "minLength" , max_length: "maxLength" )
94+
95+ case Keyword . fetch! ( opts , :string_kind ) do
96+ nil ->
97+ [ :utf8 , :printable , :ascii ]
98+ |> Enum . map ( fn codepoints -> { 1 , StreamData . string ( codepoints , string_opts ) } end )
99+ |> StreamData . frequency ( )
100+
101+ kind ->
102+ StreamData . string ( kind , string_opts )
103+ end
98104 |> filter_min_length ( schema [ "minLength" ] )
99105 end
100106
@@ -503,4 +509,71 @@ defmodule RockSolid.Strategy do
503509 end
504510 end )
505511 end
512+
513+ defp regular_integer ( schema ) do
514+ [ min: Schemas.Number . min_value ( schema ) , max: Schemas.Number . max_value ( schema ) ]
515+ |> Keyword . filter ( fn { _ , v } -> not is_nil ( v ) end )
516+ |> MoreStreamData . more_integer ( )
517+ end
518+
519+ defp close_to_max ( schema ) do
520+ max = Schemas.Number . max_value ( schema ) || 2_147_483_647
521+ min = Schemas.Number . min_value ( schema ) || - 2_147_483_648
522+
523+ StreamData . integer ( 0 .. ( max - min ) )
524+ |> StreamData . map ( fn val -> max - val end )
525+ end
526+
527+ defp close_to_min ( schema ) do
528+ max = Schemas.Number . max_value ( schema ) || 2_147_483_647
529+ min = Schemas.Number . min_value ( schema ) || - 2_147_483_648
530+
531+ StreamData . integer ( 0 .. ( max - min ) )
532+ |> StreamData . map ( fn val -> val + min end )
533+ end
534+
535+ defp gen_float ( schema ) do
536+ StreamData . frequency ( [
537+ { 90 , regular_float ( schema ) } ,
538+ { 5 , close_to_max_float ( schema ) } ,
539+ { 5 , close_to_min_float ( schema ) }
540+ ] )
541+ end
542+
543+ defp regular_float ( schema ) do
544+ [
545+ min: Schemas.Number . min_value ( schema ) ,
546+ max: Schemas.Number . max_value ( schema ) ,
547+ exclude_min?: Map . has_key? ( schema , "exclusiveMinimum" ) ,
548+ exclude_max?: Map . has_key? ( schema , "exclusiveMaximum" )
549+ ]
550+ |> MoreStreamData . more_float ( )
551+ end
552+
553+ defp close_to_max_float ( schema ) do
554+ max = Schemas.Number . max_value ( schema ) || 8.94e307
555+ min = Schemas.Number . min_value ( schema ) || - 8.94e307
556+
557+ StreamData . float ( min: 0 , max: max - min )
558+ |> StreamData . map ( fn val -> max - val end )
559+ end
560+
561+ defp close_to_min_float ( schema ) do
562+ max = Schemas.Number . max_value ( schema ) || 8.94e307
563+ min = Schemas.Number . min_value ( schema ) || - 8.94e307
564+
565+ StreamData . float ( min: 0 , max: max - min )
566+ |> StreamData . map ( fn val -> val + min end )
567+ end
568+
569+ defp float_to_int ( % { "type" => "number" } = schema ) do
570+ [ "minimum" , "maximum" , "exclusiveMinimum" , "exclusiveMaximum" ]
571+ |> Enum . reduce ( Map . put ( schema , "type" , "integer" ) , fn key , acc_schema ->
572+ if Map . has_key? ( acc_schema , key ) do
573+ Map . update! ( acc_schema , key , & trunc / 1 )
574+ else
575+ acc_schema
576+ end
577+ end )
578+ end
506579end
0 commit comments