项目文件夹

文件
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

198 行
5.8 KiB
Go

package app
import (
"reflect"
"strings"
"testing"
"github.com/pranshuparmar/witr/pkg/model"
)
func tgt(tp model.TargetType, v string) model.Target { return model.Target{Type: tp, Value: v} }
// collectTargetsInOrder is the order-preserving CLI target parser. It duplicates
// some of cobra's flag semantics (it reads raw argv to keep the user's typed
// order), so these cases pin that behavior down before any future refactor.
func TestCollectTargetsInOrder(t *testing.T) {
t.Parallel()
tests := []struct {
name string
rawArgs []string
positional []string
valueFlags []string // non-target flags that consume the next token
want []model.Target
}{
{
name: "single name",
rawArgs: []string{"nginx"},
positional: []string{"nginx"},
want: []model.Target{tgt(model.TargetName, "nginx")},
},
{
name: "pid long flag, space form",
rawArgs: []string{"--pid", "1234"},
want: []model.Target{tgt(model.TargetPID, "1234")},
},
{
name: "pid short flag",
rawArgs: []string{"-p", "1234"},
want: []model.Target{tgt(model.TargetPID, "1234")},
},
{
name: "equals form",
rawArgs: []string{"--port=8080"},
want: []model.Target{tgt(model.TargetPort, "8080")},
},
{
name: "comma split, space form",
rawArgs: []string{"--port", "80,443"},
want: []model.Target{tgt(model.TargetPort, "80"), tgt(model.TargetPort, "443")},
},
{
name: "comma split, equals form, blanks trimmed",
rawArgs: []string{"--pid=1, ,2"},
want: []model.Target{tgt(model.TargetPID, "1"), tgt(model.TargetPID, "2")},
},
{
name: "interleaved order preserved",
rawArgs: []string{"nginx", "--pid", "1234", "node"},
positional: []string{"nginx", "node"},
want: []model.Target{
tgt(model.TargetName, "nginx"),
tgt(model.TargetPID, "1234"),
tgt(model.TargetName, "node"),
},
},
{
name: "boolean flags skipped",
rawArgs: []string{"--json", "nginx", "--verbose", "-x"},
positional: []string{"nginx"},
want: []model.Target{tgt(model.TargetName, "nginx")},
},
{
name: "mixed flag types",
rawArgs: []string{"--port", "8080", "redis", "-f", "/tmp/x", "-c", "web"},
positional: []string{"redis"},
want: []model.Target{
tgt(model.TargetPort, "8080"),
tgt(model.TargetName, "redis"),
tgt(model.TargetFile, "/tmp/x"),
tgt(model.TargetContainer, "web"),
},
},
{
name: "remaining positionals appended",
rawArgs: []string{},
positional: []string{"a", "b"},
want: []model.Target{tgt(model.TargetName, "a"), tgt(model.TargetName, "b")},
},
{
// Regression for the latent argv bug: a space-form string-valued
// flag must consume its value, or that value steals a positional
// slot and corrupts the interleaved target order. Fails without the
// flag-arity fix (would yield alpha, beta, pid:5).
name: "value-flag value not mistaken for a target",
rawArgs: []string{"alpha", "--config", "nginx", "--pid", "5", "beta"},
positional: []string{"alpha", "beta"},
valueFlags: []string{"--config"},
want: []model.Target{
tgt(model.TargetName, "alpha"),
tgt(model.TargetPID, "5"),
tgt(model.TargetName, "beta"),
},
},
{
name: "value-flag in equals form needs no lookahead",
rawArgs: []string{"--config=app.yml", "nginx"},
positional: []string{"nginx"},
valueFlags: []string{"--config"},
want: []model.Target{tgt(model.TargetName, "nginx")},
},
{
name: "short value-flag, space form",
rawArgs: []string{"-C", "app.yml", "redis"},
positional: []string{"redis"},
valueFlags: []string{"-C"},
want: []model.Target{tgt(model.TargetName, "redis")},
},
{
name: "target flag without a value yields no target",
rawArgs: []string{"--pid"},
want: nil,
},
{
name: "empty value via equals yields no target",
rawArgs: []string{"--port="},
want: nil,
},
{
// "--" ends option parsing: following tokens are positional names even
// when they look like flags.
name: "double dash ends option parsing",
rawArgs: []string{"--", "nginx"},
positional: []string{"nginx"},
want: []model.Target{tgt(model.TargetName, "nginx")},
},
{
name: "double dash forces flaglike tokens to names",
rawArgs: []string{"--", "--pid", "5"},
positional: []string{"--pid", "5"},
want: []model.Target{tgt(model.TargetName, "--pid"), tgt(model.TargetName, "5")},
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
takesValue := func(a string) bool {
for _, f := range tc.valueFlags {
if a == f {
return true
}
}
return false
}
got := collectTargetsInOrder(tc.rawArgs, tc.positional, takesValue)
if len(got) == 0 && len(tc.want) == 0 {
return
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("collectTargetsInOrder(%v, %v)\n got: %v\nwant: %v", tc.rawArgs, tc.positional, got, tc.want)
}
})
}
}
func TestTargetLabel(t *testing.T) {
t.Parallel()
cases := []struct {
in model.Target
want string
}{
{tgt(model.TargetPID, "1234"), "pid: 1234"},
{tgt(model.TargetPort, "80"), "port: 80"},
{tgt(model.TargetFile, "/x"), "file: /x"},
{tgt(model.TargetContainer, "c"), "container: c"},
{tgt(model.TargetName, "n"), "name: n"},
}
for _, c := range cases {
if got := targetLabel(c.in); got != c.want {
t.Errorf("targetLabel(%+v) = %q, want %q", c.in, got, c.want)
}
}
}
func TestJSONErrorEntry(t *testing.T) {
t.Parallel()
s := jsonErrorEntry(tgt(model.TargetPort, "8080"), "boom")
for _, want := range []string{`"Error"`, "boom", "8080", "port"} {
if !strings.Contains(s, want) {
t.Errorf("jsonErrorEntry missing %q in:\n%s", want, s)
}
}
}