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