Files
five/hbrdd/cdx/cdx_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

225 lines
4.5 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// CDX engine test — reads CDX files created by Harbour.
package cdx
import (
"os"
"testing"
)
const testCDX = "/mnt/d/charles/five/dbf/cdxtest.cdx"
func TestCDXOpen(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found — run Harbour to create it first")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
t.Logf("CDX opened: %d tags", idx.TagCount())
if idx.TagCount() < 1 {
t.Fatal("Expected at least 1 tag")
}
for i := 0; i < idx.TagCount(); i++ {
tag := idx.GetTag(i)
if tag != nil {
t.Logf(" Tag %d: name=%q", i, tag.Name)
}
}
}
func TestCDXFindTag(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
tag := idx.FindTag("NAME")
if tag == nil {
// Try without prefix
for i := 0; i < idx.TagCount(); i++ {
tg := idx.GetTag(i)
t.Logf("Available tag: %q", tg.Name)
}
t.Fatal("Tag BYNAME not found")
}
t.Logf("Found tag BYNAME")
}
func TestCDXGoTop(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
tag := idx.FindTag("NAME")
if tag == nil {
// Try first tag
if idx.TagCount() > 0 {
tag = idx.GetTag(0)
t.Logf("Using first tag: %q", tag.Name)
} else {
t.Skip("No tags found")
}
}
ok := tag.GoTop()
t.Logf("GoTop: ok=%v, recNo=%d, key=%q, eof=%v", ok, tag.CurRecNo(), string(tag.CurKey()), tag.IsEOF())
if tag.IsEOF() {
t.Error("GoTop resulted in EOF")
}
// First by name should be "Cho" (Harbour verified)
key := string(tag.CurKey())
t.Logf("First key: %q", key)
}
func TestCDXTraverse(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
tag := idx.FindTag("NAME")
if tag == nil && idx.TagCount() > 0 {
tag = idx.GetTag(0)
}
if tag == nil {
t.Skip("No tags")
}
tag.GoTop()
count := 0
prev := ""
for !tag.IsEOF() {
key := string(tag.CurKey())
if key < prev {
t.Errorf("Not sorted: %q < %q at %d", key, prev, count)
break
}
prev = key
count++
if count > 200 {
t.Error("Too many iterations, possible infinite loop")
break
}
tag.SkipNext()
}
t.Logf("Traversed %d keys", count)
if count != 100 {
t.Errorf("Expected 100 keys, got %d", count)
}
}
func TestCDXSeek(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
tag := idx.FindTag("NAME")
if tag == nil && idx.TagCount() > 0 {
tag = idx.GetTag(0)
}
if tag == nil {
t.Skip("No tags")
}
// Seek "Park" — should find it
searchKey := make([]byte, 20)
copy(searchKey, []byte("Park"))
for i := 4; i < 20; i++ {
searchKey[i] = ' '
}
recNo, found := tag.Seek(searchKey)
t.Logf("Seek 'Park': found=%v recNo=%d", found, recNo)
if !found {
t.Error("Expected to find 'Park'")
}
}
func TestCDXGoBottom(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
tag := idx.FindTag("NAME")
if tag == nil && idx.TagCount() > 0 {
tag = idx.GetTag(0)
}
if tag == nil {
t.Skip("No tags")
}
tag.GoBottom()
t.Logf("GoBottom: recNo=%d key=%q", tag.CurRecNo(), string(tag.CurKey()))
// Last by name should be "Yoon" (Harbour verified)
key := string(tag.CurKey())
if len(key) >= 4 && key[:4] != "Yoon" {
t.Errorf("Last key = %q, expected 'Yoon...'", key)
}
}
func TestCDXCityTag(t *testing.T) {
if _, err := os.Stat(testCDX); err != nil {
t.Skip("cdxtest.cdx not found")
}
idx, err := OpenIndex(testCDX)
if err != nil {
t.Fatalf("OpenIndex: %v", err)
}
defer idx.Close()
tag := idx.FindTag("CITY")
if tag == nil {
t.Skip("BYCITY tag not found")
}
tag.GoTop()
t.Logf("City GoTop: recNo=%d key=%q", tag.CurRecNo(), string(tag.CurKey()))
// First by city should be "London" (Harbour verified)
key := string(tag.CurKey())
if len(key) >= 6 && key[:6] != "London" {
t.Logf("First city key = %q (expected 'London...')", key)
}
}