Skip to content

Commit

Permalink
Add helper function to compare Options (#268)
Browse files Browse the repository at this point in the history
* add OptionsEqual

* allow unexported and add unit test

* add OptionSlicesEqual

* remove comment about unexported struct
  • Loading branch information
sfc-gh-elinardi authored Jul 6, 2023
1 parent ec9a0e4 commit acbf5c6
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
26 changes: 26 additions & 0 deletions services/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"syscall"

"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

Expand Down Expand Up @@ -80,6 +81,31 @@ func (f optionfunc) apply(opts *cmdOptions) {
f(opts)
}

// OptionsEqual returns true if the results of applying both Options are equal
func OptionsEqual(a, b Option) bool {
aCmdOptions := &cmdOptions{}
bCmdOptions := &cmdOptions{}
a.apply(aCmdOptions)
b.apply(bCmdOptions)

return cmp.Equal(aCmdOptions, bCmdOptions, cmp.AllowUnexported(cmdOptions{}))
}

// OptionsEqual returns true if the results of applying all elements of both Option slices are equal
func OptionSlicesEqual(a, b []Option) bool {
aCmdOptions := &cmdOptions{}
bCmdOptions := &cmdOptions{}

for _, opt := range a {
opt.apply(aCmdOptions)
}
for _, opt := range b {
opt.apply(bCmdOptions)
}

return cmp.Equal(aCmdOptions, bCmdOptions, cmp.AllowUnexported(cmdOptions{}))
}

// FailOnStderr is an option where the command will return an error if any output appears on stderr
// regardless of exit code. As we're often parsing the text output of specific commands as root
// this is a sanity check we're getting expected output. i.e. ps never returns anything on stderr
Expand Down
85 changes: 85 additions & 0 deletions services/util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,88 @@ func TestIntSliceFlag(t *testing.T) {
t.Fatal("didn't get error from bad flag set as we should")
}
}

func TestOptionsSliceEqual(t *testing.T) {
for _, tc := range []struct {
optionA []Option
optionB []Option
expectedResult bool
name string
}{
{
name: "multiple EnvVars",
optionA: []Option{EnvVar("A=A"), EnvVar("B=B")},
optionB: []Option{EnvVar("A=A"), EnvVar("B=B")},
expectedResult: true,
},
{
name: "should be true because FailOnStdErr is idempotent",
optionA: []Option{FailOnStderr(), FailOnStderr()},
optionB: []Option{FailOnStderr()},
expectedResult: true,
},
{
name: "Ordering of idempotent funcs shouldn't matter",
optionA: []Option{StdoutMax(3), EnvVar("A=A")},
optionB: []Option{EnvVar("A=A"), StdoutMax(3)},
expectedResult: true,
},
{
name: "EnvVar ordering does matter",
optionA: []Option{EnvVar("A=A"), EnvVar("B=B")},
optionB: []Option{EnvVar("B=B"), EnvVar("A=A")},
expectedResult: false,
},
{
optionA: []Option{CommandGroup(1)},
optionB: []Option{CommandUser(2), EnvVar("FOO=BAR")},
expectedResult: false,
},
} {
tc := tc
result := OptionSlicesEqual(tc.optionA, tc.optionB)
if result != tc.expectedResult {
t.Fatalf("test %s failed: expected %v, got %v", tc.name, tc.expectedResult, result)
}
}
}

func TestOptionsEqual(t *testing.T) {
for _, tc := range []struct {
optionA Option
optionB Option
expectedResult bool
}{
{
optionA: EnvVar(""),
optionB: EnvVar(""),
expectedResult: true,
},
{
optionA: FailOnStderr(),
optionB: FailOnStderr(),
expectedResult: true,
},
{
optionA: EnvVar("SANSSHELL_PROXY=sansshell.com"),
optionB: EnvVar("SANSSHELL_PROXY=sansshell.com"),
expectedResult: true,
},
{
optionA: EnvVar(""),
optionB: EnvVar("FOO=false"),
expectedResult: false,
},
{
optionA: CommandGroup(1),
optionB: CommandUser(2),
expectedResult: false,
},
} {
tc := tc
result := OptionsEqual(tc.optionA, tc.optionB)
if result != tc.expectedResult {
t.Fatalf("expected %v, got %v", tc.expectedResult, result)
}
}
}

0 comments on commit acbf5c6

Please sign in to comment.