-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scheduler: annotate tasksUpdated with reason and purge DeepEquals (#1…
…6421) * scheduler: annotate tasksUpdated with reason and purge DeepEquals * cr: move opaque into helper * cr: swap affinity/spread hashing for slice equal * contributing: update checklist-jobspec with notes about struct methods * cr: add more cases to wait config equal method * cr: use reflect when comparing envoy config blocks * cl: add cl
- Loading branch information
Showing
13 changed files
with
1,163 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:improvement | ||
scheduler: remove most uses of reflection for task comparisons | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package helper | ||
|
||
import ( | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/google/go-cmp/cmp/cmpopts" | ||
"golang.org/x/exp/maps" | ||
) | ||
|
||
var ( | ||
cmpOptIgnoreUnexported = ignoreUnexportedAlways() | ||
cmpOptNilIsEmpty = cmpopts.EquateEmpty() | ||
cmpOptIgnore = cmp.Ignore() | ||
) | ||
|
||
// ignoreUnexportedAlways creates a cmp.Option filter that will ignore unexported | ||
// fields of on any/all types. It is a derivative of go-cmp.IgnoreUnexported, | ||
// here we do not require specifying individual types. | ||
// | ||
// reference: https://github.com/google/go-cmp/blob/master/cmp/cmpopts/ignore.go#L110 | ||
func ignoreUnexportedAlways() cmp.Option { | ||
return cmp.FilterPath( | ||
func(p cmp.Path) bool { | ||
sf, ok := p.Index(-1).(cmp.StructField) | ||
if !ok { | ||
return false | ||
} | ||
c := sf.Name()[0] | ||
return c < 'A' || c > 'Z' | ||
}, | ||
cmpOptIgnore, | ||
) | ||
} | ||
|
||
// OpaqueMapsEqual compare maps[<comparable>]<any> for equality, but safely by | ||
// using the cmp package and ignoring un-exported types, and by treating nil/empty | ||
// slices and maps as equal. | ||
// | ||
// This is intended as a substitute for reflect.DeepEqual in the case of "opaque maps", | ||
// e.g. `map[comparable]any` - such as the case for Task Driver config or Envoy proxy | ||
// pass-through configuration. | ||
func OpaqueMapsEqual[M ~map[K]V, K comparable, V any](m1, m2 M) bool { | ||
return maps.EqualFunc(m1, m2, func(a, b V) bool { | ||
return cmp.Equal(a, b, | ||
cmpOptIgnoreUnexported, // ignore all unexported fields | ||
cmpOptNilIsEmpty, // treat nil/empty slices as equal | ||
) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package helper | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/hashicorp/nomad/ci" | ||
"github.com/shoenig/test/must" | ||
) | ||
|
||
func Test_OpaqueMapsEqual(t *testing.T) { | ||
ci.Parallel(t) | ||
|
||
type public struct { | ||
F int | ||
} | ||
|
||
type private struct { | ||
g int | ||
} | ||
|
||
type mix struct { | ||
F int | ||
g int | ||
} | ||
|
||
cases := []struct { | ||
name string | ||
a, b map[string]any | ||
exp bool | ||
}{{ | ||
name: "both nil", | ||
a: nil, | ||
b: nil, | ||
exp: true, | ||
}, { | ||
name: "empty and nil", | ||
a: nil, | ||
b: make(map[string]any), | ||
exp: true, | ||
}, { | ||
name: "same strings", | ||
a: map[string]any{"a": "A"}, | ||
b: map[string]any{"a": "A"}, | ||
exp: true, | ||
}, { | ||
name: "same public struct", | ||
a: map[string]any{"a": &public{F: 42}}, | ||
b: map[string]any{"a": &public{F: 42}}, | ||
exp: true, | ||
}, { | ||
name: "different public struct", | ||
a: map[string]any{"a": &public{F: 42}}, | ||
b: map[string]any{"a": &public{F: 10}}, | ||
exp: false, | ||
}, { | ||
name: "different private struct", | ||
a: map[string]any{"a": &private{g: 42}}, | ||
b: map[string]any{"a": &private{g: 10}}, | ||
exp: true, // private fields not compared | ||
}, { | ||
name: "mix same public different private", | ||
a: map[string]any{"a": &mix{F: 42, g: 1}}, | ||
b: map[string]any{"a": &mix{F: 42, g: 2}}, | ||
exp: true, // private fields not compared | ||
}, { | ||
name: "mix different public same private", | ||
a: map[string]any{"a": &mix{F: 42, g: 1}}, | ||
b: map[string]any{"a": &mix{F: 10, g: 1}}, | ||
exp: false, | ||
}, { | ||
name: "nil vs empty slice values", | ||
a: map[string]any{"key": []string(nil)}, | ||
b: map[string]any{"key": make([]string, 0)}, | ||
exp: true, | ||
}, { | ||
name: "nil vs empty map values", | ||
a: map[string]any{"key": map[int]int(nil)}, | ||
b: map[string]any{"key": make(map[int]int, 0)}, | ||
exp: true, | ||
}} | ||
|
||
for _, tc := range cases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
result := OpaqueMapsEqual(tc.a, tc.b) | ||
must.Eq(t, tc.exp, result) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.