- Compiler: PP → Lexer → Parser → Analyzer → Gengo pipeline - Parser: 232/236 (98%) Harbour compatibility, registry-based dispatch - RTL: 351 Harbour-compatible functions - RDD: DBF/NTX/CDX engines with Rushmore bitmap optimization - Go Interop: IMPORT + pkg.Func() + obj:Method() with FastPath (15M calls/sec) - HB_FUNC API: Full Harbour C API compatible Go bridge - Concurrency: SPAWN/LAUNCH/GOROUTINE, <-, WATCH, PARALLEL FOR, ASYNC/AWAIT - Extensions: Multi-return, DEFER, Slice, f-string, Nil-safe ?:, CONST - Macro Compiler: Runtime AST parsing and evaluation - Debugger: TUI debugger with source display, breakpoints, stepping - FRB: Native + Pcode dual mode runtime binary - Tests: 13 packages ALL PASS Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
171 lines
3.2 KiB
Go
171 lines
3.2 KiB
Go
package hbrtl
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestFCreateWriteReadClose(t *testing.T) {
|
|
_, th := setupVM()
|
|
dir := t.TempDir()
|
|
fpath := filepath.Join(dir, "test.bin")
|
|
|
|
// FCREATE
|
|
th.PushString(fpath)
|
|
th.PendingParams2(1)
|
|
FCreate(th)
|
|
h := th.GetRetValue().AsInt()
|
|
if h < 0 {
|
|
t.Fatalf("FCREATE failed: handle=%d", h)
|
|
}
|
|
|
|
// FWRITE
|
|
th.PushInt(h)
|
|
th.PushString("Hello Five!")
|
|
th.PendingParams2(2)
|
|
FWrite(th)
|
|
n := th.GetRetValue().AsInt()
|
|
if n != 11 {
|
|
t.Errorf("FWRITE wrote %d bytes, want 11", n)
|
|
}
|
|
|
|
// FCLOSE
|
|
th.PushInt(h)
|
|
th.PendingParams2(1)
|
|
FClose(th)
|
|
if !th.GetRetValue().AsBool() {
|
|
t.Error("FCLOSE returned false")
|
|
}
|
|
|
|
// FOPEN read
|
|
th.PushString(fpath)
|
|
th.PushInt(0) // read-only
|
|
th.PendingParams2(2)
|
|
FOpen(th)
|
|
h2 := th.GetRetValue().AsInt()
|
|
if h2 < 0 {
|
|
t.Fatalf("FOPEN failed: handle=%d", h2)
|
|
}
|
|
|
|
// FREAD
|
|
th.PushInt(h2)
|
|
th.PushNil() // buffer (not used in our impl)
|
|
th.PushInt(11)
|
|
th.PendingParams2(3)
|
|
FRead(th)
|
|
data := th.GetRetValue().AsString()
|
|
if data != "Hello Five!" {
|
|
t.Errorf("FREAD = %q, want %q", data, "Hello Five!")
|
|
}
|
|
|
|
// FCLOSE
|
|
th.PushInt(h2)
|
|
th.PendingParams2(1)
|
|
FClose(th)
|
|
}
|
|
|
|
func TestFSeek(t *testing.T) {
|
|
_, th := setupVM()
|
|
dir := t.TempDir()
|
|
fpath := filepath.Join(dir, "seek.bin")
|
|
|
|
// Create and write
|
|
os.WriteFile(fpath, []byte("0123456789"), 0644)
|
|
|
|
th.PushString(fpath)
|
|
th.PushInt(0)
|
|
th.PendingParams2(2)
|
|
FOpen(th)
|
|
h := th.GetRetValue().AsInt()
|
|
|
|
// Seek to offset 5 from start
|
|
th.PushInt(h)
|
|
th.PushLong(5)
|
|
th.PushInt(0) // from start
|
|
th.PendingParams2(3)
|
|
FSeek(th)
|
|
pos := th.GetRetValue().AsLong()
|
|
if pos != 5 {
|
|
t.Errorf("FSEEK pos = %d, want 5", pos)
|
|
}
|
|
|
|
// Read from offset 5
|
|
th.PushInt(h)
|
|
th.PushNil()
|
|
th.PushInt(5)
|
|
th.PendingParams2(3)
|
|
FRead(th)
|
|
if r := th.GetRetValue().AsString(); r != "56789" {
|
|
t.Errorf("FREAD after seek = %q, want %q", r, "56789")
|
|
}
|
|
|
|
th.PushInt(h)
|
|
th.PendingParams2(1)
|
|
FClose(th)
|
|
}
|
|
|
|
func TestFEraseRename(t *testing.T) {
|
|
_, th := setupVM()
|
|
dir := t.TempDir()
|
|
fpath := filepath.Join(dir, "todel.txt")
|
|
os.WriteFile(fpath, []byte("x"), 0644)
|
|
|
|
// FRENAME
|
|
newPath := filepath.Join(dir, "renamed.txt")
|
|
th.PushString(fpath)
|
|
th.PushString(newPath)
|
|
th.PendingParams2(2)
|
|
FRename(th)
|
|
if r := th.GetRetValue().AsInt(); r != 0 {
|
|
t.Errorf("FRENAME = %d, want 0", r)
|
|
}
|
|
if _, err := os.Stat(newPath); err != nil {
|
|
t.Error("Renamed file not found")
|
|
}
|
|
|
|
// FERASE
|
|
th.PushString(newPath)
|
|
th.PendingParams2(1)
|
|
FErase(th)
|
|
if r := th.GetRetValue().AsInt(); r != 0 {
|
|
t.Errorf("FERASE = %d, want 0", r)
|
|
}
|
|
if _, err := os.Stat(newPath); err == nil {
|
|
t.Error("File still exists after FERASE")
|
|
}
|
|
}
|
|
|
|
func TestFWritePartial(t *testing.T) {
|
|
_, th := setupVM()
|
|
dir := t.TempDir()
|
|
fpath := filepath.Join(dir, "partial.bin")
|
|
|
|
// Create
|
|
th.PushString(fpath)
|
|
th.PendingParams2(1)
|
|
FCreate(th)
|
|
h := th.GetRetValue().AsInt()
|
|
|
|
// Write only 3 bytes of "Hello"
|
|
th.PushInt(h)
|
|
th.PushString("Hello")
|
|
th.PushInt(3)
|
|
th.PendingParams2(3)
|
|
FWrite(th)
|
|
n := th.GetRetValue().AsInt()
|
|
if n != 3 {
|
|
t.Errorf("Partial FWRITE = %d, want 3", n)
|
|
}
|
|
|
|
th.PushInt(h)
|
|
th.PendingParams2(1)
|
|
FClose(th)
|
|
|
|
// Verify
|
|
data, _ := os.ReadFile(fpath)
|
|
if string(data) != "Hel" {
|
|
t.Errorf("File content = %q, want %q", string(data), "Hel")
|
|
}
|
|
}
|