test: Harbour vs Five RDD compatibility test (91% match)

47 test items comparing Harbour and Five output:
- T01-T28: 100% match (CRUD, navigation, SET DELETED)
- T29-T39: 100% match (SEEK exact/partial/softseek)
- T40-T41: Found matches, RecNo differs (duplicate key sort stability)
- T42-T43: 100% match
- T44-T47: Five crashes (PACK with open index)

Known issues found:
- FIELD->NAME syntax not supported in INDEX ON expression
- Modulo % returns Double causing array index hang (Int() workaround)
- PACK crashes when NTX index is open

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 19:42:50 +09:00
parent 21fd9dc65c
commit 53370e7cbc

212
examples/rdd_compat.prg Normal file
View File

@@ -0,0 +1,212 @@
// RDD Compatibility Test — Harbour vs Five
PROCEDURE Main()
LOCAL i, aStruct, nCount, aCities, nIdx
aStruct := { ;
{"ID", "N", 6, 0}, ;
{"NAME", "C", 20, 0}, ;
{"CITY", "C", 15, 0}, ;
{"SALARY", "N", 10, 2}, ;
{"ACTIVE", "L", 1, 0} ;
}
dbCreate("compat_test", aStruct)
USE "compat_test" NEW
aCities := {"Seoul","Tokyo","Beijing","London","NYC"}
FOR i := 1 TO 20
APPEND BLANK
REPLACE ID WITH i
REPLACE NAME WITH PadR("Name_" + LTrim(Str(i)), 20)
nIdx := Int(((i-1) % 5)) + 1
REPLACE CITY WITH PadR(aCities[nIdx], 15)
REPLACE SALARY WITH 30000 + i * 1000.50
REPLACE ACTIVE WITH (i % 3 != 0)
NEXT
Out("T01", LTrim(Str(RecCount())))
GO TOP
Out("T02", LTrim(Str(FieldGet(1))))
Out("T03", RTrim(FieldGet(2)))
Out("T04", RTrim(FieldGet(3)))
Out("T05", LTrim(Str(FieldGet(4))))
Out("T06", IIF(FieldGet(5), ".T.", ".F."))
GO 10
Out("T07", LTrim(Str(FieldGet(1))))
Out("T08", RTrim(FieldGet(2)))
GO 20
Out("T09", LTrim(Str(FieldGet(1))))
Out("T10", LTrim(Str(FieldGet(4))))
GO TOP
Out("T11", LTrim(Str(RecNo())))
Out("T12", IIF(BOF(), ".T.", ".F."))
Out("T13", IIF(EOF(), ".T.", ".F."))
GO BOTTOM
Out("T14", LTrim(Str(RecNo())))
SKIP -1
Out("T15", LTrim(Str(RecNo())))
GO TOP
SKIP 5
Out("T16", LTrim(Str(RecNo())))
GO TOP
nCount := 0
DO WHILE !EOF()
nCount++
SKIP
ENDDO
Out("T17", LTrim(Str(nCount)))
Out("T18", IIF(EOF(), ".T.", ".F."))
GO 5
DELETE
Out("T19", IIF(Deleted(), ".T.", ".F."))
RECALL
Out("T20", IIF(Deleted(), ".T.", ".F."))
FOR i := 1 TO 20
GO i
IF i % 3 == 0
DELETE
ENDIF
NEXT
nCount := 0
GO TOP
DO WHILE !EOF()
IF Deleted()
nCount++
ENDIF
SKIP
ENDDO
Out("T21", LTrim(Str(nCount)))
SET DELETED OFF
GO TOP
nCount := 0
DO WHILE !EOF()
nCount++
SKIP
ENDDO
Out("T22", LTrim(Str(nCount)))
SET DELETED ON
GO TOP
nCount := 0
DO WHILE !EOF()
nCount++
SKIP
ENDDO
Out("T23", LTrim(Str(nCount)))
GO 1
DELETE
SET DELETED ON
GO TOP
Out("T24", LTrim(Str(RecNo())))
GO 20
DELETE
GO BOTTOM
Out("T25", LTrim(Str(RecNo())))
GO 1
RECALL
GO 20
RECALL
SET DELETED OFF
INDEX ON NAME TO compat_idx1
Out("T26", "OK")
GO TOP
Out("T27", RTrim(FieldGet(2)))
Out("T28", LTrim(Str(FieldGet(1))))
SEEK PadR("Name_1", 20)
Out("T29", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
SEEK PadR("Name_10", 20)
Out("T30", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
SEEK PadR("Name_20", 20)
Out("T31", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
SEEK PadR("Name_99", 20)
Out("T32", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
Out("T33", IIF(EOF(), ".T.", ".F."))
SEEK "Name_1"
Out("T34", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
SEEK "Name_2"
Out("T35", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
SET SOFTSEEK ON
SEEK PadR("Name_15", 20)
Out("T36", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(RecNo())))
SEEK PadR("Name_99", 20)
Out("T37", IIF(Found(), ".T.", ".F.") + " " + IIF(EOF(), ".T.", ".F."))
SET SOFTSEEK OFF
SET ORDER TO 0
GO TOP
Out("T38", LTrim(Str(FieldGet(1))))
SET ORDER TO 1
GO TOP
Out("T39", RTrim(FieldGet(2)))
INDEX ON CITY TO compat_idx2
SEEK PadR("Seoul", 15)
Out("T40", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(FieldGet(1))))
SEEK PadR("Tokyo", 15)
Out("T41", IIF(Found(), ".T.", ".F.") + " " + LTrim(Str(FieldGet(1))))
SEEK PadR("Paris", 15)
Out("T42", IIF(Found(), ".T.", ".F."))
SET ORDER TO 0
SET DELETED OFF
nCount := 0
GO TOP
DO WHILE !EOF()
IF Deleted()
nCount++
ENDIF
SKIP
ENDDO
Out("T43", LTrim(Str(nCount)))
PACK
Out("T44", LTrim(Str(RecCount())))
nCount := 0
GO TOP
DO WHILE !EOF()
IF Deleted()
nCount++
ENDIF
SKIP
ENDDO
Out("T45", LTrim(Str(nCount)))
ZAP
Out("T46", LTrim(Str(RecCount())))
Out("T47", IIF(EOF(), ".T.", ".F."))
CLOSE ALL
RETURN
PROCEDURE Out(cID, cVal)
? cID + "=" + cVal
RETURN