github.com/6543-forks/go-swagger@v0.26.0/generator/pointer_test.go (about)

     1  package generator
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/go-openapi/loads"
     8  	"github.com/go-openapi/spec"
     9  	"github.com/go-openapi/swag"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func TestTypeResolver_NestedAliasedSlice(t *testing.T) {
    15  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
    16  	require.NoError(t, err)
    17  
    18  	definitions := specDoc.Spec().Definitions
    19  	k := "Statix"
    20  	schema := definitions[k]
    21  
    22  	tr := newTypeResolver("models", specDoc)
    23  	specDoc.Spec().Definitions["StatixItems0"] = *schema.Items.Schema.Items.Schema.Items.Schema
    24  	schema.Items.Schema.Items.Schema.Items.Schema = spec.RefProperty("#/definitions/StatixItems0")
    25  	tr.KnownDefs["StatixItems0"] = struct{}{}
    26  	tr.ModelName = k
    27  	rt, err := tr.ResolveSchema(&schema, false, false)
    28  	require.NoError(t, err)
    29  
    30  	assert.Equal(t, "[][][]models.StatixItems0", rt.AliasedType)
    31  }
    32  
    33  func TestTypeResolver_PointerLifting(t *testing.T) {
    34  	_, resolver, err := basicTaskListResolver(t)
    35  	require.NoError(t, err)
    36  
    37  	testPointToPrimitives(t, *resolver, false /* not aliased */)
    38  	testPointToPrimitives(t, *resolver, true /* aliased */)
    39  	testPointToSliceElements(t, *resolver, false /* not aliased */)
    40  	testPointToSliceElements(t, *resolver, true /* aliased */)
    41  	testPointToAdditionalPropertiesElements(t, *resolver, false /* not aliased */)
    42  	testPointToAdditionalPropertiesElements(t, *resolver, true /* aliased */)
    43  }
    44  
    45  type builtinVal struct {
    46  	Type, Format, Expected, AliasedType string
    47  
    48  	Nullable, Aliased bool
    49  
    50  	Default interface{}
    51  
    52  	Extensions spec.Extensions
    53  
    54  	Required         bool
    55  	ReadOnly         bool
    56  	Maximum          *float64
    57  	ExclusiveMaximum bool
    58  	Minimum          *float64
    59  	ExclusiveMinimum bool
    60  	MaxLength        *int64
    61  	MinLength        *int64
    62  	Pattern          string
    63  	MaxItems         *int64
    64  	MinItems         *int64
    65  	UniqueItems      bool
    66  	MultipleOf       *float64
    67  	Enum             []interface{}
    68  }
    69  
    70  func nullableExt() spec.Extensions {
    71  	return spec.Extensions{"x-nullable": true}
    72  }
    73  func isNullableExt() spec.Extensions {
    74  	return spec.Extensions{"x-isnullable": true}
    75  }
    76  func notNullableExt() spec.Extensions {
    77  	return spec.Extensions{"x-nullable": false}
    78  }
    79  func isNotNullableExt() spec.Extensions {
    80  	return spec.Extensions{"x-isnullable": false}
    81  }
    82  
    83  var boolPointerVals = []builtinVal{
    84  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: true, Required: false, ReadOnly: false},
    85  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: true, ReadOnly: false},
    86  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: false, ReadOnly: false},
    87  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: true, ReadOnly: true},
    88  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: true, Required: true, ReadOnly: true},
    89  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: true, Required: false, ReadOnly: false, Extensions: nullableExt()},
    90  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: true, ReadOnly: false, Extensions: nullableExt()},
    91  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: false, ReadOnly: false, Extensions: nullableExt()},
    92  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: true, ReadOnly: true, Extensions: nullableExt()},
    93  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: true, Required: true, ReadOnly: true, Extensions: nullableExt()},
    94  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: true, Required: false, ReadOnly: false, Extensions: isNullableExt()},
    95  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: true, ReadOnly: false, Extensions: isNullableExt()},
    96  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: false, ReadOnly: false, Extensions: isNullableExt()},
    97  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: nil, Required: true, ReadOnly: true, Extensions: isNullableExt()},
    98  	{Type: "boolean", Format: "", Expected: "bool", Nullable: true, Default: true, Required: true, ReadOnly: true, Extensions: isNullableExt()},
    99  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: true, Required: false, ReadOnly: false, Extensions: notNullableExt()},
   100  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: true, ReadOnly: false, Extensions: notNullableExt()},
   101  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: false, ReadOnly: false, Extensions: notNullableExt()},
   102  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: true, ReadOnly: true, Extensions: notNullableExt()},
   103  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: true, Required: true, ReadOnly: true, Extensions: notNullableExt()},
   104  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: true, Required: false, ReadOnly: false, Extensions: isNotNullableExt()},
   105  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: true, ReadOnly: false, Extensions: isNotNullableExt()},
   106  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: false, ReadOnly: false, Extensions: isNotNullableExt()},
   107  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: nil, Required: true, ReadOnly: true, Extensions: isNotNullableExt()},
   108  	{Type: "boolean", Format: "", Expected: "bool", Nullable: false, Default: true, Required: true, ReadOnly: true, Extensions: isNotNullableExt()},
   109  }
   110  
   111  func generateNumberPointerVals(t, v string) (result []builtinVal) {
   112  
   113  	vv := v
   114  	if vv == "" || vv == "int" {
   115  		if t == "integer" {
   116  			vv = "int64"
   117  		} else {
   118  			vv = "float64"
   119  		}
   120  	}
   121  	if vv == "uint" && t == "integer" {
   122  		vv = "uint64"
   123  	}
   124  	if t == "number" {
   125  		if v == "float" {
   126  			vv = "float32"
   127  		} else {
   128  			vv = "float64"
   129  		}
   130  	}
   131  	return []builtinVal{
   132  		// plain vanilla
   133  		{Type: t, Format: v, Expected: vv},
   134  		{Type: t, Format: v, Expected: vv, Nullable: true, Extensions: nullableExt()},
   135  		{Type: t, Format: v, Expected: vv, Nullable: true, Extensions: isNullableExt()}, // 2
   136  
   137  		// plain vanilla readonly and defaults
   138  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true},
   139  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Extensions: nullableExt()},
   140  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Extensions: isNullableExt()},
   141  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3},
   142  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, ReadOnly: true},
   143  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   144  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 9
   145  
   146  		// required
   147  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true},
   148  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Extensions: nullableExt()},
   149  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Extensions: isNullableExt()}, // 12
   150  
   151  		// required, readonly and defaults
   152  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, ReadOnly: true},
   153  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, ReadOnly: true, Extensions: nullableExt()},
   154  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, ReadOnly: true, Extensions: isNullableExt()},
   155  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3},
   156  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, Default: 3, ReadOnly: true},
   157  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   158  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 19
   159  
   160  		// minimum validation
   161  		{Type: t, Format: v, Expected: vv, Minimum: swag.Float64(2)},
   162  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(0)},
   163  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(2), Extensions: nullableExt()},
   164  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(2), Extensions: isNullableExt()}, // 23
   165  
   166  		// minimum validation, readonly and defaults
   167  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Minimum: swag.Float64(2)},
   168  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Minimum: swag.Float64(0)},
   169  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Minimum: swag.Float64(2), Extensions: nullableExt()},
   170  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Minimum: swag.Float64(2), Extensions: isNullableExt()},
   171  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, Minimum: swag.Float64(2)},
   172  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, ReadOnly: true, Minimum: swag.Float64(2)},
   173  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Minimum: swag.Float64(2), Extensions: nullableExt()},
   174  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Minimum: swag.Float64(2), Extensions: isNullableExt()}, // 31
   175  
   176  		// required, minimum validation
   177  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2)},
   178  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(0)},
   179  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Extensions: nullableExt()},
   180  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Extensions: isNullableExt()}, // 35
   181  
   182  		// required, minimum validation, readonly and defaults
   183  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, Minimum: swag.Float64(2), ReadOnly: true},
   184  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), ReadOnly: true, Extensions: nullableExt()},
   185  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), ReadOnly: true, Extensions: isNullableExt()},
   186  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Default: 3},
   187  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, Minimum: swag.Float64(2), Default: 3, ReadOnly: true},
   188  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Default: 3, ReadOnly: true, Extensions: nullableExt()},
   189  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 42
   190  
   191  		// maximum validation
   192  		{Type: t, Format: v, Expected: vv, Maximum: swag.Float64(2)},
   193  		{Type: t, Format: v, Expected: vv, Nullable: true, Maximum: swag.Float64(0)},
   194  		{Type: t, Format: v, Expected: vv, Nullable: true, Maximum: swag.Float64(2), Extensions: nullableExt()},
   195  		{Type: t, Format: v, Expected: vv, Nullable: true, Maximum: swag.Float64(2), Extensions: isNullableExt()}, // 46
   196  
   197  		// maximum validation, readonly and defaults
   198  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Maximum: swag.Float64(2)},
   199  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Maximum: swag.Float64(0)},
   200  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Maximum: swag.Float64(2), Extensions: nullableExt()},
   201  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Maximum: swag.Float64(2), Extensions: isNullableExt()},
   202  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, Maximum: swag.Float64(2)},
   203  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, ReadOnly: true, Maximum: swag.Float64(2)},
   204  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Maximum: swag.Float64(2), Extensions: nullableExt()},
   205  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Maximum: swag.Float64(2), Extensions: isNullableExt()}, // 54
   206  
   207  		// required, maximum validation
   208  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2)},
   209  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(0)},
   210  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), Extensions: nullableExt()},
   211  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), Extensions: isNullableExt()}, // 58
   212  
   213  		// required, maximum validation, readonly and defaults
   214  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, Maximum: swag.Float64(2), ReadOnly: true},
   215  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), ReadOnly: true, Extensions: nullableExt()},
   216  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), ReadOnly: true, Extensions: isNullableExt()},
   217  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), Default: 3},
   218  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, Maximum: swag.Float64(2), Default: 3, ReadOnly: true},
   219  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), Default: 3, ReadOnly: true, Extensions: nullableExt()},
   220  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Maximum: swag.Float64(2), Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 65
   221  
   222  		// minimum and maximum validation
   223  		{Type: t, Format: v, Expected: vv, Minimum: swag.Float64(2), Maximum: swag.Float64(5)},
   224  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(1)},
   225  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(0), Maximum: swag.Float64(1)},
   226  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(0)},
   227  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(2), Maximum: swag.Float64(6), Extensions: nullableExt()},
   228  		{Type: t, Format: v, Expected: vv, Nullable: true, Minimum: swag.Float64(2), Maximum: swag.Float64(6), Extensions: isNullableExt()}, // 72
   229  
   230  		// minimum and maximum validation, readonly and defaults
   231  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(2)},
   232  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Minimum: swag.Float64(0), Maximum: swag.Float64(3)},
   233  		{Type: t, Format: v, Expected: vv, Nullable: false, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(0)},
   234  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, Minimum: swag.Float64(-1), ReadOnly: true, Maximum: swag.Float64(2)},
   235  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Maximum: swag.Float64(2), Extensions: nullableExt()},
   236  		{Type: t, Format: v, Expected: vv, Nullable: true, ReadOnly: true, Maximum: swag.Float64(2), Extensions: isNullableExt()},
   237  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, Minimum: swag.Float64(-1), Maximum: swag.Float64(6)},
   238  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, Minimum: swag.Float64(1), Maximum: swag.Float64(6)},
   239  		{Type: t, Format: v, Expected: vv, Nullable: false, Default: 3, Minimum: swag.Float64(-6), Maximum: swag.Float64(-1)},
   240  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(2), Extensions: nullableExt()},
   241  		{Type: t, Format: v, Expected: vv, Nullable: true, Default: 3, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(2), Extensions: isNullableExt()}, // 83
   242  
   243  		// required, minimum and maximum validation
   244  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Maximum: swag.Float64(5)},
   245  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(1)},
   246  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(0), Maximum: swag.Float64(1)},
   247  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(0)},
   248  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Maximum: swag.Float64(6), Extensions: nullableExt()},
   249  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Minimum: swag.Float64(2), Maximum: swag.Float64(6), Extensions: isNullableExt()}, // 89
   250  
   251  		// required, minimum and maximum validation, readonly and defaults
   252  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(2)},
   253  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, ReadOnly: true, Minimum: swag.Float64(0), Maximum: swag.Float64(3)},
   254  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(0)},
   255  		{Type: t, Format: v, Expected: vv, Nullable: false, Required: true, Default: 3, Minimum: swag.Float64(-1), ReadOnly: true, Maximum: swag.Float64(2)},
   256  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, ReadOnly: true, Maximum: swag.Float64(2), Extensions: nullableExt()},
   257  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, ReadOnly: true, Maximum: swag.Float64(2), Extensions: isNullableExt()},
   258  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, Minimum: swag.Float64(-1), Maximum: swag.Float64(6)},
   259  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, Minimum: swag.Float64(1), Maximum: swag.Float64(6)},
   260  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, Minimum: swag.Float64(-6), Maximum: swag.Float64(-1)},
   261  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(2), Extensions: nullableExt()},
   262  		{Type: t, Format: v, Expected: vv, Nullable: true, Required: true, Default: 3, ReadOnly: true, Minimum: swag.Float64(-1), Maximum: swag.Float64(2), Extensions: isNullableExt()}, // 99
   263  	}
   264  }
   265  
   266  var stringPointerVals = []builtinVal{
   267  	{Type: "string", Format: "", Expected: "string", Nullable: false},
   268  	{Type: "string", Format: "", Expected: "string", Nullable: true, Extensions: nullableExt()},
   269  	{Type: "string", Format: "", Expected: "string", Nullable: true, Extensions: isNullableExt()}, // 2
   270  
   271  	// plain vanilla readonly and defaults
   272  	{Type: "string", Format: "", Expected: "string", Nullable: false, ReadOnly: true},
   273  	{Type: "string", Format: "", Expected: "string", Nullable: true, ReadOnly: true, Extensions: nullableExt()},
   274  	{Type: "string", Format: "", Expected: "string", Nullable: true, ReadOnly: true, Extensions: isNullableExt()},
   275  	{Type: "string", Format: "", Expected: "string", Nullable: true, Default: 3},
   276  	{Type: "string", Format: "", Expected: "string", Nullable: false, Default: 3, ReadOnly: true},
   277  	{Type: "string", Format: "", Expected: "string", Nullable: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   278  	{Type: "string", Format: "", Expected: "string", Nullable: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 9
   279  
   280  	// required
   281  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true},
   282  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, Extensions: nullableExt()},
   283  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, Extensions: isNullableExt()}, // 12
   284  
   285  	// required, readonly and defaults
   286  	{Type: "string", Format: "", Expected: "string", Nullable: false, Required: true, ReadOnly: true},
   287  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, ReadOnly: true, Extensions: nullableExt()},
   288  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, ReadOnly: true, Extensions: isNullableExt()},
   289  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, Default: 3},
   290  	{Type: "string", Format: "", Expected: "string", Nullable: false, Required: true, Default: 3, ReadOnly: true},
   291  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   292  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 19
   293  
   294  	// minLength validation
   295  	{Type: "string", Format: "", Expected: "string", Nullable: false, MinLength: swag.Int64(2)},
   296  	{Type: "string", Format: "", Expected: "string", Nullable: true, MinLength: swag.Int64(0)},
   297  	{Type: "string", Format: "", Expected: "string", Nullable: true, MinLength: swag.Int64(2), Extensions: nullableExt()},
   298  	{Type: "string", Format: "", Expected: "string", Nullable: true, MinLength: swag.Int64(2), Extensions: isNullableExt()}, // 23
   299  
   300  	// minLength validation, readonly and defaults
   301  	{Type: "string", Format: "", Expected: "string", Nullable: false, ReadOnly: true, MinLength: swag.Int64(2)},
   302  	{Type: "string", Format: "", Expected: "string", Nullable: false, ReadOnly: true, MinLength: swag.Int64(0)},
   303  	{Type: "string", Format: "", Expected: "string", Nullable: true, ReadOnly: true, MinLength: swag.Int64(2), Extensions: nullableExt()},
   304  	{Type: "string", Format: "", Expected: "string", Nullable: true, ReadOnly: true, MinLength: swag.Int64(2), Extensions: isNullableExt()},
   305  	{Type: "string", Format: "", Expected: "string", Nullable: false, Default: 3, MinLength: swag.Int64(2)},
   306  	{Type: "string", Format: "", Expected: "string", Nullable: false, Default: 3, ReadOnly: true, MinLength: swag.Int64(2)},
   307  	{Type: "string", Format: "", Expected: "string", Nullable: true, Default: 3, ReadOnly: true, MinLength: swag.Int64(2), Extensions: nullableExt()},
   308  	{Type: "string", Format: "", Expected: "string", Nullable: true, Default: 3, ReadOnly: true, MinLength: swag.Int64(2), Extensions: isNullableExt()}, // 31
   309  
   310  	// required, minLength validation
   311  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2)},
   312  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(0)},
   313  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), Extensions: nullableExt()},
   314  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), Extensions: isNullableExt()}, // 35
   315  
   316  	// required, minLength validation, readonly and defaults
   317  	{Type: "string", Format: "", Expected: "string", Nullable: false, Required: true, MinLength: swag.Int64(2), ReadOnly: true},
   318  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), ReadOnly: true, Extensions: nullableExt()},
   319  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), ReadOnly: true, Extensions: isNullableExt()},
   320  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), Default: 3},
   321  	{Type: "string", Format: "", Expected: "string", Nullable: false, Required: true, MinLength: swag.Int64(2), Default: 3, ReadOnly: true},
   322  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), Default: 3, ReadOnly: true, Extensions: nullableExt()},
   323  	{Type: "string", Format: "", Expected: "string", Nullable: true, Required: true, MinLength: swag.Int64(2), Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 42
   324  }
   325  
   326  var strfmtValues = []builtinVal{
   327  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: false},
   328  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Extensions: nullableExt()},
   329  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Extensions: isNullableExt()}, // 2
   330  
   331  	// plain vanilla readonly and defaults
   332  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: false, ReadOnly: true},
   333  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, ReadOnly: true, Extensions: nullableExt()},
   334  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, ReadOnly: true, Extensions: isNullableExt()},
   335  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Default: 3},
   336  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: false, Default: 3, ReadOnly: true},
   337  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   338  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 9
   339  
   340  	// required
   341  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true},
   342  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, Extensions: nullableExt()},
   343  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, Extensions: isNullableExt()}, // 12
   344  
   345  	// required, readonly and defaults
   346  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: false, Required: true, ReadOnly: true},
   347  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, ReadOnly: true, Extensions: nullableExt()},
   348  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, ReadOnly: true, Extensions: isNullableExt()},
   349  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, Default: 3},
   350  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: false, Required: true, Default: 3, ReadOnly: true},
   351  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   352  	{Type: "string", Format: "password", Expected: "strfmt.Password", Nullable: true, Required: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 19
   353  
   354  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false},
   355  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Extensions: nullableExt()},
   356  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Extensions: isNullableExt()}, // 22
   357  
   358  	// plain vanilla readonly and defaults
   359  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, ReadOnly: true},
   360  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, ReadOnly: true, Extensions: nullableExt()},
   361  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, ReadOnly: true, Extensions: isNullableExt()},
   362  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Default: 3},
   363  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Default: 3, ReadOnly: true},
   364  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   365  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 29
   366  
   367  	// required
   368  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true},
   369  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, Extensions: nullableExt()},
   370  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, Extensions: isNullableExt()}, // 32
   371  
   372  	// required, readonly and defaults
   373  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, ReadOnly: true},
   374  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, ReadOnly: true, Extensions: nullableExt()},
   375  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, ReadOnly: true, Extensions: isNullableExt()},
   376  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, Default: 3},
   377  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, Default: 3, ReadOnly: true},
   378  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, Default: 3, ReadOnly: true, Extensions: nullableExt()},
   379  	{Type: "string", Format: "binary", Expected: "io.ReadCloser", Nullable: false, Required: true, Default: 3, ReadOnly: true, Extensions: isNullableExt()}, // 39
   380  }
   381  
   382  func testPointToAdditionalPropertiesElements(t testing.TB, tr typeResolver, aliased bool) bool {
   383  	if aliased {
   384  		tr.ModelName = "MyAliasedThing"
   385  	}
   386  	resolver := &tr
   387  	for i, val := range boolPointerVals {
   388  		if !assertBuiltinAdditionalPropertiesElem(t, resolver, aliased, i, val) {
   389  			return false
   390  		}
   391  	}
   392  	for _, v := range []string{"", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64"} {
   393  		passed := true
   394  		for i, val := range generateNumberPointerVals("integer", v) {
   395  			if !assertBuiltinAdditionalPropertiesElem(t, resolver, aliased, i, val) {
   396  				passed = false
   397  			}
   398  		}
   399  		if !passed {
   400  			return false
   401  		}
   402  	}
   403  	for _, v := range []string{"", "float", "double"} {
   404  		passed := true
   405  		for i, val := range generateNumberPointerVals("number", v) {
   406  			if !assertBuiltinAdditionalPropertiesElem(t, resolver, aliased, i, val) {
   407  				passed = false
   408  			}
   409  		}
   410  		if !passed {
   411  			return false
   412  		}
   413  	}
   414  	for i, val := range stringPointerVals {
   415  		if !assertBuiltinAdditionalPropertiesElem(t, resolver, aliased, i, val) {
   416  			return false
   417  		}
   418  	}
   419  	for i, val := range strfmtValues {
   420  		if !assertBuiltinAdditionalPropertiesElem(t, resolver, aliased, i, val) {
   421  			return false
   422  		}
   423  	}
   424  	return true
   425  }
   426  
   427  func testPointToSliceElements(t testing.TB, tr typeResolver, aliased bool) bool {
   428  	if aliased {
   429  		tr.ModelName = "MyAliasedThing"
   430  	}
   431  	resolver := &tr
   432  	for i, val := range boolPointerVals {
   433  
   434  		if !assertBuiltinSliceElem(t, resolver, aliased, i, val) {
   435  			return false
   436  		}
   437  	}
   438  	for _, v := range []string{"", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64"} {
   439  		passed := true
   440  		for i, val := range generateNumberPointerVals("integer", v) {
   441  			if !assertBuiltinSliceElem(t, resolver, aliased, i, val) {
   442  				passed = false
   443  			}
   444  		}
   445  		if !passed {
   446  			return false
   447  		}
   448  	}
   449  	for _, v := range []string{"", "float", "double"} {
   450  		passed := true
   451  		for i, val := range generateNumberPointerVals("number", v) {
   452  			if !assertBuiltinSliceElem(t, resolver, aliased, i, val) {
   453  				passed = false
   454  			}
   455  		}
   456  		if !passed {
   457  			return false
   458  		}
   459  	}
   460  	for i, val := range stringPointerVals {
   461  		if !assertBuiltinSliceElem(t, resolver, aliased, i, val) {
   462  			return false
   463  		}
   464  	}
   465  	for i, val := range strfmtValues {
   466  		if !assertBuiltinSliceElem(t, resolver, aliased, i, val) {
   467  			return false
   468  		}
   469  	}
   470  	return true
   471  }
   472  
   473  func testPointToPrimitives(t testing.TB, tr typeResolver, aliased bool) bool {
   474  	if aliased {
   475  		tr.ModelName = "MyAliasedThing"
   476  		tr.KnownDefs[tr.ModelName] = struct{}{}
   477  	}
   478  	resolver := &tr
   479  	for i, val := range boolPointerVals {
   480  		if !assertBuiltinVal(t, resolver, aliased, i, val) {
   481  			return false
   482  		}
   483  	}
   484  	for _, v := range []string{"", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64"} {
   485  		passed := true
   486  		for i, val := range generateNumberPointerVals("integer", v) {
   487  			if !assertBuiltinVal(t, resolver, aliased, i, val) {
   488  				passed = false
   489  			}
   490  		}
   491  		if !passed {
   492  			return false
   493  		}
   494  	}
   495  	for _, v := range []string{"", "float", "double"} {
   496  		passed := true
   497  		for i, val := range generateNumberPointerVals("number", v) {
   498  			if !assertBuiltinVal(t, resolver, aliased, i, val) {
   499  				passed = false
   500  			}
   501  		}
   502  		if !passed {
   503  			return false
   504  		}
   505  	}
   506  
   507  	for i, val := range stringPointerVals {
   508  		if !assertBuiltinVal(t, resolver, aliased, i, val) {
   509  			return false
   510  		}
   511  	}
   512  
   513  	for i, val := range strfmtValues {
   514  		if !assertBuiltinVal(t, resolver, aliased, i, val) {
   515  			return false
   516  		}
   517  	}
   518  	return true
   519  }
   520  
   521  func assertBuiltinVal(t testing.TB, resolver *typeResolver, aliased bool, i int, val builtinVal) bool {
   522  	val.Aliased = aliased
   523  	if aliased {
   524  		val.AliasedType = val.Expected
   525  		val.Expected = "models.MyAliasedThing"
   526  	}
   527  
   528  	sch := new(spec.Schema)
   529  	sch.Typed(val.Type, val.Format)
   530  	sch.Default = val.Default
   531  	sch.ReadOnly = val.ReadOnly
   532  	sch.Extensions = val.Extensions
   533  	sch.Minimum = val.Minimum
   534  	sch.Maximum = val.Maximum
   535  	sch.MultipleOf = val.MultipleOf
   536  	sch.MinLength = val.MinLength
   537  	sch.MaxLength = val.MaxLength
   538  
   539  	rt, err := resolver.ResolveSchema(sch, !aliased, val.Required)
   540  	require.NoError(t, err)
   541  	if val.Nullable {
   542  		if !assert.True(t, rt.IsNullable, "expected nullable for item at: %d", i) {
   543  			// fmt.Println("isRequired:", val.Required)
   544  			// pretty.Println(sch)
   545  			return false
   546  		}
   547  	} else {
   548  		if !assert.False(t, rt.IsNullable, "expected not nullable for item at: %d", i) {
   549  			// fmt.Println("isRequired:", val.Required)
   550  			// pretty.Println(sch)
   551  			return false
   552  		}
   553  	}
   554  	if !assert.Equal(t, val.Aliased, rt.IsAliased, "expected (%q, %q) to be an aliased type", val.Type, val.Format) {
   555  		return false
   556  	}
   557  	if val.Aliased {
   558  		if !assert.Equal(t, val.AliasedType, rt.AliasedType, "expected %q (%q, %q) to be aliased as %q, but got %q", val.Expected, val.Type, val.Format, val.AliasedType, rt.AliasedType) {
   559  			return false
   560  		}
   561  	}
   562  	if !assertBuiltinResolve(t, val.Type, val.Format, val.Expected, rt, i) {
   563  		return false
   564  	}
   565  	return true
   566  }
   567  
   568  func assertBuiltinSliceElem(t testing.TB, resolver *typeResolver, aliased bool, i int, val builtinVal) bool {
   569  	val.Nullable = false
   570  	if nullableExtension(val.Extensions) != nil {
   571  		val.Nullable = *nullableExtension(val.Extensions)
   572  	}
   573  	sliceType := "[]" + val.Expected
   574  	if val.Nullable {
   575  		sliceType = "[]*" + val.Expected
   576  	}
   577  	val.Expected = sliceType
   578  
   579  	val.Aliased = aliased
   580  	if aliased {
   581  		val.AliasedType = val.Expected
   582  		val.Expected = "models.MyAliasedThing"
   583  	}
   584  
   585  	items := new(spec.Schema)
   586  	items.Typed(val.Type, val.Format)
   587  	items.Default = val.Default
   588  	items.ReadOnly = val.ReadOnly
   589  	items.Extensions = val.Extensions
   590  	items.Minimum = val.Minimum
   591  	items.Maximum = val.Maximum
   592  	items.MultipleOf = val.MultipleOf
   593  	items.MinLength = val.MinLength
   594  	items.MaxLength = val.MaxLength
   595  
   596  	sch := spec.ArrayProperty(items)
   597  
   598  	rt, err := resolver.ResolveSchema(sch, !aliased, val.Required)
   599  	require.NoError(t, err)
   600  
   601  	if val.Nullable {
   602  		if !assert.True(t, rt.ElemType.IsNullable, "expected nullable for item at: %d", i) {
   603  			return false
   604  		}
   605  	} else {
   606  		if !assert.False(t, rt.ElemType != nil && rt.ElemType.IsNullable, "expected not nullable for item at: %d", i) {
   607  			return false
   608  		}
   609  	}
   610  
   611  	if val.Aliased {
   612  		if !assert.Equal(t, val.Aliased, rt.IsAliased, "expected (%q, %q) to be an aliased type at: %d", val.Type, val.Format, i) {
   613  			return false
   614  		}
   615  		if !assert.Equal(t, val.AliasedType, rt.AliasedType, "expected %q (%q, %q) to be aliased as %q, but got %q at %d", val.Expected, val.Type, val.Format, val.AliasedType, rt.AliasedType, i) {
   616  			return false
   617  		}
   618  	}
   619  
   620  	if !assertBuiltinSliceElemnResolve(t, val.Type, val.Format, val.Expected, rt, i) {
   621  		return false
   622  	}
   623  	return true
   624  }
   625  
   626  func assertBuiltinAdditionalPropertiesElem(t testing.TB, resolver *typeResolver, aliased bool, i int, val builtinVal) bool {
   627  	val.Nullable = false
   628  	if nullableExtension(val.Extensions) != nil {
   629  		val.Nullable = *nullableExtension(val.Extensions)
   630  	}
   631  	sliceType := "map[string]" + val.Expected
   632  	if val.Nullable {
   633  		sliceType = "map[string]*" + val.Expected
   634  	}
   635  	val.Expected = sliceType
   636  
   637  	val.Aliased = aliased
   638  	if aliased {
   639  		val.AliasedType = val.Expected
   640  		val.Expected = "models.MyAliasedThing"
   641  	}
   642  
   643  	items := new(spec.Schema)
   644  	items.Typed(val.Type, val.Format)
   645  	items.Default = val.Default
   646  	items.ReadOnly = val.ReadOnly
   647  	items.Extensions = val.Extensions
   648  	items.Minimum = val.Minimum
   649  	items.Maximum = val.Maximum
   650  	items.MultipleOf = val.MultipleOf
   651  	items.MinLength = val.MinLength
   652  	items.MaxLength = val.MaxLength
   653  
   654  	sch := spec.MapProperty(items)
   655  
   656  	rt, err := resolver.ResolveSchema(sch, !aliased, val.Required)
   657  	require.NoError(t, err)
   658  
   659  	if val.Nullable {
   660  		if !assert.True(t, rt.ElemType.IsNullable, "expected nullable for item at: %d", i) {
   661  			return false
   662  		}
   663  	} else {
   664  		if !assert.False(t, rt.ElemType != nil && rt.ElemType.IsNullable, "expected not nullable for item at: %d", i) {
   665  			return false
   666  		}
   667  	}
   668  
   669  	if !assert.Equal(t, val.Aliased, rt.IsAliased, "expected (%q, %q) to be an aliased type at %d", val.Type, val.Format, i) {
   670  		return false
   671  	}
   672  
   673  	if val.Aliased {
   674  		if !assert.Equal(t, val.AliasedType, rt.AliasedType, "expected %q (%q, %q) to be aliased as %q, but got %q at %d", val.Expected, val.Type, val.Format, val.AliasedType, rt.AliasedType, i) {
   675  			return false
   676  		}
   677  	}
   678  
   679  	if !assertBuiltinSliceElemnResolve(t, val.Type, val.Format, val.Expected, rt, i) {
   680  		return false
   681  	}
   682  	return true
   683  }
   684  
   685  func assertBuiltinResolve(t testing.TB, tpe, tfmt, exp string, tr resolvedType, i int) bool {
   686  	return assert.Equal(t, tpe, tr.SwaggerType, fmt.Sprintf("expected %q (%q, %q) at %d for the swagger type but got %q", tpe, tfmt, exp, i, tr.SwaggerType)) &&
   687  		assert.Equal(t, tfmt, tr.SwaggerFormat, fmt.Sprintf("expected %q (%q, %q) at %d for the swagger format but got %q", tfmt, tpe, exp, i, tr.SwaggerFormat)) &&
   688  		assert.Equal(t, exp, tr.GoType, fmt.Sprintf("expected %q (%q, %q) at %d for the go type but got %q", exp, tpe, tfmt, i, tr.GoType))
   689  }
   690  
   691  func assertBuiltinSliceElemnResolve(t testing.TB, tpe, tfmt, exp string, tr resolvedType, i int) bool {
   692  	return assert.Equal(t, tpe, tr.ElemType.SwaggerType, fmt.Sprintf("expected %q (%q, %q) at %d for the swagger type but got %q", tpe, tfmt, exp, i, tr.SwaggerType)) &&
   693  		assert.Equal(t, tfmt, tr.ElemType.SwaggerFormat, fmt.Sprintf("expected %q (%q, %q) at %d for the swagger format but got %q", tfmt, tpe, exp, i, tr.SwaggerFormat)) &&
   694  		assert.Equal(t, exp, tr.GoType, fmt.Sprintf("expected %q (%q, %q) at %d for the go type but got %q", exp, tpe, tfmt, i, tr.GoType))
   695  }