Files
2026-07-22 14:07:49 -07:00

115 lines
3.5 KiB
Go

// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package maincli
import (
"reflect"
"testing"
"github.com/google/subcommands"
"gvisor.dev/gvisor/runsc/cmd"
"gvisor.dev/gvisor/runsc/flag"
)
var fakeFlagValues = [...]string{
"1",
"2:2",
"foo",
"none",
"never",
"1,2,3",
"2h45m",
"1:1,2:2",
"0 0 1,100000 100000 65536",
"lisafs:self,lisafs:none",
}
func dupFlag(t *testing.T, cmd subcommands.Command, flagName string) *flag.Flag {
// To create a true duplicate of the flag, we need to duplicate the command
// and its FlagSet.
var cmd2 subcommands.Command
var fs2 flag.FlagSet
cmd2 = reflect.New(reflect.TypeOf(cmd).Elem()).Interface().(subcommands.Command)
cmd2.SetFlags(&fs2)
flag2 := fs2.Lookup(flagName)
if flag2 == nil {
t.Fatalf("duplicate FlagSet does not contain flag %q for cmd %q", flagName, cmd.Name())
}
return flag2
}
// Tests that all the flags in all commands are idempotent; i.e. Set(String())
// should be an idempotent operation.
func TestFlagSetIdempotent(t *testing.T) {
cmds := make(map[string][]subcommands.Command)
nonIdempotentCommands := map[string]bool{
new(cmd.Exec).Name(): true,
}
allCommands, _ := commands()
for cmd, group := range allCommands {
// Skip commands that are known to be non-idempotent.
if _, ok := nonIdempotentCommands[cmd.Name()]; ok {
continue
}
if cmdList, ok := cmds[group]; ok {
cmds[group] = append(cmdList, cmd)
} else {
cmds[group] = []subcommands.Command{cmd}
}
}
for group, cmdList := range cmds {
t.Run(group, func(t *testing.T) {
for _, cmd := range cmdList {
t.Run(cmd.Name(), func(t *testing.T) {
var fs flag.FlagSet
cmd.SetFlags(&fs)
// Iterate through all flags configured by this command.
fs.VisitAll(func(flag *flag.Flag) {
// Try a list of possible values for this flag.
matchedOneFlag := false
for _, v := range fakeFlagValues {
// Set() may have side effects even when it fails. So create a new
// flag for each try.
curFlag := dupFlag(t, cmd, flag.Name)
if err := curFlag.Value.Set(v); err != nil {
continue
}
// Worked. Now test that this flag is idempotent.
oldValue := curFlag.Value.String()
// Get a fresh flag.Flag to Set() this old value on.
newFlag := dupFlag(t, cmd, flag.Name)
if err := newFlag.Value.Set(oldValue); err != nil {
t.Errorf("flag %q from cmd %q is not idempotent: oldValue = %q, err = %v", flag.Name, cmd.Name(), oldValue, err)
return
}
// Compare this new flag value with old value.
if newValue := newFlag.Value.String(); newValue != oldValue {
t.Errorf("flag %q from cmd %q is not idempotent: oldValue = %q, newValue = %q", flag.Name, cmd.Name(), oldValue, newValue)
return
}
matchedOneFlag = true
}
if !matchedOneFlag {
t.Fatalf("none of the fake flag values work for flag %q from cmd %q", flag.Name, cmd.Name())
}
})
})
}
})
}
}