package tools import ( "reflect" "testing" ) func TestShellSplitPatterns(t *testing.T) { tests := []struct { name string command string patterns []string always []string ok bool // false = ожидаем nil (непарсится -> безопасный отказ) }{ { name: "single command", command: "cat /etc/hosts", patterns: []string{"cat /etc/hosts"}, always: []string{"cat *"}, ok: true, }, { name: "chain with &&", command: "git status && git log", patterns: []string{"git status", "git log"}, always: []string{"git status *", "git log *"}, ok: true, }, { name: "chain with semicolon hides destructive", command: "cat /etc/hosts; rm -rf /", patterns: []string{"cat /etc/hosts", "rm -rf /"}, always: []string{"cat *", "rm *"}, ok: true, }, { name: "pipe", command: "ps aux | grep sshd", patterns: []string{"ps aux", "grep sshd"}, always: []string{"ps aux *", "grep sshd *"}, ok: true, }, { name: "command substitution", command: "echo $(rm -rf /tmp)", patterns: []string{"echo $(rm -rf /tmp)", "rm -rf /tmp"}, always: []string{"echo *", "rm *"}, ok: true, }, { name: "sh -c hides destructive", command: "sh -c 'rm -rf /'", patterns: []string{"sh -c 'rm -rf /'", "rm -rf /"}, always: []string{"sh *", "rm *"}, ok: true, }, { name: "quoted semicolon not split", command: "echo 'a;b'", patterns: []string{"echo 'a;b'"}, always: []string{"echo *"}, ok: true, }, { name: "redirection", command: "echo hi > /etc/foo", patterns: []string{"echo hi > /etc/foo"}, always: []string{"echo *"}, ok: true, }, { name: "unbalanced quote -> nil", command: "echo 'unterminated", patterns: nil, always: nil, ok: false, }, { name: "empty", command: "", patterns: nil, always: nil, ok: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { p, a := shellSplitPatterns(tt.command) if !tt.ok { if p != nil || a != nil { t.Fatalf("expected nil patterns/always, got %v / %v", p, a) } return } if !reflect.DeepEqual(p, tt.patterns) { t.Fatalf("patterns = %v, want %v", p, tt.patterns) } if !reflect.DeepEqual(a, tt.always) { t.Fatalf("always = %v, want %v", a, tt.always) } }) } }