diff --git a/datamodel/high/base/schema_test.go b/datamodel/high/base/schema_test.go index 6657463..58a67bb 100644 --- a/datamodel/high/base/schema_test.go +++ b/datamodel/high/base/schema_test.go @@ -164,7 +164,17 @@ xml: externalDocs: url: https://pb33f.io/docs enum: [fish, cake] -required: [cake, fish]` +required: [cake, fish] +maxLength: 10 +minLength: 1 +maxItems: 10 +minItems: 1 +maxProperties: 10 +minProperties: 1 +nullable: true +readOnly: true +writeOnly: false +deprecated: true` var compNode yaml.Node _ = yaml.Unmarshal([]byte(testSpec), &compNode) diff --git a/datamodel/low/base/discriminator_test.go b/datamodel/low/base/discriminator_test.go index 85e9e94..37de719 100644 --- a/datamodel/low/base/discriminator_test.go +++ b/datamodel/low/base/discriminator_test.go @@ -26,3 +26,26 @@ mapping: assert.Nil(t, n.FindMappingValue("freshCakes")) } + +func TestDiscriminator_Hash(t *testing.T) { + + left := `propertyName: freshCakes +mapping: + something: nothing` + + right := `mapping: + something: nothing +propertyName: freshCakes` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc Discriminator + var rDoc Discriminator + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + + assert.Equal(t, lDoc.Hash(), rDoc.Hash()) +} diff --git a/datamodel/low/base/example_test.go b/datamodel/low/base/example_test.go index 88234dd..e2be3d3 100644 --- a/datamodel/low/base/example_test.go +++ b/datamodel/low/base/example_test.go @@ -124,9 +124,44 @@ value: } +func TestExample_Hash(t *testing.T) { + + left := `summary: hot +description: cakes +x-burger: nice +externalValue: cake +value: + pizza: oven + yummy: pizza` + + right := `externalValue: cake +summary: hot +value: + pizza: oven + yummy: pizza +description: cakes +x-burger: nice` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc Example + var rDoc Example + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + assert.Equal(t, lDoc.Hash(), rDoc.Hash()) + assert.Len(t, lDoc.GetExtensions(), 1) +} + func TestExtractExampleValue(t *testing.T) { assert.True(t, ExtractExampleValue(&yaml.Node{Tag: "!!bool", Value: "true"}).(bool)) assert.Equal(t, int64(10), ExtractExampleValue(&yaml.Node{Tag: "!!int", Value: "10"}).(int64)) assert.Equal(t, 33.2, ExtractExampleValue(&yaml.Node{Tag: "!!float", Value: "33.2"}).(float64)) + assert.Equal(t, "WHAT A NICE COW", ExtractExampleValue(&yaml.Node{Tag: "!!str", Value: "WHAT A NICE COW"})) } diff --git a/datamodel/low/base/external_doc.go b/datamodel/low/base/external_doc.go index 129e2c8..5f20fda 100644 --- a/datamodel/low/base/external_doc.go +++ b/datamodel/low/base/external_doc.go @@ -35,9 +35,6 @@ func (ex *ExternalDoc) Build(root *yaml.Node, idx *index.SpecIndex) error { // GetExtensions returns all ExternalDoc extensions and satisfies the low.HasExtensions interface. func (ex *ExternalDoc) GetExtensions() map[low.KeyReference[string]]low.ValueReference[any] { - if ex == nil { - return nil - } return ex.Extensions } diff --git a/datamodel/low/base/external_doc_test.go b/datamodel/low/base/external_doc_test.go index d5f547f..d309ab9 100644 --- a/datamodel/low/base/external_doc_test.go +++ b/datamodel/low/base/external_doc_test.go @@ -53,3 +53,29 @@ x-b33f: princess` assert.Equal(t, "princess", ext.Value) } + +func TestExternalDoc_Hash(t *testing.T) { + + left := `url: https://pb33f.io +description: the ranch +x-b33f: princess` + + right := `url: https://pb33f.io +x-b33f: princess +description: the ranch` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc ExternalDoc + var rDoc ExternalDoc + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + assert.Equal(t, lDoc.Hash(), rDoc.Hash()) + assert.Len(t, lDoc.GetExtensions(), 1) +} diff --git a/datamodel/low/base/schema.go b/datamodel/low/base/schema.go index c5a5aa0..d9d4b16 100644 --- a/datamodel/low/base/schema.go +++ b/datamodel/low/base/schema.go @@ -107,7 +107,6 @@ type Schema struct { // Hash will calculate a SHA256 hash from the values of the schema, This allows equality checking against // Schemas defined inside an OpenAPI document. The only way to know if a schema has changed, is to hash it. -// Polymorphic items func (s *Schema) Hash() [32]byte { // calculate a hash from every property in the schema. v := "%v" @@ -265,10 +264,14 @@ func (s *Schema) Hash() [32]byte { if s.Example.Value != nil { d = append(d, low.GenerateHashString(s.Example.Value)) } - for w := range s.Examples.Value { - d = append(d, low.GenerateHashString(s.Examples.Value[w])) + if !s.Examples.IsEmpty() { + var xph []string + for w := range s.Examples.Value { + xph = append(xph, low.GenerateHashString(s.Examples.Value[w].Value)) + } + sort.Strings(xph) + d = append(d, strings.Join(xph, "|")) } - return sha256.Sum256([]byte(strings.Join(d, "|"))) } diff --git a/datamodel/low/base/schema_proxy_test.go b/datamodel/low/base/schema_proxy_test.go index 8f26172..3778a90 100644 --- a/datamodel/low/base/schema_proxy_test.go +++ b/datamodel/low/base/schema_proxy_test.go @@ -20,4 +20,7 @@ func TestSchemaProxy_Build(t *testing.T) { err := sch.Build(&idxNode, nil) assert.NoError(t, err) assert.Equal(t, "something", sch.Schema().Description.Value) + assert.Empty(t, sch.GetSchemaReference()) + assert.NotNil(t, sch.GetValueNode()) + assert.False(t, sch.IsSchemaReference()) } diff --git a/datamodel/low/base/schema_test.go b/datamodel/low/base/schema_test.go index d13da1b..72ce849 100644 --- a/datamodel/low/base/schema_test.go +++ b/datamodel/low/base/schema_test.go @@ -9,8 +9,8 @@ import ( "testing" ) -func Test_Schema(t *testing.T) { - testSpec := `type: object +func test_get_schema_blob() string { + return `type: object description: something object discriminator: propertyName: athing @@ -105,7 +105,20 @@ properties: additionalProperties: why: yes thatIs: true -additionalProperties: true ` +additionalProperties: true +required: + - them +enum: + - one + - two +x-pizza: tasty +examples: + - hey + - hi!` +} + +func Test_Schema(t *testing.T) { + testSpec := test_get_schema_blob() var rootNode yaml.Node mErr := yaml.Unmarshal([]byte(testSpec), &rootNode) @@ -229,6 +242,26 @@ additionalProperties: true ` assert.Equal(t, "party", mv.Value) } +func TestSchema_Hash(t *testing.T) { + + //create two versions + testSpec := test_get_schema_blob() + var sc1n yaml.Node + _ = yaml.Unmarshal([]byte(testSpec), &sc1n) + sch1 := Schema{} + _ = low.BuildModel(&sc1n, &sch1) + _ = sch1.Build(sc1n.Content[0], nil) + + var sc2n yaml.Node + _ = yaml.Unmarshal([]byte(testSpec), &sc2n) + sch2 := Schema{} + _ = low.BuildModel(&sc2n, &sch2) + _ = sch2.Build(sc2n.Content[0], nil) + + assert.Equal(t, sch1.Hash(), sch2.Hash()) + +} + func Test_Schema_31(t *testing.T) { testSpec := `$schema: https://something type: