define-namespace/examples/test-aatree.scm

189 lines
6.4 KiB
Scheme

;;;; Copyright (c) 2024, Peter McGoron
;;;;
;;;; Redistribution and use in source and binary forms, with or without
;;;; modification, are permitted provided that the following conditions
;;;; are met:
;;;;
;;;; 1) Redistributions of source code must retain the above copyright
;;;; notice, this list of conditions and the following disclaimer.
;;;; 2) Redistributions in binary form must reproduce the above copyright
;;;; notice, this list of conditions and the following disclaimer
;;;; in the documentation and/or other materials provided with the
;;;; distribution.
;;;;
;;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;;;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;;;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
;;;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
;;;; COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
;;;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
;;;; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;;;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;;;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
;;;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
;;;; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
;;;; POSSIBILITY OF SUCH DAMAGE.
(load "../srfi/srfi-64.scm")
(load "../define-namespace-5.scm")
(load "aatree.scm")
(define (string<=> x y)
(if (string<? x y)
'<
(if (string=? x y)
'=
'>)))
(import-from-namespace
(only aatree aatree? aatree->alist)
(rename aatree
(new aatree/new)
(search aatree/search)
(insert aatree/insert)
(delete aatree/delete)))
(test-begin "AATree")
(test-begin "insert one")
(define tree (aatree/new string<=>))
(let-values (((status key value)
(aatree/insert tree "a" 1)))
(test-equal "insert status" 'not-found status)
(let-values (((status key value)
(aatree/search tree "a")))
(test-equal "search status" 'found status)
(test-equal "search key" "a" key)
(test-equal "search value" 1 value)))
(test-end "insert one")
(test-begin "insert many in order")
(define inspairs
'(("a" . 1) ("b" . 2) ("c" . 3) ("d" . 4) ("e" . 5) ("f" . 6)
("g" . 7) ("h" . 8) ("i" . 9) ("j" . 10) ("k" . 11) ("l" . 12)
("m" . 13) ("n" . 14) ("o" . 15) ("p" . 16) ("q" . 17) ("r" . 18)
("s" . 19) ("t" . 20) ("u" . 21) ("v" . 22) ("w" . 23) ("x" . 24)
("y" . 25) ("z" . 26)))
(define (fold-collect f start processed to-process)
(if (null? to-process)
start
(let ((new-elem (car to-process)))
(fold-collect f (f start new-elem processed)
(cons new-elem processed)
(cdr to-process)))))
(define (iter f l)
(if (pair? l)
(begin
(f (car l))
(iter f (cdr l)))))
(define (test-insert node pair searchlist)
(let-values (((status key value)
(aatree/insert node (car pair) (cdr pair))))
(test-equal "insert" 'not-found status)
(iter (lambda (pair)
(let ((key (car pair))
(val (cdr pair)))
(let-values (((status retkey retval)
(aatree/search node key)))
(test-equal "search status" 'found status)
(test-equal "search key" key retkey)
(test-equal "search value" val retval))))
searchlist)
node))
(define inserted-in-order
(fold-collect test-insert (aatree/new string<=>) '() inspairs))
(test-end "insert many in order")
(display "a\n")
;; Not possible to implement good randomin strictly portable R5RS scheme,
;; Shuffled using "shuf"
(test-begin "insert shuffled")
(define shuffled-list
'(("k" . 11)
("p" . 16)
("r" . 18)
("w" . 23)
("x" . 24)
("t" . 20)
("f" . 6)
("z" . 26)
("h" . 8)
("a" . 1)
("s" . 19)
("e" . 5)
("d" . 4)
("y" . 25)
("c" . 3)
("j" . 10)
("v" . 22)
("g" . 7)
("o" . 15)
("q" . 17)
("m" . 13)
("u" . 21)
("l" . 12)
("b" . 2)
("n" . 14)
("i" . 9)))
(fold-collect test-insert (aatree/new string<=>) '() shuffled-list)
(test-end "insert shuffled")
(test-begin "delete one")
(define tree (aatree/new string<=>))
(let-values (((status key value)
(aatree/insert tree "a" 1)))
(test-equal "insert status" 'not-found status)
(let-values (((status retkey retval)
(aatree/search tree "a")))
(test-equal "search 1 status" 'found status)
(test-equal "search 1 key" "a" retkey)
(test-equal "search 1 value" 1 retval)
(let-values (((status retkey retval)
(aatree/delete tree "a")))
(test-equal "delete status" 'found status)
(test-equal "delete key" "a" retkey)
(test-equal "delete value" 1 retval)
(let-values (((status . _)
(aatree/search tree "a")))
(test-equal "search 2 status" status 'not-found)))))
(test-end "delete one")
(define (test-delete tree deleted to-delete)
(if (pair? to-delete)
(let ((pair (car to-delete)))
(let-values (((status retkey retval)
(aatree/delete tree (car pair))))
(test-equal "delete status" 'found status)
(test-equal "delete key" (car pair) retkey)
(test-equal "delete value" (cdr pair) retval)
(iter (lambda (pair)
(let ((key (car pair)))
(let-values (((status . _)
(aatree/search tree key)))
(test-equal "deleted search" 'not-found status))))
(cons pair deleted))
(iter (lambda (pair)
(let ((key (car pair))
(val (cdr pair)))
(let-values (((status retkey retval)
(aatree/search tree key)))
(test-equal "to-delete search" 'found status)
(test-equal "to-delete search value" val retval)
(test-equal "to-delete search key" key retkey))))
(cdr to-delete))
(test-delete tree (cons pair deleted) (cdr to-delete))))))
(test-begin "insert and shuffled delete")
(test-delete inserted-in-order '() shuffled-list)
(test-end "insert and shuffled delete")
(test-end "AATree")