diff --git a/application_test.go b/application_test.go index 219e463..977c5d2 100644 --- a/application_test.go +++ b/application_test.go @@ -59,6 +59,26 @@ func TestApplication_LoadCode(t *testing.T) { require.Len(t, sctx.app.Responses, 11) } +func TestApplication_DebugLogging(t *testing.T) { + // Exercises the debugLogf code path with Debug: true. + _, err := Run(&Options{ + Packages: []string{"./goparsing/petstore/..."}, + WorkDir: "fixtures", + ScanModels: true, + Debug: true, + }) + require.NoError(t, err) +} + +func TestRun_InvalidWorkDir(t *testing.T) { + // Exercises the Run() error path when package loading fails. + _, err := Run(&Options{ + Packages: []string{"./..."}, + WorkDir: "/nonexistent/directory", + }) + require.Error(t, err) +} + func TestAppScanner_NewSpec(t *testing.T) { doc, err := Run(&Options{ Packages: []string{"./goparsing/petstore/..."}, diff --git a/fixtures/goparsing/classification/operations/noparams.go b/fixtures/goparsing/classification/operations/noparams.go index 0c546ec..e703f30 100644 --- a/fixtures/goparsing/classification/operations/noparams.go +++ b/fixtures/goparsing/classification/operations/noparams.go @@ -226,6 +226,18 @@ type NoParams struct { // in: query BarSlice [][][]string `json:"bar_slice"` + // a NumSlice has numeric items with item-level validation + // + // min items: 1 + // max items: 20 + // items.minimum: 5 + // items.maximum: 100 + // items.multiple of: 5 + // items.unique: true + // items.collection format: csv + // in: query + NumSlice []int32 `json:"num_slice"` + // the items for this order // // in: body diff --git a/fixtures/goparsing/go123/special/special_types.go b/fixtures/goparsing/go123/special/special_types.go index 919939a..32be1e7 100644 --- a/fixtures/goparsing/go123/special/special_types.go +++ b/fixtures/goparsing/go123/special/special_types.go @@ -63,6 +63,7 @@ type SpecialTypes struct { PtrFormatUUID *strfmt.UUID Err error Map map[string]*GoStruct + NamedArray GoArray // and what not WhatNot struct { diff --git a/parameters_test.go b/parameters_test.go index 1297f57..ea4691a 100644 --- a/parameters_test.go +++ b/parameters_test.go @@ -181,7 +181,7 @@ func assertSomeOperationParams(t *testing.T, operations map[string]*spec.Operati t.Helper() op, okParam := operations["someOperation"] assert.TrueT(t, okParam) - assert.Len(t, op.Parameters, 12) + assert.Len(t, op.Parameters, 13) for _, param := range op.Parameters { switch param.Name { @@ -215,6 +215,8 @@ func assertSomeOperationParams(t *testing.T, operations map[string]*spec.Operati assert.FalseT(t, param.ExclusiveMinimum) assert.EqualValues(t, 2, param.Default, "%s default value is incorrect", param.Name) assert.EqualValues(t, 27, param.Example) + require.NotNil(t, param.MultipleOf) + assert.InDeltaT(t, 3.00, *param.MultipleOf, epsilon) case paramHdrName: assert.EqualT(t, "Name of this no model instance", param.Description) @@ -368,6 +370,26 @@ func assertSomeOperationParams(t *testing.T, operations map[string]*spec.Operati assert.EqualT(t, int64(10), *itprop3.MaxLength, "'bar_slice.items.items.items.maxLength' should have been 10") assert.EqualT(t, "\\w+", itprop3.Pattern, "'bar_slice.items.items.items.pattern' should have \\w+") + case "num_slice": + assert.EqualT(t, "a NumSlice has numeric items with item-level validation", param.Description) + assert.EqualT(t, "query", param.In) + assert.EqualT(t, "array", param.Type) + require.NotNil(t, param.MinItems) + assert.EqualT(t, int64(1), *param.MinItems) + require.NotNil(t, param.MaxItems) + assert.EqualT(t, int64(20), *param.MaxItems) + + itprop := param.Items + require.NotNil(t, itprop) + require.NotNil(t, itprop.Minimum) + assert.InDeltaT(t, 5.00, *itprop.Minimum, epsilon, "'num_slice.items.minimum' should have been 5") + require.NotNil(t, itprop.Maximum) + assert.InDeltaT(t, 100.00, *itprop.Maximum, epsilon, "'num_slice.items.maximum' should have been 100") + require.NotNil(t, itprop.MultipleOf) + assert.InDeltaT(t, 5.00, *itprop.MultipleOf, epsilon, "'num_slice.items.multipleOf' should have been 5") + assert.TrueT(t, itprop.UniqueItems, "'num_slice.items' should have been unique") + assert.EqualT(t, "csv", itprop.CollectionFormat, "'num_slice.items.collectionFormat' should have been csv") + default: assert.Fail(t, "unknown property: "+param.Name) } @@ -379,7 +401,7 @@ func assertAnotherOperationParamOrder(t *testing.T, operations map[string]*spec. order, ok := operations["anotherOperation"] assert.TrueT(t, ok) - assert.Len(t, order.Parameters, 12) + assert.Len(t, order.Parameters, 13) for index, param := range order.Parameters { switch param.Name { @@ -405,8 +427,10 @@ func assertAnotherOperationParamOrder(t *testing.T, operations map[string]*spec. assert.EqualT(t, 9, index, "%s index incorrect", param.Name) case paramBarSlice: assert.EqualT(t, 10, index, "%s index incorrect", param.Name) - case "items": + case "num_slice": assert.EqualT(t, 11, index, "%s index incorrect", param.Name) + case "items": + assert.EqualT(t, 12, index, "%s index incorrect", param.Name) default: assert.Fail(t, "unknown property: "+param.Name) } diff --git a/parser.go b/parser.go index 92b269b..a9109b5 100644 --- a/parser.go +++ b/parser.go @@ -721,7 +721,7 @@ func (sm *setMultipleOf) Parse(lines []string) error { return nil } matches := sm.rx.FindStringSubmatch(lines[0]) - if len(matches) > 2 && len(matches[1]) > 0 { + if len(matches) > 1 && len(matches[1]) > 0 { multipleOf, err := strconv.ParseFloat(matches[1], 64) if err != nil { return err diff --git a/responses_test.go b/responses_test.go index 1a53a0c..8d23860 100644 --- a/responses_test.go +++ b/responses_test.go @@ -158,6 +158,8 @@ func assertSomeResponseHeaders(t *testing.T, responses map[string]spec.Response) assert.InDeltaT(t, 3.00, *header.Minimum, epsilon) assert.FalseT(t, header.ExclusiveMinimum) assert.EqualValues(t, 27, header.Example) + require.NotNil(t, header.MultipleOf, "'score' should have had a multipleOf") + assert.InDeltaT(t, 3.00, *header.MultipleOf, epsilon, "'score' should have had multipleOf 3") case "x-hdr-name": assert.EqualT(t, "Name of this some response instance", header.Description) diff --git a/schema_test.go b/schema_test.go index 68de053..4d52589 100644 --- a/schema_test.go +++ b/schema_test.go @@ -161,6 +161,8 @@ func TestSchemaBuilder(t *testing.T) { assert.InDeltaT(t, 3.00, *prop.Minimum, epsilon) assert.FalseT(t, prop.ExclusiveMinimum, "'score' should not have had an exclusive minimum") assert.EqualValues(t, 27, prop.Example) + require.NotNil(t, prop.MultipleOf, "'score' should have had a multipleOf") + assert.InDeltaT(t, 3.00, *prop.MultipleOf, epsilon, "'score' should have had multipleOf 3") expectedNameExtensions := spec.Extensions{ "x-go-name": "Name", @@ -1765,6 +1767,12 @@ func testSpecialTypesStruct(t *testing.T, sp *spec.Swagger) { assertIsRef(t, mapSchema, "#/definitions/GoStruct") }) + t.Run("a property which is a named array type should render as a ref", func(t *testing.T) { + na, ok := props["NamedArray"] + require.TrueT(t, ok) + assertIsRef(t, &na, "#/definitions/go_array") + }) + testSpecialTypesWhatNot(t, sp, props) }) }