diff --git a/devel/216_2.md b/devel/216_2.md index a0a7549c..ec43cdc8 100644 --- a/devel/216_2.md +++ b/devel/216_2.md @@ -166,6 +166,7 @@ tests/ ├── alist-cons-test.scm ├── any-test.scm ├── append-map-test.scm + ├── append-test.scm ├── circular-list-test.scm ├── cons-star-test.scm ├── count-test.scm @@ -221,6 +222,53 @@ tests/ └── zip-test.scm ``` +## 2026-04-01 复现 append 长列表 bug + +### What +在 `tests/liii/list/append-test.scm` 中添加了 bug 复现测试: + +1. **问题描述**:当使用 `append` 循环构建长列表(约 600+ 元素)时,列表结构会损坏变成 dotted pair + +2. **复现代码**: +```scheme +(let* ((entries (map (lambda (i) (cons (number->string i) (list "lib"))) (iota 600))) + (result + (let loop ((entries entries) + (visible '())) + (if (null? entries) + visible + (let* ((entry (car entries)) + (function-name (car entry))) + (loop (cdr entries) + (if (not (member function-name visible)) + (append visible (list function-name)) + visible))))))) + result) +``` + +3. **错误信息**: +``` +;append first argument, ("0" "1" "2" ...), is a pair but should be a proper list +``` + +### 说明 +- 错误发生在 `g_list_append` 函数中(src/s7.c) +- 示例代码逻辑正确,但触发了 Goldfish Scheme / S7 的 `append` 实现 bug +- 问题可能与 `member` 函数调用或垃圾回收有关 + +## 2026-03-31 新增 append-test.scm + +### What +新增 `append` 函数的测试文件 `tests/liii/list/append-test.scm`: +1. 包含 26 个测试用例,覆盖 `append` 函数的各种使用场景 +2. 测试覆盖基本功能、嵌套列表、空列表处理、不同类型元素、点对(dotted list)等情况 +3. 文件遵循测试文件格式规范,无协议头,使用 `;; ` 风格注释 + +### 测试结果 +``` +; *** checks *** : 26 correct, 0 failed. +``` + ## 2026-03-29 完成拆分 ### What diff --git a/tests/liii/list/append-test.scm b/tests/liii/list/append-test.scm new file mode 100644 index 00000000..82257cf1 --- /dev/null +++ b/tests/liii/list/append-test.scm @@ -0,0 +1,101 @@ +(import (liii list) + (liii check) +) ;import + +(check-set-mode! 'report-failed) + +;; append 函数测试 +;; +;; 连接多个列表并返回新列表。 +;; +;; 语法 +;; ---- +;; (append list ...) +;; +;; 参数 +;; ---- +;; list : list? +;; 零个或多个要连接的列表。 +;; +;; 返回值 +;; ---- +;; list +;; 一个新的列表,包含所有输入列表的元素。 +;; +;; 说明 +;; ---- +;; append函数接受多个列表作为参数,返回一个新列表,其中包含所有输入列表的元素。 +;; 最后一个参数可以是任意对象,此时返回的是一个点对(dotted list)。 + +; 基本功能测试 +(check (append) => '()) +(check (append '()) => '()) +(check (append '(1 2 3)) => '(1 2 3)) +(check (append '(1 2) '(3 4)) => '(1 2 3 4)) +(check (append '(a b) '(c d) '(e f)) => '(a b c d e f)) +(check (append '() '()) => '()) +(check (append '() '(1) '()) => '(1)) + +; 嵌套列表测试 +(check (append '((1 2)) '((3 4))) => '((1 2) (3 4))) +(check (append '(a b) '((c d) (e f))) => '(a b (c d) (e f))) + +; 空列表处理 +(check (append '() '(a b c)) => '(a b c)) +(check (append '(a b c) '()) => '(a b c)) +(check (append '() '() '(1 2) '()) => '(1 2)) + +; 不同类型元素测试 +(check (append '(1 2) '("hello" 'symbol)) => '(1 2 "hello" 'symbol)) +(check (append '(#t #f) '(42)) => '(#t #f 42)) +(check (append '(1 2.5) '(#\a #\b)) => '(1 2.5 #\a #\b)) + +; 最后一个参数为点对(dotted list) +(check (append '(a b) 'c) => '(a b . c)) +(check (append '(1 2) '(3 . 4)) => '(1 2 3 . 4)) +(check (append '() 'x) => 'x) + +; 单参数测试 +; 注意:单参数append可能返回原列表或副本,取决于实现 +(let ((original '(a b c))) + (let ((appended (append original))) + (check-true (list? appended)) + (check (length appended) => (length original)) + (check appended => '(a b c)) + ) ;let +) ;let + +; 不修改原始列表测试 +(let ((l1 '(1 2 3))) + (let ((l2 '(4 5 6))) + (let ((result (append l1 l2))) + (set-car! result 99) + (check l1 => '(1 2 3)) + (check l2 => '(4 5 6)) + (check result => '(99 2 3 4 5 6)) + ) ;let + ) ;let +) ;let + +; 复杂组合测试 +(check (append '(1) '(2) '(3) '(4) '(5)) => '(1 2 3 4 5)) +(check (append '(a b) '() '(c) '() '(d e)) => '(a b c d e)) + +; Bug 复现测试:使用 append 构建长列表时结构损坏问题 +; 测试:使用 map + member(原始场景) +(let* ((entries (map (lambda (i) (cons (number->string i) (list "lib"))) (iota 600))) + (result + (let loop ((entries entries) + (visible '())) + (if (null? entries) + visible + (let* ((entry (car entries)) + (function-name (car entry))) + (loop (cdr entries) + (if (not (member function-name visible)) + (append visible (list function-name)) + visible))))))) + (check-true (list? result)) + (check (length result) => 600)) + +(check-report)