Skip to content

Commit

Permalink
add responses delta
Browse files Browse the repository at this point in the history
  • Loading branch information
Reuven committed Jan 22, 2024
1 parent bc58315 commit 3f532a6
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 18 deletions.
19 changes: 17 additions & 2 deletions delta/delta.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ func Get(asymmetric bool, diffReport *diff.Diff) float64 {
return 0
}

delta := getEndpointsDelta(asymmetric, diffReport.EndpointsDiff)
deltaEndpoints := getEndpointsDelta(asymmetric, diffReport.EndpointsDiff)

return delta
return weightedAverage(deltaEndpoints)
}

func ratio(asymmetric bool, added int, deleted int, modifiedDelta float64, all int) float64 {
Expand All @@ -23,3 +23,18 @@ func ratio(asymmetric bool, added int, deleted int, modifiedDelta float64, all i

return (float64(added+deleted) + modifiedDelta) / float64(all)
}

type WeightedDelta struct {
delta float64
weight int
}

func weightedAverage(weightedDeltas ...WeightedDelta) float64 {
dividend := 0.0
divisor := 0
for _, weightedDelta := range weightedDeltas {
dividend += weightedDelta.delta
divisor += weightedDelta.weight
}
return dividend / float64(divisor)
}
13 changes: 13 additions & 0 deletions delta/delta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,16 @@ func TestParameters(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 0.25, delta.Get(true, d))
}

func TestResponses(t *testing.T) {
loader := openapi3.NewLoader()
s1, err := loader.LoadFromFile("../data/simple2.yaml")
require.NoError(t, err)

s2, err := loader.LoadFromFile("../data/simple4.yaml")
require.NoError(t, err)

d, err := diff.Get(diff.NewConfig(), s1, s2)
require.NoError(t, err)
require.Equal(t, 0.0625, delta.Get(true, d))
}
13 changes: 12 additions & 1 deletion delta/doc.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
/*
Package delta provides a distance function for OpenAPI Spec 3.
The delta is a numeric value representing the distance between base and revision specs.
The delta is a numeric value between 0 and 1 representing the distance between base and revision specs.
For any spec, a: delta(a, a) = 0
For any two specs, a and b, with no common elements: delta(a, b) = 1
Symmetric mode:
Delta considers both elements of base that are deleted in revision and elements of base that are added in revision.
For any two specs, a and b: delta(a, b) = delta(b, a)
Asymmetric mode:
Delta only considers elements of base that are deleted in revision but not elements of base that are added in revision.
For any two specs, a and b: Delta(a, b) + Delta(b, a) = 1
*/
package delta
14 changes: 9 additions & 5 deletions delta/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/tufin/oasdiff/diff"
)

func getEndpointsDelta(asymmetric bool, d *diff.EndpointsDiff) float64 {
func getEndpointsDelta(asymmetric bool, d *diff.EndpointsDiff) WeightedDelta {
if d.Empty() {
return 0
return WeightedDelta{}
}

added := len(d.Added)
Expand All @@ -17,7 +17,10 @@ func getEndpointsDelta(asymmetric bool, d *diff.EndpointsDiff) float64 {

modifiedDelta := coefficient * getModifiedEndpointsDelta(asymmetric, d.Modified)

return ratio(asymmetric, added, deleted, modifiedDelta, all)
return WeightedDelta{
delta: ratio(asymmetric, added, deleted, modifiedDelta, all),
weight: 1,
}
}

func getModifiedEndpointsDelta(asymmetric bool, d diff.ModifiedEndpoints) float64 {
Expand All @@ -34,7 +37,8 @@ func getModifiedEndpointDelta(asymmetric bool, d *diff.MethodDiff) float64 {
}

// TODO: consider additional elements of MethodDiff
delta := getParametersDelta(asymmetric, d.ParametersDiff)
paramsDelta := getParametersDelta(asymmetric, d.ParametersDiff)
responsesDelta := getResponsesDelta(asymmetric, d.ResponsesDiff)

return delta
return weightedAverage(paramsDelta, responsesDelta)
}
9 changes: 6 additions & 3 deletions delta/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/tufin/oasdiff/diff"
)

func getParametersDelta(asymmetric bool, d *diff.ParametersDiffByLocation) float64 {
func getParametersDelta(asymmetric bool, d *diff.ParametersDiffByLocation) WeightedDelta {
if d.Empty() {
return 0
return WeightedDelta{}
}

added := d.Added.Len()
Expand All @@ -18,5 +18,8 @@ func getParametersDelta(asymmetric bool, d *diff.ParametersDiffByLocation) float
// TODO: drill down into modified
modifiedDelta := coefficient * float64(modified)

return ratio(asymmetric, added, deleted, modifiedDelta, all)
return WeightedDelta{
delta: ratio(asymmetric, added, deleted, modifiedDelta, all),
weight: all,
}
}
25 changes: 25 additions & 0 deletions delta/responses.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package delta

import (
"github.com/tufin/oasdiff/diff"
)

func getResponsesDelta(asymmetric bool, d *diff.ResponsesDiff) WeightedDelta {
if d.Empty() {
return WeightedDelta{}
}

added := d.Added.Len()
deleted := d.Deleted.Len()
modified := len(d.Modified)
unchanged := d.Unchanged.Len()
all := added + deleted + modified + unchanged

// TODO: drill down into modified
modifiedDelta := coefficient * float64(modified)

return WeightedDelta{
delta: ratio(asymmetric, added, deleted, modifiedDelta, all),
weight: all,
}
}
18 changes: 11 additions & 7 deletions diff/responses_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (

// ResponsesDiff describes the changes between a pair of sets of response objects: https://swagger.io/specification/#responses-object
type ResponsesDiff struct {
Added utils.StringList `json:"added,omitempty" yaml:"added,omitempty"`
Deleted utils.StringList `json:"deleted,omitempty" yaml:"deleted,omitempty"`
Modified ModifiedResponses `json:"modified,omitempty" yaml:"modified,omitempty"`
Added utils.StringList `json:"added,omitempty" yaml:"added,omitempty"`
Deleted utils.StringList `json:"deleted,omitempty" yaml:"deleted,omitempty"`
Modified ModifiedResponses `json:"modified,omitempty" yaml:"modified,omitempty"`
Unchanged utils.StringList `json:"unchanged,omitempty" yaml:"unchanged,omitempty"`
}

// Empty indicates whether a change was found in this element
Expand All @@ -30,9 +31,10 @@ type ModifiedResponses map[string]*ResponseDiff

func newResponsesDiff() *ResponsesDiff {
return &ResponsesDiff{
Added: utils.StringList{},
Deleted: utils.StringList{},
Modified: ModifiedResponses{},
Added: utils.StringList{},
Deleted: utils.StringList{},
Modified: ModifiedResponses{},
Unchanged: utils.StringList{},
}
}

Expand Down Expand Up @@ -73,7 +75,9 @@ func getResponsesDiffInternal(config *Config, state *state, responses1, response
if err != nil {
return nil, err
}
if !diff.Empty() {
if diff.Empty() {
result.Unchanged = append(result.Unchanged, responseValue1)
} else {
result.Modified[responseValue1] = diff
}
} else {
Expand Down

0 comments on commit 3f532a6

Please sign in to comment.