@@ -5,41 +5,36 @@ import (
55 "testing"
66)
77
8- func TestUnmatchedClosingParen_NoPanic_ParseBacktickEnabled (t * testing.T ) {
8+ // ParseBacktick=true → an unmatched ‘)’ should be treated as an ERROR (not a literal)
9+ func TestUnmatchedClosingParen_ReturnsError_ParseBacktickEnabled (t * testing.T ) {
910 p := NewParser ()
1011 p .ParseBacktick = true
1112
12- defer func () {
13- if r := recover (); r != nil {
14- t .Fatalf ("unexpected panic: %v" , r )
15- }
16- }()
17-
18- out , err := p .Parse ("))" )
19- if err != nil {
20- t .Fatalf ("unexpected error: %v" , err )
21- }
22-
23- if len (out ) != 1 || out [0 ] != "))" {
24- t .Fatalf ("unexpected output: %#v" , out )
13+ _ , err := p .Parse ("))" )
14+ if err == nil {
15+ t .Fatal ("expected error for unmatched ')', got nil" )
2516 }
2617}
2718
28- func TestBareClosingParen_DoesNotTriggerCommandExecution (t * testing.T ) {
19+ // ParseBacktick=true → Do not execute; must fail
20+ func TestBareClosingParen_NoExecution_ReturnsError (t * testing.T ) {
2921 p := NewParser ()
3022 p .ParseBacktick = true
3123
32- out , err := p .Parse ("prefix)echo PWNED)" )
33- if err ! = nil {
34- t .Fatalf ( "unexpected error: %v" , err )
24+ _ , err := p .Parse ("prefix)echo PWNED)" )
25+ if err = = nil {
26+ t .Fatal ( "expected error for unmatched ')', got nil" )
3527 }
28+ }
3629
37- got := strings .Join (out , " " )
38- if strings .Contains (got , "PWNED" ) && got != "prefix)echo PWNED)" {
39- t .Fatalf ("unexpected command execution or substitution occurred: %q" , got )
30+ // Default behavior → ‘)’ is a literal; it does not break parsing
31+ func TestBareClosingParen_DefaultParsingLiteral (t * testing.T ) {
32+ out , err := Parse (")a b)c d" )
33+ if err != nil {
34+ t .Fatalf ("unexpected error: %v" , err )
4035 }
4136
42- want := []string {"prefix)echo " , "PWNED) " }
37+ want := []string {")a " , "b)c" , "d " }
4338 if len (out ) != len (want ) {
4439 t .Fatalf ("unexpected token count: got %d, want %d, out=%#v" , len (out ), len (want ), out )
4540 }
@@ -50,23 +45,26 @@ func TestBareClosingParen_DoesNotTriggerCommandExecution(t *testing.T) {
5045 }
5146}
5247
53- func TestBareClosingParen_DefaultParsingLiteral (t * testing.T ) {
54- out , err := Parse (")a b)c d" )
48+ // ParseBacktick=false → $(...) remains a FULL literal
49+ func TestDollarParenLiteralWhenParseBacktickDisabled (t * testing.T ) {
50+ p := NewParser ()
51+ p .ParseBacktick = false
52+
53+ out , err := p .Parse (`$(echo "foo")` )
5554 if err != nil {
5655 t .Fatalf ("unexpected error: %v" , err )
5756 }
5857
59- want := []string {")a" , "b)c" , "d" }
58+ want := []string {`$(echo "foo")` }
6059 if len (out ) != len (want ) {
6160 t .Fatalf ("unexpected token count: got %d, want %d, out=%#v" , len (out ), len (want ), out )
6261 }
63- for i := range want {
64- if out [i ] != want [i ] {
65- t .Fatalf ("unexpected token at %d: got %q, want %q, out=%#v" , i , out [i ], want [i ], out )
66- }
62+ if out [0 ] != want [0 ] {
63+ t .Fatalf ("unexpected output: got %q, want %q" , out [0 ], want [0 ])
6764 }
6865}
6966
67+ // If true → $(...) continues to work with ParseBacktick=true
7068func TestValidDollarCommandSubstitutionStillWorks (t * testing.T ) {
7169 p := NewParser ()
7270 p .ParseBacktick = true
@@ -82,6 +80,7 @@ func TestValidDollarCommandSubstitutionStillWorks(t *testing.T) {
8280 }
8381}
8482
83+ // Error → Unclosed $(
8584func TestUnclosedDollarCommandSubstitutionReturnsError (t * testing.T ) {
8685 p := NewParser ()
8786 p .ParseBacktick = true
@@ -90,4 +89,4 @@ func TestUnclosedDollarCommandSubstitutionReturnsError(t *testing.T) {
9089 if err == nil {
9190 t .Fatal ("expected error for unclosed command substitution, got nil" )
9291 }
93- }
92+ }
0 commit comments