Skip to content

Commit

Permalink
simpify delta func
Browse files Browse the repository at this point in the history
  • Loading branch information
Reuven committed Jan 18, 2024
1 parent 9361ae3 commit a623b3b
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 89 deletions.
2 changes: 1 addition & 1 deletion data/simple3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ paths:
description: OK
post:
responses:
200:
201:
description: OK
17 changes: 17 additions & 0 deletions data/simple4.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
info:
title: Tufin
version: 1.0.0
openapi: 3.0.3
paths:
/api/test:
get:
parameters:
- name: a
in: query
responses:
200:
description: OK
post:
responses:
201:
description: OK
42 changes: 0 additions & 42 deletions delta/calc.go

This file was deleted.

25 changes: 25 additions & 0 deletions delta/delta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package delta

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

const coefficient = 0.5

func Get(asymmetric bool, diffReport *diff.Diff) float64 {
if diffReport.Empty() {
return 0
}

delta := getEndpointsDelta(asymmetric, diffReport.EndpointsDiff)

return delta
}

func ratio(asymmetric bool, added int, deleted int, modifiedDelta float64, all int) float64 {
if asymmetric {
added = 0
}

return (float64(added+deleted) + modifiedDelta) / float64(all)
}
48 changes: 37 additions & 11 deletions delta/calc_test.go → delta/delta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/tufin/oasdiff/utils"
)

func TestCalc_EndpointAdded(t *testing.T) {
func TestEndpointAdded(t *testing.T) {
loader := openapi3.NewLoader()
s1, err := loader.LoadFromFile("../data/simple1.yaml")
require.NoError(t, err)
Expand All @@ -20,10 +20,23 @@ func TestCalc_EndpointAdded(t *testing.T) {

d, err := diff.Get(diff.NewConfig(), s1, s2)
require.NoError(t, err)
require.Equal(t, delta.Get(false, d, s1, s2), 0.25)
require.Equal(t, 0.5, delta.Get(false, d))
}

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

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

d, err := diff.Get(diff.NewConfig(), s1, s2)
require.NoError(t, err)
require.Equal(t, 0.5, delta.Get(true, d))
}

func TestEndpointAddedAndDeleted(t *testing.T) {
loader := openapi3.NewLoader()
s1, err := loader.LoadFromFile("../data/simple1.yaml")
require.NoError(t, err)
Expand All @@ -33,11 +46,11 @@ func TestCalc_EndpointAddedAndDeleted(t *testing.T) {

d, err := diff.Get(diff.NewConfig(), s1, s2)
require.NoError(t, err)
require.Equal(t, delta.Get(false, d, s1, s2), 1.0)
require.Equal(t, 1.0, delta.Get(false, d))
}

func TestSymmetric(t *testing.T) {
specs := utils.StringList{"../data/simple.yaml", "../data/simple1.yaml", "../data/simple2.yaml", "../data/simple3.yaml"}
specs := utils.StringList{"../data/simple.yaml", "../data/simple1.yaml", "../data/simple2.yaml", "../data/simple3.yaml", "../data/simple4.yaml"}
specPairs := specs.CartesianProduct(specs)

loader := openapi3.NewLoader()
Expand All @@ -54,12 +67,12 @@ func TestSymmetric(t *testing.T) {
d2, err := diff.Get(diff.NewConfig(), s2, s1)
require.NoError(t, err)

require.Equal(t, delta.Get(false, d1, s1, s2), delta.Get(false, d2, s2, s1), pair)
require.Equal(t, delta.Get(false, d1), delta.Get(false, d2), pair)
}
}

func TestAsymmetric(t *testing.T) {
specs := utils.StringList{"../data/simple.yaml", "../data/simple1.yaml", "../data/simple2.yaml", "../data/simple3.yaml"}
specs := utils.StringList{"../data/simple.yaml", "../data/simple1.yaml", "../data/simple2.yaml", "../data/simple3.yaml", "../data/simple4.yaml"}
specPairs := specs.CartesianProduct(specs)

loader := openapi3.NewLoader()
Expand All @@ -72,14 +85,27 @@ func TestAsymmetric(t *testing.T) {

d1, err := diff.Get(diff.NewConfig(), s1, s2)
require.NoError(t, err)
asymmetric1 := delta.Get(true, d1, s1, s2)
asymmetric1 := delta.Get(true, d1)

d2, err := diff.Get(diff.NewConfig(), s2, s1)
require.NoError(t, err)
asymmetric2 := delta.Get(true, d2, s2, s1)
asymmetric2 := delta.Get(true, d2)

symmetric := delta.Get(false, d2, s2, s1)
symmetric := delta.Get(false, d2)

require.Equal(t, utils.Average(asymmetric1, asymmetric2), symmetric, pair)
require.Equal(t, asymmetric1+asymmetric2, symmetric, pair)
}
}

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

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

d, err := diff.Get(diff.NewConfig(), s1, s2)
require.NoError(t, err)
require.Equal(t, 0.25, delta.Get(true, d))
}
40 changes: 40 additions & 0 deletions delta/endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package delta

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

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

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

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

return ratio(asymmetric, added, deleted, modifiedDelta, all)
}

func getModifiedEndpointsDelta(asymmetric bool, d diff.ModifiedEndpoints) float64 {
result := 0.0
for _, methodDiff := range d {
result += getModifiedEndpointDelta(asymmetric, methodDiff)
}
return result
}

func getModifiedEndpointDelta(asymmetric bool, d *diff.MethodDiff) float64 {
if d.Empty() {
return 0
}

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

return delta
}
22 changes: 22 additions & 0 deletions delta/parameters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package delta

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

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

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

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

return ratio(asymmetric, added, deleted, modifiedDelta, all)
}
7 changes: 4 additions & 3 deletions diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ func TestDiff_ModifiedOperation(t *testing.T) {
require.NoError(t, err)

require.Equal(t, &diff.OperationsDiff{
Added: utils.StringList{"GET"},
Deleted: utils.StringList{"POST"},
Modified: diff.ModifiedOperations{},
Added: utils.StringList{"GET"},
Deleted: utils.StringList{"POST"},
Modified: diff.ModifiedOperations{},
Unchanged: utils.StringList{},
},
d.PathsDiff.Modified["/api/test"].OperationsDiff)
}
Expand Down
25 changes: 19 additions & 6 deletions diff/endpoints_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ For example, if there's a new path "/test" with method POST then EndpointsDiff w
Or, if path "/test" was modified to include a new methdod, PUT, then EndpointsDiff will describe this as a new endpoint: PUT /test.
*/
type EndpointsDiff struct {
Added Endpoints `json:"added,omitempty" yaml:"added,omitempty"`
Deleted Endpoints `json:"deleted,omitempty" yaml:"deleted,omitempty"`
Modified ModifiedEndpoints `json:"modified,omitempty" yaml:"modified,omitempty"`
Added Endpoints `json:"added,omitempty" yaml:"added,omitempty"`
Deleted Endpoints `json:"deleted,omitempty" yaml:"deleted,omitempty"`
Modified ModifiedEndpoints `json:"modified,omitempty" yaml:"modified,omitempty"`
Unchanged Endpoints `json:"unchanged,omitempty" yaml:"unchanged,omitempty"`
}

// Endpoint is a combination of an HTTP method and a Path
Expand All @@ -37,9 +38,10 @@ func (diff *EndpointsDiff) Empty() bool {

func newEndpointsDiff() *EndpointsDiff {
return &EndpointsDiff{
Added: Endpoints{},
Deleted: Endpoints{},
Modified: ModifiedEndpoints{},
Added: Endpoints{},
Deleted: Endpoints{},
Modified: ModifiedEndpoints{},
Unchanged: Endpoints{},
}
}

Expand Down Expand Up @@ -109,6 +111,13 @@ func (diff *EndpointsDiff) addDeletedPath(path string, method string) {
})
}

func (diff *EndpointsDiff) addUnchangedPath(path string, method string) {
diff.Unchanged = append(diff.Unchanged, Endpoint{
Method: method,
Path: path,
})
}

func (diff *EndpointsDiff) addModifiedPaths(config *Config, state *state, path string, pathItemPair *pathItemPair) error {

pathDiff, err := getPathDiff(config, state, pathItemPair)
Expand All @@ -135,6 +144,10 @@ func (diff *EndpointsDiff) addModifiedPaths(config *Config, state *state, path s
}] = methodDiff
}

for _, method := range pathDiff.OperationsDiff.Unchanged {
diff.addUnchangedPath(path, method)
}

return nil
}

Expand Down
16 changes: 10 additions & 6 deletions diff/operations_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import (

// OperationsDiff describes the changes between a pair of operation objects (https://swagger.io/specification/#operation-object) of two path item objects
type OperationsDiff struct {
Added utils.StringList `json:"added,omitempty" yaml:"added,omitempty"`
Deleted utils.StringList `json:"deleted,omitempty" yaml:"deleted,omitempty"`
Modified ModifiedOperations `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 ModifiedOperations `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 @@ -29,9 +30,10 @@ func (operationsDiff *OperationsDiff) Empty() bool {

func newOperationsDiff() *OperationsDiff {
return &OperationsDiff{
Added: utils.StringList{},
Deleted: utils.StringList{},
Modified: ModifiedOperations{},
Added: utils.StringList{},
Deleted: utils.StringList{},
Modified: ModifiedOperations{},
Unchanged: utils.StringList{},
}
}

Expand Down Expand Up @@ -105,6 +107,8 @@ func (operationsDiff *OperationsDiff) diffOperation(config *Config, state *state

if !diff.Empty() {
operationsDiff.Modified[method] = diff
} else {
operationsDiff.Unchanged = append(operationsDiff.Unchanged, method)
}

return nil
Expand Down
Loading

0 comments on commit a623b3b

Please sign in to comment.