Files
five/tests/std_ch/test_sort.prg
CharlesKWON 3a7f1dea72 feat(rtl,tests): pre-release UX round (Wave 5)
Three audit findings around polish + a release-readiness commit:

  * #UX1 LIST/DISPLAY output: dropped \r\n (unix terminals showed a
    stray ^M), moved the newline to AFTER each row (no more leading
    blank line), and added the `*` deleted-record marker after the
    record number — matches xBase LIST/DISPLAY convention. With
    SET DELETED ON the marker is unreachable since the row would
    have been skipped at Area.Skip level; with SET DELETED OFF the
    user now sees which rows are tombstoned.

  * #26 temp aliases: `__copytmp` / `__sorttmp` / `__totaltmp` /
    `__jointmp` were process-global string constants. A nested
    invocation (e.g., COPY inside a FOR clause whose expression
    runs another COPY) collided on the alias and the inner Open
    failed with "alias already in use" — surfacing as `.F.` with
    no clear cause. Each Open now goes through a new helper
    `nextTmpAlias(prefix)` backed by an atomic counter, so every
    call gets `__copytmp_1`, `__copytmp_2`, etc. — no collisions.

  * #J test coverage gap: the 13 std.ch regression tests were all
    sitting in `/tmp` — lost on tmpfs reboot, never in git, never
    in CI. Move them into `tests/std_ch/` and add a simple
    `run.sh` runner that builds + executes each one in a temp
    scratch directory and grep-asserts on FAIL / NOT REJECTED /
    expectation-mismatch markers. 13/13 pass against the current
    head:

       PASS  test_pp_stdch       PASS  test_count
       PASS  test_sum_avg        PASS  test_sum_multi
       PASS  test_copy           PASS  test_sort
       PASS  test_list           PASS  test_total
       PASS  test_join           PASS  test_update
       PASS  test_set_deleted    PASS  test_unsupported
       PASS  test_block_comma

    test_block_comma in particular guards the gengo SeqExpr fix
    from Wave 1 — without it the comma-in-block miscompile would
    silently come back.

Gates green:
  go test ./...      : PASS
  FiveSql2 SQL:1999  : 43/43
  Harbour compat     : 56/56
  std.ch suite       : 13/13

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 08:07:50 +09:00

75 lines
1.8 KiB
Plaintext

/* SORT TO via PP rule. */
PROCEDURE Main()
LOCAL aStruct
FErase( "src.dbf" )
FErase( "dst1.dbf" )
FErase( "dst2.dbf" )
FErase( "dst3.dbf" )
aStruct := { ;
{ "ID", "N", 4, 0 }, ;
{ "NAME", "C", 20, 0 }, ;
{ "AGE", "N", 3, 0 } }
dbCreate( "src.dbf", aStruct )
USE src.dbf NEW EXCLUSIVE ALIAS s
dbAppend() ; FieldPut(1,1) ; FieldPut(2,"Carol") ; FieldPut(3,30)
dbAppend() ; FieldPut(1,2) ; FieldPut(2,"Alice") ; FieldPut(3,18)
dbAppend() ; FieldPut(1,3) ; FieldPut(2,"Eve") ; FieldPut(3,60)
dbAppend() ; FieldPut(1,4) ; FieldPut(2,"Bob") ; FieldPut(3,25)
dbAppend() ; FieldPut(1,5) ; FieldPut(2,"Dan") ; FieldPut(3,45)
dbCommit()
/* 1. SORT ON name asc */
dbGoTop()
SORT TO dst1.dbf ON name
dbCloseArea()
USE dst1.dbf NEW EXCLUSIVE
dbGoTop()
? "1. name asc:"
DO WHILE !Eof()
? " ", FieldGet(1), AllTrim(FieldGet(2)), FieldGet(3)
dbSkip()
ENDDO
? " (expect: Alice, Bob, Carol, Dan, Eve)"
dbCloseArea()
/* 2. SORT ON age/D */
USE src.dbf NEW EXCLUSIVE ALIAS s
dbGoTop()
SORT TO dst2.dbf ON age/D
dbCloseArea()
USE dst2.dbf NEW EXCLUSIVE
dbGoTop()
? "2. age desc:"
DO WHILE !Eof()
? " ", FieldGet(1), AllTrim(FieldGet(2)), FieldGet(3)
dbSkip()
ENDDO
? " (expect: 60, 45, 30, 25, 18)"
dbCloseArea()
/* 3. SORT ON age FOR age >= 30 */
USE src.dbf NEW EXCLUSIVE ALIAS s
dbGoTop()
SORT TO dst3.dbf ON age FOR s->age >= 30
dbCloseArea()
USE dst3.dbf NEW EXCLUSIVE
dbGoTop()
? "3. age asc, FOR age>=30:"
DO WHILE !Eof()
? " ", FieldGet(1), AllTrim(FieldGet(2)), FieldGet(3)
dbSkip()
ENDDO
? " (expect: Carol/30, Dan/45, Eve/60)"
dbCloseArea()
FErase( "src.dbf" )
FErase( "dst1.dbf" )
FErase( "dst2.dbf" )
FErase( "dst3.dbf" )
? "DONE"
RETURN