Files
five/hbrtl/fileio_test.go
Charles KWON OhJun 59568f3301 Five v0.9 — Harbour + Go fusion language
- 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>
2026-03-31 09:41:50 +09:00

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")
}
}