* [COMPLIANCE] Update Copyright and License Headers * chore: make gen to generate files with copyright headers * chore: update missed copyright headers --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Justin Nguyen <justin.nguyen@hashicorp.com>
244 lines
6.7 KiB
Go
244 lines
6.7 KiB
Go
// Copyright IBM Corp. 2020, 2025
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package base
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/mitchellh/cli"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestFlagSet_StringSliceMapVar(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
setString string
|
|
wantErrContains string
|
|
wantTarget map[string][]string
|
|
}{
|
|
{
|
|
name: "key-value",
|
|
setString: "key=value",
|
|
wantTarget: map[string][]string{"key": {"value"}},
|
|
},
|
|
{
|
|
name: "many-values",
|
|
setString: "key=v1,v2,v3,v4,v5",
|
|
wantTarget: map[string][]string{"key": {"v1", "v2", "v3", "v4", "v5"}},
|
|
},
|
|
{
|
|
// this case passes here and errors at worker client
|
|
name: "duplicate-values",
|
|
setString: "k1=v1,v1",
|
|
wantTarget: map[string][]string{"k1": {"v1", "v1"}},
|
|
},
|
|
{
|
|
name: "no-deliminator",
|
|
setString: "key",
|
|
wantErrContains: "missing = in KV pair",
|
|
},
|
|
{
|
|
name: "multiple-keys",
|
|
setString: "k1=v1, k2=v2",
|
|
wantErrContains: "value \"k2=v2\" is invalid",
|
|
},
|
|
{
|
|
name: "too-many-commas",
|
|
setString: "k1=v1,,v3?,,,,,v8",
|
|
wantErrContains: "value \"\" is invalid",
|
|
},
|
|
{
|
|
name: "illegal-characters-key",
|
|
setString: "!@#$=%^&*()_",
|
|
wantErrContains: "key \"!@#$\" is invalid",
|
|
},
|
|
{
|
|
name: "illegal-characters-value",
|
|
setString: "k=%^&*()_",
|
|
wantErrContains: "value \"%^&*()_\" is invalid",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
|
|
target := make(map[string][]string, 1)
|
|
sliceMapVal := &stringSliceMapValue{
|
|
hidden: false,
|
|
target: &target,
|
|
}
|
|
|
|
err := sliceMapVal.Set(tt.setString)
|
|
if tt.wantErrContains != "" {
|
|
assert.Error(err)
|
|
assert.Contains(err.Error(), tt.wantErrContains)
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
assert.Equal(tt.wantTarget, *sliceMapVal.target)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFlagSet_StringSliceMapVar_NullCheck(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
setStrings []string
|
|
wantErrContains string
|
|
wantTarget map[string][]string
|
|
}{
|
|
{
|
|
name: "null",
|
|
setStrings: []string{"null"},
|
|
wantTarget: map[string][]string{"null": nil},
|
|
// this target is then converted to a nil value in workerscmd/func.go
|
|
},
|
|
{
|
|
name: "glass-half-null",
|
|
setStrings: []string{"milk=half", "null"},
|
|
wantErrContains: `"null" cannot be combined with other values`,
|
|
},
|
|
{
|
|
name: "invalid-entry-before",
|
|
setStrings: []string{"the-milk-is-bad", "null"},
|
|
wantErrContains: `missing = in KV pair: "the-milk-is-bad"`,
|
|
},
|
|
{
|
|
name: "invalid-entry-after",
|
|
setStrings: []string{"null", "the-milk-is-still-bad"},
|
|
wantErrContains: `"null" cannot be combined with other values`,
|
|
},
|
|
{
|
|
name: "no-error",
|
|
setStrings: []string{"k1=v1,v2,v3", "k2=v4,v5,v6"},
|
|
wantTarget: map[string][]string{"k1": {"v1", "v2", "v3"}, "k2": {"v4", "v5", "v6"}},
|
|
},
|
|
{
|
|
name: "too-null",
|
|
setStrings: []string{"null", "null", "null"},
|
|
wantErrContains: `"null" cannot be combined with other values`,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
|
|
target := make(map[string][]string, 1)
|
|
sliceMapVal := &stringSliceMapValue{
|
|
hidden: false,
|
|
target: &target,
|
|
nullCheck: func() bool { return true },
|
|
}
|
|
var err error
|
|
|
|
for _, s := range tt.setStrings {
|
|
err = sliceMapVal.Set(s)
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
if tt.wantErrContains != "" {
|
|
assert.Error(err)
|
|
assert.Contains(err.Error(), tt.wantErrContains)
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
assert.Equal(tt.wantTarget, *sliceMapVal.target)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUint16Var(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
target := uint16(0)
|
|
|
|
flagSets := NewFlagSets(cli.NewMockUi())
|
|
f := flagSets.NewFlagSet("testset")
|
|
f.Uint16Var(&Uint16Var{
|
|
Name: "test_name",
|
|
Aliases: []string{"test_alias1"},
|
|
Usage: "test_usage",
|
|
Default: 1,
|
|
Hidden: false,
|
|
Target: &target,
|
|
})
|
|
require.Equal(t, uint16(1), target) // Should immediately default.
|
|
|
|
// Value that overflows uint16 should error.
|
|
err := flagSets.Parse([]string{"-test_name", "66000"})
|
|
require.EqualError(t, err, "invalid value \"66000\" for flag -test_name: strconv.ParseUint: parsing \"66000\": value out of range")
|
|
require.Equal(t, uint16(1), target)
|
|
|
|
// Value that overflows uint16 (via alias) should error.
|
|
err = flagSets.Parse([]string{"-test_alias1", "66000"})
|
|
require.EqualError(t, err, "invalid value \"66000\" for flag -test_alias1: strconv.ParseUint: parsing \"66000\": value out of range")
|
|
require.Equal(t, uint16(1), target)
|
|
|
|
// Negative value should error.
|
|
err = flagSets.Parse([]string{"-test_name", "-1"})
|
|
require.EqualError(t, err, "invalid value \"-1\" for flag -test_name: strconv.ParseUint: parsing \"-1\": invalid syntax")
|
|
require.Equal(t, uint16(1), target)
|
|
|
|
// Negative value (via alias) should error.
|
|
err = flagSets.Parse([]string{"-test_alias1", "-1"})
|
|
require.EqualError(t, err, "invalid value \"-1\" for flag -test_alias1: strconv.ParseUint: parsing \"-1\": invalid syntax")
|
|
require.Equal(t, uint16(1), target)
|
|
|
|
// Valid value should be put into target.
|
|
err = flagSets.Parse([]string{"-test_name", "123"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, uint16(123), target)
|
|
|
|
// Valid value (using alias) should be put into target.
|
|
err = flagSets.Parse([]string{"-test_alias1", "456"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, uint16(456), target)
|
|
|
|
// Env var tests.
|
|
envTarget := uint16(0)
|
|
envVarName := "test_uint16_env_var"
|
|
|
|
envFlagSets := NewFlagSets(cli.NewMockUi())
|
|
ef := envFlagSets.NewFlagSet("env_testset")
|
|
|
|
require.NoError(t, os.Setenv(envVarName, "66000"))
|
|
ef.Uint16Var(&Uint16Var{
|
|
Name: "test_env_name1",
|
|
Default: 1,
|
|
EnvVar: envVarName,
|
|
Target: &envTarget,
|
|
})
|
|
require.Equal(t, uint16(1), envTarget) // Should be set to default because env value parse will have failed.
|
|
require.NoError(t, os.Unsetenv(envVarName))
|
|
envTarget = uint16(0)
|
|
|
|
require.NoError(t, os.Setenv(envVarName, "-1"))
|
|
ef.Uint16Var(&Uint16Var{
|
|
Name: "test_env_name2",
|
|
Default: 1,
|
|
EnvVar: envVarName,
|
|
Target: &envTarget,
|
|
})
|
|
require.Equal(t, uint16(1), envTarget) // Should be set to default because env value parse will have failed.
|
|
require.NoError(t, os.Unsetenv(envVarName))
|
|
envTarget = uint16(0)
|
|
|
|
require.NoError(t, os.Setenv(envVarName, "123"))
|
|
ef.Uint16Var(&Uint16Var{
|
|
Name: "test_env_name3",
|
|
Default: 1,
|
|
EnvVar: envVarName,
|
|
Target: &envTarget,
|
|
})
|
|
require.Equal(t, uint16(123), envTarget) // Should be set to what was set in env.
|
|
require.NoError(t, os.Unsetenv(envVarName))
|
|
}
|