// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com) // All rights reserved. package pp import ( "strings" "testing" ) func TestCommandSimple(t *testing.T) { p := New() src := `#command CLS => @ 0,0 CLEAR CLS` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "@ 0,0 CLEAR") { t.Errorf("CLS should expand to '@ 0,0 CLEAR', got: %q", result) } } func TestCommandWithMarker(t *testing.T) { p := New() src := `#command SAY => QOut( ) SAY "Hello"` result, _ := p.Process("test.prg", src) if !strings.Contains(result, `QOut( "Hello" )`) { t.Errorf("SAY should expand, got: %q", result) } } func TestCommandWithMultipleMarkers(t *testing.T) { p := New() src := `#command STORE TO => := STORE 42 TO myVar` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "myVar := 42") { t.Errorf("STORE should expand, got: %q", result) } } func TestTranslateStringify(t *testing.T) { p := New() // Simple stringify without parentheses in pattern src := `#translate ASSERT => __Assert( <(expr)>, ) ASSERT x > 10` result, _ := p.Process("test.prg", src) if !strings.Contains(result, `"x > 10"`) { t.Errorf("stringify should produce quoted text, got: %q", result) } } func TestCommandCaseInsensitive(t *testing.T) { p := New() src := `#command CLEAR SCREEN => @ 0,0 CLEAR clear screen` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "@ 0,0 CLEAR") { t.Errorf("case insensitive match failed, got: %q", result) } } func TestXtranslateCaseSensitive(t *testing.T) { p := New() // Without parentheses in pattern for simpler matching src := `#xtranslate MYFUNC => myFuncImpl( ) MYFUNC 42 myfunc 99` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "myFuncImpl( 42 )") { t.Errorf("case-sensitive match should work, got: %q", result) } if strings.Contains(result, "myFuncImpl( 99 )") { t.Error("case-sensitive should NOT match lowercase") } } func TestCommandWordList(t *testing.T) { p := New() src := `#command SET DELETED => Set( _SET_DELETED, <(x)> ) SET DELETED ON` result, _ := p.Process("test.prg", src) if !strings.Contains(result, `Set( _SET_DELETED, "ON" )`) { t.Errorf("word list match failed, got: %q", result) } } func TestCommandWildcard(t *testing.T) { p := New() src := `#command NOTE <*x*> => NOTE This is a comment that should disappear` result, _ := p.Process("test.prg", src) trimmed := strings.TrimSpace(result) if trimmed != "" { t.Errorf("NOTE with wildcard should produce empty, got: %q", trimmed) } } func TestCommandOptional(t *testing.T) { p := New() // Simpler optional test without comma-list src := `#command DO => () DO MyFunc` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "MyFunc()") { t.Errorf("DO MyFunc should expand to MyFunc(), got: %q", result) } } func TestCommandWithArgs(t *testing.T) { p := New() src := `#command DO WITH => ( ) DO MyFunc WITH 42` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "MyFunc( 42 )") { t.Errorf("DO WITH should expand, got: %q", result) } } func TestStdChPatterns(t *testing.T) { // Test patterns from Harbour's std.ch p := New() src := `#command END => end #command ENDDO <*x*> => enddo #command ENDIF <*x*> => endif END SEQUENCE ENDDO something ENDIF // test` result, _ := p.Process("test.prg", src) lines := strings.Split(strings.TrimSpace(result), "\n") expects := []string{"end", "enddo", "endif"} idx := 0 for _, l := range lines { l = strings.TrimSpace(l) if l == "" { continue } if idx < len(expects) && l == expects[idx] { idx++ } } if idx != len(expects) { t.Errorf("std.ch patterns: matched %d/%d, result:\n%s", idx, len(expects), result) } } func TestHBTEST_Pattern(t *testing.T) { // The key pattern from hbtest.ch p := New() src := `#xtranslate HBTEST IS => TEST_CALL( #, {|| }, ) HBTEST Len("abc") IS 3` result, _ := p.Process("test.prg", src) if !strings.Contains(result, "TEST_CALL") { t.Errorf("HBTEST macro should expand, got: %q", result) } if !strings.Contains(result, `"Len("abc")"`) || !strings.Contains(result, "3") { // At minimum, the result marker should be present if !strings.Contains(result, "3") { t.Errorf("expected result value 3 in expansion, got: %q", result) } } } func TestMultipleRules(t *testing.T) { p := New() src := `#command PRINT => QOut( ) #command PRINTLN => QOut( ) ; QOut() PRINT "Hello" PRINTLN "World"` result, _ := p.Process("test.prg", src) if !strings.Contains(result, `QOut( "Hello" )`) { t.Error("PRINT should expand") } if !strings.Contains(result, `QOut( "World" )`) { t.Error("PRINTLN should expand") } }