Files
wehub-resource-sync 5357c39144
Fuzzer / Run Fuzzer (push) Has been cancelled
Race tests / Go race tests (ubuntu-22.04) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:01:40 +08:00

312 lines
8.3 KiB
Go

// Copyright 2020 Dolthub, Inc.
//
// 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 argparser
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func createParserWithOptionalArgs() *ArgParser {
ap := NewArgParserWithMaxArgs("test", 16)
ap.SupportsFlag("flag", "f", "flag")
ap.SupportsString("param", "p", "param", "")
ap.SupportsOptionalString("optional", "o", "optional", "")
return ap
}
func TestArgParser(t *testing.T) {
tests := []struct {
ap *ArgParser
args []string
expectedErr error
expectedOptions map[string]string
expectedArgs []string
}{
{
NewArgParserWithVariableArgs("test"),
[]string{},
nil,
map[string]string{},
[]string{},
},
{
NewArgParserWithVariableArgs("test"),
[]string{"arg1", "arg2"},
nil,
map[string]string{},
[]string{"arg1", "arg2"},
},
{
NewArgParserWithVariableArgs("test"),
[]string{"--unknown_flag"},
UnknownArgumentParam{"unknown_flag"},
map[string]string{},
[]string{},
},
{
NewArgParserWithVariableArgs("test"),
[]string{"--help"},
ErrHelp,
map[string]string{},
[]string{},
},
{
NewArgParserWithVariableArgs("test"),
[]string{"-h"},
ErrHelp,
map[string]string{},
[]string{},
},
{
NewArgParserWithVariableArgs("test"),
[]string{"help"},
nil,
map[string]string{},
[]string{"help"},
},
{
NewArgParserWithVariableArgs("test").SupportsString("param", "p", "", ""),
[]string{"--param", "value", "arg1"},
nil,
map[string]string{"param": "value"},
[]string{"arg1"},
},
{
NewArgParserWithVariableArgs("test").SupportsString("param", "p", "", ""),
[]string{"-pvalue"},
nil,
map[string]string{"param": "value"},
[]string{},
},
{
NewArgParserWithVariableArgs("test").SupportsString("param", "p", "", ""),
[]string{"--paramvalue"},
UnknownArgumentParam{"paramvalue"},
map[string]string{},
[]string{},
},
{
createParserWithOptionalArgs(),
[]string{"foo", "bar"},
nil,
map[string]string{},
[]string{"foo", "bar"},
},
{
createParserWithOptionalArgs(),
[]string{"-o", "-f", "foo", "bar"},
nil,
map[string]string{"flag": "", "optional": ""},
[]string{"foo", "bar"},
},
{
createParserWithOptionalArgs(),
[]string{"-o", "optional value", "-f", "foo", "bar"},
nil,
map[string]string{"flag": "", "optional": "optional value"},
[]string{"foo", "bar"},
},
{
createParserWithOptionalArgs(),
[]string{"-o", "--", "foo", "bar"},
nil,
map[string]string{"optional": ""},
[]string{"foo", "bar"},
},
{
createParserWithOptionalArgs(),
[]string{"-p", "value", "-o"},
nil,
map[string]string{"param": "value", "optional": ""},
[]string{},
},
{
createParserWithOptionalArgs(),
[]string{"-p", "value", "-o", "--"},
nil,
map[string]string{"param": "value", "optional": ""},
[]string{},
},
{
createParserWithOptionalArgs(),
[]string{"-o", "-p", "value"},
nil,
map[string]string{"param": "value", "optional": ""},
[]string{},
},
{
NewArgParserWithVariableArgs("test").SupportsString("param", "p", "", ""),
[]string{"--param", "value", "arg1", "--", "table1", "table2"},
nil,
map[string]string{"param": "value"},
[]string{"arg1", "table1", "table2"},
},
}
for _, test := range tests {
apr, err := test.ap.Parse(test.args)
require.Equal(t, test.expectedErr, err)
if err == nil {
assert.Equal(t, test.expectedOptions, apr.options)
assert.Equal(t, test.expectedArgs, apr.Args)
}
}
}
func TestArgParserSet(t *testing.T) {
ap := createParserWithOptionalArgs()
apr, err := ap.Parse([]string{"-o", "optional value", "-f", "foo", "bar"})
require.NoError(t, err)
apr, err = apr.SetArgument("param", "abcdefg")
require.NoError(t, err)
assert.Equal(t, map[string]string{"flag": "", "optional": "optional value", "param": "abcdefg"}, apr.options)
apr, err = apr.SetArgument("garbage", "garbage value")
require.Error(t, err)
}
func TestRepeatableFlags(t *testing.T) {
ap := NewArgParserWithVariableArgs("test")
ap.SupportsRepeatableFlag("verbose", "v", "Verbose output")
testCases := []struct {
args []string
expectedCount int
expectError bool
}{
{[]string{"-v"}, 1, false},
{[]string{"-vv"}, 2, false},
{[]string{"-vvv"}, 3, false},
{[]string{"-vvvv"}, 4, false},
{[]string{"--verbose"}, 1, false},
{[]string{"--verbose", "--verbose"}, 2, false},
{[]string{"--verbose", "-v"}, 2, false},
{[]string{"--verbose", "-vv"}, 3, false},
{[]string{"-v", "-v"}, 2, false},
{[]string{"-v", "-vv"}, 3, false},
{[]string{"-vv", "-v"}, 3, false},
}
for _, test := range testCases {
t.Run(fmt.Sprintf("args=%v", test.args), func(t *testing.T) {
apr, err := ap.Parse(test.args)
if test.expectError {
require.Error(t, err)
return
}
require.NoError(t, err)
count, ok := apr.GetFlagCount("verbose")
assert.True(t, ok)
assert.Equal(t, test.expectedCount, count)
})
}
}
func TestRepeatableFlagsWithOtherOptions(t *testing.T) {
ap := NewArgParserWithVariableArgs("test")
ap.SupportsRepeatableFlag("verbose", "v", "Verbose output")
ap.SupportsString("param", "p", "param", "")
ap.SupportsFlag("flag", "f", "flag")
testCases := []struct {
name string
args []string
expectedVerbose int
expectedParam string
expectedFlag bool
expectedArgs []string
}{
{"verbose with param", []string{"-v", "-p", "value"}, 1, "value", false, []string{}},
{"double verbose with param", []string{"-vv", "-p", "value"}, 2, "value", false, []string{}},
{"interleaved verbose and flag", []string{"-v", "-f", "-v"}, 2, "", true, []string{}},
{"verbose with flag and param", []string{"-vv", "-f", "-p", "test", "-v"}, 3, "test", true, []string{}},
{"combined flags", []string{"-vfp", "value"}, 1, "value", true, []string{}},
{"combined repeatable flags", []string{"-vvf", "-p", "data"}, 2, "data", true, []string{}},
{"verbose with positional args", []string{"-vv", "arg1", "arg2"}, 2, "", false, []string{"arg1", "arg2"}},
{"mixed order", []string{"-p", "value", "-vv", "-f", "-v", "arg1"}, 3, "value", true, []string{"arg1"}},
{"long form mixed", []string{"-v", "--param", "test", "--flag", "--verbose"}, 2, "test", true, []string{}},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
apr, err := ap.Parse(test.args)
require.NoError(t, err)
// Check verbose count
verboseCount, ok := apr.GetFlagCount("verbose")
if test.expectedVerbose > 0 {
assert.True(t, ok)
assert.Equal(t, test.expectedVerbose, verboseCount)
} else {
assert.False(t, ok)
assert.Equal(t, 0, verboseCount)
}
// Check param value
if test.expectedParam != "" {
paramValue, exists := apr.GetValue("param")
assert.True(t, exists)
assert.Equal(t, test.expectedParam, paramValue)
} else {
assert.False(t, apr.Contains("param"))
}
// Check flag
assert.Equal(t, test.expectedFlag, apr.Contains("flag"))
// Check positional arguments
assert.Equal(t, test.expectedArgs, apr.Args)
})
}
}
func TestGetFlagCountErrorHandling(t *testing.T) {
ap := NewArgParserWithVariableArgs("test")
ap.SupportsRepeatableFlag("verbose", "v", "Verbose output")
ap.SupportsFlag("flag", "f", "flag")
apr, err := ap.Parse([]string{"-vv", "-f"})
require.NoError(t, err)
// Test successful cases
count, ok := apr.GetFlagCount("verbose")
assert.True(t, ok)
assert.Equal(t, 2, count)
count, ok = apr.GetFlagCount("flag")
assert.True(t, ok)
assert.Equal(t, 1, count)
// Test non-existent flag
assert.Panics(t, func() {
_, _ = apr.GetFlagCount("nonexistent")
})
// Test flag that wasn't set
ap.SupportsRepeatableFlag("debug", "d", "Debug output")
count, ok = apr.GetFlagCount("debug")
assert.False(t, ok)
assert.Equal(t, 0, count)
}