diff options
author | Andy Wingo <wingo@pobox.com> | 2009-12-20 23:11:34 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2009-12-21 00:01:50 +0100 |
commit | 500f6a47e2609f936d43f47bcce4e429eb57997d (patch) | |
tree | 37825b5a3f67b788fb101da3f66e5ed4f3412123 | |
parent | c55cb58ac15b61eac574d8adafb08bc32f2bc8c1 (diff) | |
download | guile-500f6a47e2609f936d43f47bcce4e429eb57997d.tar.gz |
add test suites
-rw-r--r-- | test-suite/Makefile.am | 9 | ||||
-rw-r--r-- | test-suite/tests/statprof.test | 111 | ||||
-rw-r--r-- | test-suite/tests/sxml.fold.test | 212 | ||||
-rw-r--r-- | test-suite/tests/sxml.ssax.test | 143 | ||||
-rw-r--r-- | test-suite/tests/sxml.transform.test | 101 | ||||
-rw-r--r-- | test-suite/tests/sxml.xpath.test | 700 | ||||
-rw-r--r-- | test-suite/tests/texinfo.docbook.test | 35 | ||||
-rw-r--r-- | test-suite/tests/texinfo.serialize.test | 188 | ||||
-rw-r--r-- | test-suite/tests/texinfo.string-utils.test | 118 | ||||
-rw-r--r-- | test-suite/tests/texinfo.test | 407 |
10 files changed, 2024 insertions, 0 deletions
diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am index 94bc2e953..ddbfc6962 100644 --- a/test-suite/Makefile.am +++ b/test-suite/Makefile.am @@ -92,11 +92,20 @@ SCM_TESTS = tests/alist.test \ tests/srfi-88.test \ tests/srfi-4.test \ tests/srfi-9.test \ + tests/statprof.test \ tests/strings.test \ tests/structs.test \ + tests/sxml.fold.test \ + tests/sxml.ssax.test \ + tests/sxml.transform.test \ + tests/sxml.xpath.test \ tests/symbols.test \ tests/syncase.test \ tests/syntax.test \ + tests/texinfo.test \ + tests/texinfo.docbook.test \ + tests/texinfo.serialize.test \ + tests/texinfo.string-utils.test \ tests/threads.test \ tests/time.test \ tests/tree-il.test \ diff --git a/test-suite/tests/statprof.test b/test-suite/tests/statprof.test new file mode 100644 index 000000000..22fce3298 --- /dev/null +++ b/test-suite/tests/statprof.test @@ -0,0 +1,111 @@ +;; guile-lib -*- scheme -*- +;; Copyright (C) 2004, 2009 Andy Wingo <wingo at pobox dot com> +;; Copyright (C) 2001 Rob Browning <rlb at defaultvalue dot org> + +;; This library is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public +;; License as published by the Free Software Foundation; either +;; version 2.1 of the License, or (at your option) any later version. +;; +;; This library is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (debugging statprof). +;; +;;; Code: + +(define-module (test-suite test-statprof) + #:use-module (test-suite lib) + #:use-module (system base compile) + #:use-module (srfi srfi-1) + #:use-module (statprof)) + +;; FIXME +(debug-enable 'debug) +(trap-enable 'traps) + +(pass-if "statistical sample counts within expected range" + (let () + ;; test to see that if we call 3 identical functions equally, they + ;; show up equally in the call count, +/- 30%. it's a big range, and + ;; I tried to do something more statistically valid, but failed (for + ;; the moment). + + ;; make sure these are compiled so we're not swamped in `eval' + (define (make-func) + (compile '(lambda (n) + (do ((i 0 (+ i 1))) ((= 200 i)) (+ i i))))) + (define run-test + (compile '(lambda (num-calls funcs) + (let loop ((x num-calls) (funcs funcs)) + (cond + ((positive? x) + ((car funcs) x) + (loop (- x 1) (cdr funcs)))))))) + + (let ((num-calls 40000) + (funcs (circular-list (make-func) (make-func) (make-func)))) + + ;; Run test. 10000 us == 100 Hz. + (statprof-reset 0 10000 #f #f) + (statprof-start) + (run-test num-calls funcs) + (statprof-stop) + + (let* ((a-data (statprof-proc-call-data (car funcs))) + (b-data (statprof-proc-call-data (cadr funcs))) + (c-data (statprof-proc-call-data (caddr funcs))) + (samples (map statprof-call-data-cum-samples + (list a-data b-data c-data))) + (average (/ (apply + samples) 3)) + (max-allowed-drift 0.30) ; 30% + (diffs (map (lambda (x) (abs (- x average))) + samples)) + (max-diff (apply max diffs))) + + (let ((drift-fraction (/ max-diff average))) + (or (< drift-fraction max-allowed-drift) + ;; don't stop the the test suite for what statistically is + ;; bound to happen. + (throw 'unresolved (pk average drift-fraction)))))))) + +(pass-if "accurate call counting" + (let () + ;; Test to see that if we call a function N times while the profiler + ;; is active, it shows up N times. + (let ((num-calls 200)) + + (define (do-nothing n) + (simple-format #f "FOO ~A\n" (+ n n))) + + (throw 'unresolved) ;; need to fix VM tracing. + + ;; Run test. + (statprof-reset 0 50000 #t #f) + (statprof-start) + (let loop ((x num-calls)) + (cond + ((positive? x) + (do-nothing x) + (loop (- x 1)) + #t))) + (statprof-stop) + + ;;(statprof-display) + + ;; Check result. + (let ((proc-data (statprof-proc-call-data do-nothing))) + (and proc-data + (= (statprof-call-data-calls proc-data) + num-calls)))))) diff --git a/test-suite/tests/sxml.fold.test b/test-suite/tests/sxml.fold.test new file mode 100644 index 000000000..7374e5262 --- /dev/null +++ b/test-suite/tests/sxml.fold.test @@ -0,0 +1,212 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2007, 2009 Andy Wingo <wingo at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (sxml fold). +;; +;;; Code: + +(define-module (test-suite sxml-fold) + #:use-module (test-suite lib) + #:use-module (sxml fold)) + +(define atom? (@@ (sxml fold) atom?)) +(define (id x) x) +(define-syntax accept + (syntax-rules () + ((_ expr) + (call-with-values (lambda () expr) list)))) + +(with-test-prefix "test-fold" + (define test-doc + '(presentation + (@ (width 1024) + (height 768) + (title-style "font-family:Georgia") + (title-height 72) + (title-baseline-y 96) + (title-x 48) + (text-height 64) + (text-style "font-family:Georgia") + (text-upper-left-x 96) + (text-upper-left-y 216)) + (slide + (@ (title "Declarative interface")) + (p "The declarative interface" + "lets you be more concise" + "when making the slides.")) + (slide + (@ (title "Still cumbersome")) + (p "Parentheses are still" + "cumbersome.")))) + + (pass-if (atom? 'foo)) + (pass-if (atom? '())) + (pass-if (not (atom? '(1 2 3)))) + + (pass-if "foldt identity" + (equal? (foldt id id test-doc) test-doc)) + + (pass-if "fold cons == reverse" + (equal? (fold cons '() test-doc) + (reverse test-doc))) + + (pass-if "foldts identity" + (equal? (foldts (lambda (seed tree) '()) + (lambda (seed kid-seed tree) + (cons (reverse kid-seed) seed)) + (lambda (seed tree) + (cons tree seed)) + '() + test-doc) + (cons test-doc '()))) + + (pass-if "foldts* identity" + (equal? (foldts* (lambda (seed tree) (values '() tree)) + (lambda (seed kid-seed tree) + (cons (reverse kid-seed) seed)) + (lambda (seed tree) + (cons tree seed)) + '() + test-doc) + (cons test-doc '()))) + + (pass-if "fold-values == fold" + (equal? (fold-values cons test-doc '()) + (fold cons '() test-doc))) + + (pass-if "foldts*-values == foldts*" + (equal? (foldts*-values + (lambda (tree seed) (values tree '())) + (lambda (tree seed kid-seed) + (cons (reverse kid-seed) seed)) + (lambda (tree seed) + (cons tree seed)) + test-doc + '()) + (foldts* (lambda (seed tree) (values '() tree)) + (lambda (seed kid-seed tree) + (cons (reverse kid-seed) seed)) + (lambda (seed tree) + (cons tree seed)) + '() + test-doc))) + + (let () + (define (replace pred val list) + (reverse + (fold + (lambda (x xs) + (cons (if (pred x) val x) xs)) + '() + list))) + + (define (car-eq? x what) + (and (pair? x) (eq? (car x) what))) + + ;; avoid entering <slide> + (pass-if "foldts* *pre* behaviour" + (equal? (foldts*-values + (lambda (tree seed) + (values (if (car-eq? tree 'slide) '() tree) '())) + (lambda (tree seed kid-seed) + (cons (reverse kid-seed) seed)) + (lambda (tree seed) + (cons tree seed)) + test-doc + '()) + (cons + (replace (lambda (x) (car-eq? x 'slide)) + '() + test-doc) + '())))) + + (let () + (define (all-elts tree) + (reverse! + (foldts*-values + (lambda (tree seed) + (values tree seed)) + (lambda (tree seed kid-seed) + kid-seed) + (lambda (tree seed) + (cons tree seed)) + tree + '()))) + + (define (len tree) + (foldts*-values + (lambda (tree seed) + (values tree seed)) + (lambda (tree seed kid-seed) + kid-seed) + (lambda (tree seed) + (1+ seed)) + tree + 0)) + + (pass-if "foldts length" + (equal? (length (all-elts test-doc)) + (len test-doc))))) + +(with-test-prefix "test-fold-layout" + (define test-doc + '(presentation + (@ (width 1024) + (height 768) + (title-style "font-family:Georgia") + (title-height 72) + (title-baseline-y 96) + (title-x 48) + (text-height 64) + (text-style "font-family:Georgia") + (text-upper-left-x 96) + (text-upper-left-y 216)) + (slide + (@ (title "Declarative interface")) + (p "The declarative interface" + "lets you be more concise" + "when making the slides.")) + (slide + (@ (title "Still cumbersome")) + (p "Parentheses are still" + "cumbersome.")))) + + (define (identity-layout tree) + (fold-layout + tree + `((*default* + . ,(lambda (tag params old-layout layout kids) + (values layout + (if (null? (car params)) + (cons tag kids) + (cons* tag (cons '@ (car params)) kids))))) + (*text* + . ,(lambda (text params layout) + (values layout text)))) + '() + (cons 0 0) + '())) + + (pass-if "fold-layout" + (equal? (accept (identity-layout test-doc)) + (list test-doc (cons 0 0))))) diff --git a/test-suite/tests/sxml.ssax.test b/test-suite/tests/sxml.ssax.test new file mode 100644 index 000000000..f7b9597ab --- /dev/null +++ b/test-suite/tests/sxml.ssax.test @@ -0,0 +1,143 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2004, 2009 Andy Wingo <wingo at pobox dot com> +;; Copyright (C) 2001,2002,2003,2004 Oleg Kiselyov <oleg at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (sxml ssax). You can tweak this harness to get more +;; debugging information, but in the end I just wanted to keep Oleg's +;; tests in the file and see if we could work with them directly. +;; +;;; Code: + +(define-module (test-suite sxml-ssax) + #:use-module (sxml ssax input-parse) + #:use-module (test-suite lib) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-13) + #:use-module (sxml ssax) + #:use-module (ice-9 pretty-print)) + +(define pp pretty-print) + +(define-macro (import module . symbols) + `(begin + ,@(map (lambda (sym) + `(module-define! (current-module) ',sym (module-ref (resolve-module ',module) ',sym))) + symbols))) + +;; This list was arrived at over time. See the problem is that SSAX's +;; test cases are inline with its text, and written in the private +;; language of SSAX. That is to say, they use procedures that (sxml +;; ssax) doesn't export. So here we test that the procedures from (sxml +;; ssax) actually work, but in order to do so we have to pull in private +;; definitions. It's not the greatest solution, but it's what we got. +(import (sxml ssax) + ssax:read-NCName + ssax:read-QName + ssax:largest-unres-name + ssax:Prefix-XML + ssax:resolve-name + ssax:scan-Misc + ssax:assert-token + ssax:handle-parsed-entity + ssax:warn + ssax:skip-pi + ssax:S-chars + ssax:skip-S + ssax:ncname-starting-char? + ssax:define-labeled-arg-macro + let*-values + ssax:make-parser/positional-args + when + make-xml-token + nl + ;unesc-string + parser-error + ascii->char + char->ascii + char-newline + char-return + char-tab + name-compare) + +(define (cout . args) + "Similar to @code{cout << arguments << args}, where @var{argument} can +be any Scheme object. If it's a procedure (e.g. @code{newline}), it's +called without args rather than printed." + (for-each (lambda (x) + (if (procedure? x) (x) (display x))) + args)) + +(define (cerr . args) + "Similar to @code{cerr << arguments << args}, where @var{argument} can +be any Scheme object. If it's a procedure (e.g. @code{newline}), it's +called without args rather than printed." + (format (current-ssax-error-port) + ";;; SSAX warning: ~a\n" args)) + +(define (list-intersperse src-l elem) + (if (null? src-l) src-l + (let loop ((l (cdr src-l)) (dest (cons (car src-l) '()))) + (if (null? l) (reverse dest) + (loop (cdr l) (cons (car l) (cons elem dest))))))) + +(define-syntax failed? + (syntax-rules () + ((_ e ...) + (not (false-if-exception (begin e ... #t)))))) + +(define *saved-port* (current-output-port)) + +(define-syntax assert + (syntax-rules () + ((assert expr ...) + (with-output-to-port *saved-port* + (lambda () + (pass-if '(and expr ...) + (let* ((out (open-output-string)) + (res (with-output-to-port out + (lambda () + (with-ssax-error-to-port (current-output-port) + (lambda () + (and expr ...))))))) + ;; (get-output-string out) + res))))))) + +(define (load-tests file) + (with-input-from-file (%search-load-path file) + (lambda () + (let loop ((sexp (read))) + (cond + ((eof-object? sexp)) + ((and (pair? sexp) (pair? (cdr sexp)) + (eq? (cadr sexp) 'run-test)) + (primitive-eval sexp) + (loop (read))) + ((and (pair? sexp) (eq? (car sexp) 'run-test)) + (primitive-eval sexp) + (loop (read))) + (else + (loop (read)))))))) + +(with-output-to-string + (lambda () + (load-tests "sxml/upstream/SSAX.scm"))) diff --git a/test-suite/tests/sxml.transform.test b/test-suite/tests/sxml.transform.test new file mode 100644 index 000000000..92b0f40ce --- /dev/null +++ b/test-suite/tests/sxml.transform.test @@ -0,0 +1,101 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2004, 2009 Andy Wingo <wingo at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (sxml transform). +;; +;;; Code: + +(define-module (test-suite sxml-transform) + #:use-module (test-suite lib) + #:use-module (sxml transform)) + +(let* ((tree '(root (n1 (n11) "s12" (n13)) + "s2" + (n2 (n21) "s22") + (n3 (n31 (n311)) + "s32" + (n33 (n331) "s332" (n333)) + "s34")))) + (define (test pred-begin pred-end expected) + (pass-if expected + (equal? expected (car (replace-range pred-begin pred-end (list tree)))))) + + ;; Remove one node, "s2" + (test + (lambda (node) + (and (equal? node "s2") '())) + (lambda (node) (list node)) + '(root (n1 (n11) "s12" (n13)) + (n2 (n21) "s22") + (n3 (n31 (n311)) "s32" (n33 (n331) "s332" (n333)) "s34"))) + + ;; Replace one node, "s2" with "s2-new" + (test + (lambda (node) + (and (equal? node "s2") '("s2-new"))) + (lambda (node) (list node)) + '(root (n1 (n11) "s12" (n13)) + "s2-new" + (n2 (n21) "s22") + (n3 (n31 (n311)) "s32" (n33 (n331) "s332" (n333)) "s34"))) + + ;; Replace one node, "s2" with "s2-new" and its brother (n-new "s") + (test + (lambda (node) + (and (equal? node "s2") '("s2-new" (n-new "s")))) + (lambda (node) (list node)) + '(root (n1 (n11) "s12" (n13)) + "s2-new" (n-new "s") + (n2 (n21) "s22") + (n3 (n31 (n311)) "s32" (n33 (n331) "s332" (n333)) "s34"))) + + ;; Remove everything from "s2" onward + (test + (lambda (node) + (and (equal? node "s2") '())) + (lambda (node) #f) + '(root (n1 (n11) "s12" (n13)))) + + ;; Remove everything from "n1" onward + (test + (lambda (node) + (and (pair? node) (eq? 'n1 (car node)) '())) + (lambda (node) #f) + '(root)) + + ;; Replace from n1 through n33 + (test + (lambda (node) + (and (pair? node) + (eq? 'n1 (car node)) + (list node '(n1* "s12*")))) + (lambda (node) + (and (pair? node) + (eq? 'n33 (car node)) + (list node))) + '(root + (n1 (n11) "s12" (n13)) + (n1* "s12*") + (n3 + (n33 (n331) "s332" (n333)) + "s34")))) diff --git a/test-suite/tests/sxml.xpath.test b/test-suite/tests/sxml.xpath.test new file mode 100644 index 000000000..0793f600e --- /dev/null +++ b/test-suite/tests/sxml.xpath.test @@ -0,0 +1,700 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2004, 2009 Andy Wingo <wingo at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (sxml xpath). +;; +;;; Code: + +(define-module (test-suite sxml-xpath) + #:use-module (test-suite lib) + #:use-module (sxml xpath)) + +(define tree1 + '(html + (head (title "Slides")) + (body + (p (@ (align "center")) + (table (@ (style "font-size: x-large")) + (tr + (td (@ (align "right")) "Talks ") + (td (@ (align "center")) " = ") + (td " slides + transition")) + (tr (td) + (td (@ (align "center")) " = ") + (td " data + control")) + (tr (td) + (td (@ (align "center")) " = ") + (td " programs")))) + (ul + (li (a (@ (href "slides/slide0001.gif")) "Introduction")) + (li (a (@ (href "slides/slide0010.gif")) "Summary"))) + ))) + + +;; Example from a posting "Re: DrScheme and XML", +;; Shriram Krishnamurthi, comp.lang.scheme, Nov. 26. 1999. +;; http://www.deja.com/getdoc.xp?AN=553507805 +(define tree3 + '(poem (@ (title "The Lovesong of J. Alfred Prufrock") + (poet "T. S. Eliot")) + (stanza + (line "Let us go then, you and I,") + (line "When the evening is spread out against the sky") + (line "Like a patient etherized upon a table:")) + (stanza + (line "In the room the women come and go") + (line "Talking of Michaelangelo.")))) + +(define (run-test selector node expected) + (pass-if expected + (equal? expected (selector node)))) + +(with-test-prefix "test-all" + + + ;; Location path, full form: child::para + ;; Location path, abbreviated form: para + ;; selects the para element children of the context node + (let ((tree + '(elem (@) (para (@) "para") (br (@)) "cdata" (para (@) "second par")) + ) + (expected '((para (@) "para") (para (@) "second par"))) + ) + (run-test (select-kids (node-typeof? 'para)) tree expected) + (run-test (sxpath '(para)) tree expected)) + + ;; Location path, full form: child::* + ;; Location path, abbreviated form: * + ;; selects all element children of the context node + (let ((tree + '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par")) + ) + (expected + '((para (@) "para") (br (@)) (para "second par"))) + ) + (run-test (select-kids (node-typeof? '*)) tree expected) + (run-test (sxpath '(*)) tree expected)) + + ;; Location path, full form: child::text() + ;; Location path, abbreviated form: text() + ;; selects all text node children of the context node + (let ((tree + '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par")) + ) + (expected + '("cdata")) + ) + (run-test (select-kids (node-typeof? '*text*)) tree expected) + (run-test (sxpath '(*text*)) tree expected)) + + ;; Location path, full form: child::node() + ;; Location path, abbreviated form: node() + ;; selects all the children of the context node, whatever their node type + (let* ((tree + '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par")) + ) + (expected (cdr tree)) + ) + (run-test (select-kids (node-typeof? '*any*)) tree expected) + (run-test (sxpath '(*any*)) tree expected) + ) + + ;; Location path, full form: child::*/child::para + ;; Location path, abbreviated form: */para + ;; selects all para grandchildren of the context node + + (let ((tree + '(elem (@) (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para "third para"))) + ) + (expected + '((para "third para"))) + ) + (run-test + (node-join (select-kids (node-typeof? '*)) + (select-kids (node-typeof? 'para))) + tree expected) + (run-test (sxpath '(* para)) tree expected) + ) + + + ;; Location path, full form: attribute::name + ;; Location path, abbreviated form: @name + ;; selects the 'name' attribute of the context node + + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para (@) "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (expected + '((name "elem"))) + ) + (run-test + (node-join (select-kids (node-typeof? '@)) + (select-kids (node-typeof? 'name))) + tree expected) + (run-test (sxpath '(@ name)) tree expected) + ) + + ;; Location path, full form: attribute::* + ;; Location path, abbreviated form: @* + ;; selects all the attributes of the context node + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (expected + '((name "elem") (id "idz"))) + ) + (run-test + (node-join (select-kids (node-typeof? '@)) + (select-kids (node-typeof? '*))) + tree expected) + (run-test (sxpath '(@ *)) tree expected) + ) + + + ;; Location path, full form: descendant::para + ;; Location path, abbreviated form: .//para + ;; selects the para element descendants of the context node + + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (expected + '((para (@) "para") (para "second par") (para (@) "third para"))) + ) + (run-test + (node-closure (node-typeof? 'para)) + tree expected) + (run-test (sxpath '(// para)) tree expected) + ) + + ;; Location path, full form: self::para + ;; Location path, abbreviated form: _none_ + ;; selects the context node if it is a para element; otherwise selects nothing + + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + ) + (run-test (node-self (node-typeof? 'para)) tree '()) + (run-test (node-self (node-typeof? 'elem)) tree (list tree)) + ) + + ;; Location path, full form: descendant-or-self::node() + ;; Location path, abbreviated form: // + ;; selects the context node, all the children (including attribute nodes) + ;; of the context node, and all the children of all the (element) + ;; descendants of the context node. + ;; This is _almost_ a powerset of the context node. + (let* ((tree + '(para (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (expected + (cons tree + (append (cdr tree) + '((@) "para" (@) "second par" + (@ (name "aa")) (para (@) "third para") + (@) "third para")))) + ) + (run-test + (node-or + (node-self (node-typeof? '*any*)) + (node-closure (node-typeof? '*any*))) + tree expected) + (run-test (sxpath '(//)) tree expected) + ) + + ;; Location path, full form: ancestor::div + ;; Location path, abbreviated form: _none_ + ;; selects all div ancestors of the context node + ;; This Location expression is equivalent to the following: + ; /descendant-or-self::div[descendant::node() = curr_node] + ;; This shows that the ancestor:: axis is actually redundant. Still, + ;; it can be emulated as the following SXPath expression demonstrates. + + ;; The insight behind "ancestor::div" -- selecting all "div" ancestors + ;; of the current node -- is + ;; S[ancestor::div] context_node = + ;; { y | y=subnode*(root), context_node=subnode(subnode*(y)), + ;; isElement(y), name(y) = "div" } + ;; We observe that + ;; { y | y=subnode*(root), pred(y) } + ;; can be expressed in SXPath as + ;; ((node-or (node-self pred) (node-closure pred)) root-node) + ;; The composite predicate 'isElement(y) & name(y) = "div"' corresponds to + ;; (node-self (node-typeof? 'div)) in SXPath. Finally, filter + ;; context_node=subnode(subnode*(y)) is tantamount to + ;; (node-closure (node-eq? context-node)), whereas node-reduce denotes the + ;; the composition of converters-predicates in the filtering context. + + (let* + ((root + '(div (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para (@) "second par") + (div (@ (name "aa")) (para (@) "third para")))) + (context-node ; /descendant::any()[child::text() == "third para"] + (car + ((node-closure + (select-kids + (node-equal? "third para"))) + root))) + (pred + (node-reduce (node-self (node-typeof? 'div)) + (node-closure (node-eq? context-node)) + )) + ) + (run-test + (node-or + (node-self pred) + (node-closure pred)) + root + (cons root + '((div (@ (name "aa")) (para (@) "third para"))))) + ) + + + + ;; Location path, full form: child::div/descendant::para + ;; Location path, abbreviated form: div//para + ;; selects the para element descendants of the div element + ;; children of the context node + + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para") + (div (para "fourth para")))) + ) + (expected + '((para (@) "third para") (para "fourth para"))) + ) + (run-test + (node-join + (select-kids (node-typeof? 'div)) + (node-closure (node-typeof? 'para))) + tree expected) + (run-test (sxpath '(div // para)) tree expected) + ) + + + ;; Location path, full form: /descendant::olist/child::item + ;; Location path, abbreviated form: //olist/item + ;; selects all the item elements that have an olist parent (which is not root) + ;; and that are in the same document as the context node + ;; See the following test. + + ;; Location path, full form: /descendant::td/attribute::align + ;; Location path, abbreviated form: //td/@align + ;; Selects 'align' attributes of all 'td' elements in tree1 + (let ((tree tree1) + (expected + '((align "right") (align "center") (align "center") (align "center")) + )) + (run-test + (node-join + (node-closure (node-typeof? 'td)) + (select-kids (node-typeof? '@)) + (select-kids (node-typeof? 'align))) + tree expected) + (run-test (sxpath '(// td @ align)) tree expected) + ) + + + ;; Location path, full form: /descendant::td[attribute::align] + ;; Location path, abbreviated form: //td[@align] + ;; Selects all td elements that have an attribute 'align' in tree1 + (let ((tree tree1) + (expected + '((td (@ (align "right")) "Talks ") (td (@ (align "center")) " = ") + (td (@ (align "center")) " = ") (td (@ (align "center")) " = ")) + )) + (run-test + (node-reduce + (node-closure (node-typeof? 'td)) + (filter + (node-join + (select-kids (node-typeof? '@)) + (select-kids (node-typeof? 'align))))) + tree expected) + (run-test (sxpath `(// td ,(node-self (sxpath '(@ align))))) tree expected) + (run-test (sxpath '(// (td (@ align)))) tree expected) + (run-test (sxpath '(// ((td) (@ align)))) tree expected) + ;; note! (sxpath ...) is a converter. Therefore, it can be used + ;; as any other converter, for example, in the full-form SXPath. + ;; Thus we can mix the full and abbreviated form SXPath's freely. + (run-test + (node-reduce + (node-closure (node-typeof? 'td)) + (filter + (sxpath '(@ align)))) + tree expected) + ) + + + ;; Location path, full form: /descendant::td[attribute::align = "right"] + ;; Location path, abbreviated form: //td[@align = "right"] + ;; Selects all td elements that have an attribute align = "right" in tree1 + (let ((tree tree1) + (expected + '((td (@ (align "right")) "Talks ")) + )) + (run-test + (node-reduce + (node-closure (node-typeof? 'td)) + (filter + (node-join + (select-kids (node-typeof? '@)) + (select-kids (node-equal? '(align "right")))))) + tree expected) + (run-test (sxpath '(// (td (@ (equal? (align "right")))))) tree expected) + ) + + ;; Location path, full form: child::para[position()=1] + ;; Location path, abbreviated form: para[1] + ;; selects the first para child of the context node + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (expected + '((para (@) "para")) + )) + (run-test + (node-reduce + (select-kids (node-typeof? 'para)) + (node-pos 1)) + tree expected) + (run-test (sxpath '((para 1))) tree expected) + ) + + ;; Location path, full form: child::para[position()=last()] + ;; Location path, abbreviated form: para[last()] + ;; selects the last para child of the context node + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (expected + '((para "second par")) + )) + (run-test + (node-reduce + (select-kids (node-typeof? 'para)) + (node-pos -1)) + tree expected) + (run-test (sxpath '((para -1))) tree expected) + ) + + ;; Illustrating the following Note of Sec 2.5 of XPath: + ;; "NOTE: The location path //para[1] does not mean the same as the + ;; location path /descendant::para[1]. The latter selects the first + ;; descendant para element; the former selects all descendant para + ;; elements that are the first para children of their parents." + + (let ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + ) + (run-test + (node-reduce ; /descendant::para[1] in SXPath + (node-closure (node-typeof? 'para)) + (node-pos 1)) + tree '((para (@) "para"))) + (run-test (sxpath '(// (para 1))) tree + '((para (@) "para") (para (@) "third para"))) + ) + + ;; Location path, full form: parent::node() + ;; Location path, abbreviated form: .. + ;; selects the parent of the context node. The context node may be + ;; an attribute node! + ;; For the last test: + ;; Location path, full form: parent::*/attribute::name + ;; Location path, abbreviated form: ../@name + ;; Selects the name attribute of the parent of the context node + + (let* ((tree + '(elem (@ (name "elem") (id "idz")) + (para (@) "para") (br (@)) "cdata" (para "second par") + (div (@ (name "aa")) (para (@) "third para"))) + ) + (para1 ; the first para node + (car ((sxpath '(para)) tree))) + (para3 ; the third para node + (car ((sxpath '(div para)) tree))) + (div ; div node + (car ((sxpath '(// div)) tree))) + ) + (run-test + (node-parent tree) + para1 (list tree)) + (run-test + (node-parent tree) + para3 (list div)) + (run-test ; checking the parent of an attribute node + (node-parent tree) + ((sxpath '(@ name)) div) (list div)) + (run-test + (node-join + (node-parent tree) + (select-kids (node-typeof? '@)) + (select-kids (node-typeof? 'name))) + para3 '((name "aa"))) + (run-test + (sxpath `(,(node-parent tree) @ name)) + para3 '((name "aa"))) + ) + + ;; Location path, full form: following-sibling::chapter[position()=1] + ;; Location path, abbreviated form: none + ;; selects the next chapter sibling of the context node + ;; The path is equivalent to + ;; let cnode = context-node + ;; in + ;; parent::* / child::chapter [take-after node_eq(self::*,cnode)] + ;; [position()=1] + (let* ((tree + '(document + (preface "preface") + (chapter (@ (id "one")) "Chap 1 text") + (chapter (@ (id "two")) "Chap 2 text") + (chapter (@ (id "three")) "Chap 3 text") + (chapter (@ (id "four")) "Chap 4 text") + (epilogue "Epilogue text") + (appendix (@ (id "A")) "App A text") + (References "References")) + ) + (a-node ; to be used as a context node + (car ((sxpath '(// (chapter (@ (equal? (id "two")))))) tree))) + (expected + '((chapter (@ (id "three")) "Chap 3 text"))) + ) + (run-test + (node-reduce + (node-join + (node-parent tree) + (select-kids (node-typeof? 'chapter))) + (take-after (node-eq? a-node)) + (node-pos 1) + ) + a-node expected) + ) + + ;; preceding-sibling::chapter[position()=1] + ;; selects the previous chapter sibling of the context node + ;; The path is equivalent to + ;; let cnode = context-node + ;; in + ;; parent::* / child::chapter [take-until node_eq(self::*,cnode)] + ;; [position()=-1] + (let* ((tree + '(document + (preface "preface") + (chapter (@ (id "one")) "Chap 1 text") + (chapter (@ (id "two")) "Chap 2 text") + (chapter (@ (id "three")) "Chap 3 text") + (chapter (@ (id "four")) "Chap 4 text") + (epilogue "Epilogue text") + (appendix (@ (id "A")) "App A text") + (References "References")) + ) + (a-node ; to be used as a context node + (car ((sxpath '(// (chapter (@ (equal? (id "three")))))) tree))) + (expected + '((chapter (@ (id "two")) "Chap 2 text"))) + ) + (run-test + (node-reduce + (node-join + (node-parent tree) + (select-kids (node-typeof? 'chapter))) + (take-until (node-eq? a-node)) + (node-pos -1) + ) + a-node expected) + ) + + + ;; /descendant::figure[position()=42] + ;; selects the forty-second figure element in the document + ;; See the next example, which is more general. + + ;; Location path, full form: + ;; child::table/child::tr[position()=2]/child::td[position()=3] + ;; Location path, abbreviated form: table/tr[2]/td[3] + ;; selects the third td of the second tr of the table + (let ((tree ((node-closure (node-typeof? 'p)) tree1)) + (expected + '((td " data + control")) + )) + (run-test + (node-join + (select-kids (node-typeof? 'table)) + (node-reduce (select-kids (node-typeof? 'tr)) + (node-pos 2)) + (node-reduce (select-kids (node-typeof? 'td)) + (node-pos 3))) + tree expected) + (run-test (sxpath '(table (tr 2) (td 3))) tree expected) + ) + + + ;; Location path, full form: + ;; child::para[attribute::type='warning'][position()=5] + ;; Location path, abbreviated form: para[@type='warning'][5] + ;; selects the fifth para child of the context node that has a type + ;; attribute with value warning + (let ((tree + '(chapter + (para "para1") + (para (@ (type "warning")) "para 2") + (para (@ (type "warning")) "para 3") + (para (@ (type "warning")) "para 4") + (para (@ (type "warning")) "para 5") + (para (@ (type "warning")) "para 6")) + ) + (expected + '((para (@ (type "warning")) "para 6")) + )) + (run-test + (node-reduce + (select-kids (node-typeof? 'para)) + (filter + (node-join + (select-kids (node-typeof? '@)) + (select-kids (node-equal? '(type "warning"))))) + (node-pos 5)) + tree expected) + (run-test (sxpath '( (((para (@ (equal? (type "warning"))))) 5 ) )) + tree expected) + (run-test (sxpath '( (para (@ (equal? (type "warning"))) 5 ) )) + tree expected) + ) + + + ;; Location path, full form: + ;; child::para[position()=5][attribute::type='warning'] + ;; Location path, abbreviated form: para[5][@type='warning'] + ;; selects the fifth para child of the context node if that child has a 'type' + ;; attribute with value warning + (let ((tree + '(chapter + (para "para1") + (para (@ (type "warning")) "para 2") + (para (@ (type "warning")) "para 3") + (para (@ (type "warning")) "para 4") + (para (@ (type "warning")) "para 5") + (para (@ (type "warning")) "para 6")) + ) + (expected + '((para (@ (type "warning")) "para 5")) + )) + (run-test + (node-reduce + (select-kids (node-typeof? 'para)) + (node-pos 5) + (filter + (node-join + (select-kids (node-typeof? '@)) + (select-kids (node-equal? '(type "warning")))))) + tree expected) + (run-test (sxpath '( (( (para 5)) (@ (equal? (type "warning")))))) + tree expected) + (run-test (sxpath '( (para 5 (@ (equal? (type "warning")))) )) + tree expected) + ) + + ;; Location path, full form: + ;; child::*[self::chapter or self::appendix] + ;; Location path, semi-abbreviated form: *[self::chapter or self::appendix] + ;; selects the chapter and appendix children of the context node + (let ((tree + '(document + (preface "preface") + (chapter (@ (id "one")) "Chap 1 text") + (chapter (@ (id "two")) "Chap 2 text") + (chapter (@ (id "three")) "Chap 3 text") + (epilogue "Epilogue text") + (appendix (@ (id "A")) "App A text") + (References "References")) + ) + (expected + '((chapter (@ (id "one")) "Chap 1 text") + (chapter (@ (id "two")) "Chap 2 text") + (chapter (@ (id "three")) "Chap 3 text") + (appendix (@ (id "A")) "App A text")) + )) + (run-test + (node-join + (select-kids (node-typeof? '*)) + (filter + (node-or + (node-self (node-typeof? 'chapter)) + (node-self (node-typeof? 'appendix))))) + tree expected) + (run-test (sxpath `(* ,(node-or (node-self (node-typeof? 'chapter)) + (node-self (node-typeof? 'appendix))))) + tree expected) + ) + + + ;; Location path, full form: child::chapter[child::title='Introduction'] + ;; Location path, abbreviated form: chapter[title = 'Introduction'] + ;; selects the chapter children of the context node that have one or more + ;; title children with string-value equal to Introduction + ;; See a similar example: //td[@align = "right"] above. + + ;; Location path, full form: child::chapter[child::title] + ;; Location path, abbreviated form: chapter[title] + ;; selects the chapter children of the context node that have one or + ;; more title children + ;; See a similar example //td[@align] above. + + (let ((tree tree3) + (expected + '("Let us go then, you and I," "In the room the women come and go") + )) + (run-test + (node-join + (node-closure (node-typeof? 'stanza)) + (node-reduce + (select-kids (node-typeof? 'line)) (node-pos 1)) + (select-kids (node-typeof? '*text*))) + tree expected) + (run-test (sxpath '(// stanza (line 1) *text*)) tree expected) + ) + ) diff --git a/test-suite/tests/texinfo.docbook.test b/test-suite/tests/texinfo.docbook.test new file mode 100644 index 000000000..d7c710e60 --- /dev/null +++ b/test-suite/tests/texinfo.docbook.test @@ -0,0 +1,35 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2007, 2009 Andy Wingo <wingo at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (texinfo docbook). +;; +;;; Code: + +(define-module (test-suite texinfo-docbook) + #:use-module (test-suite lib) + #:use-module (texinfo docbook)) + +(with-test-prefix "test-flatten" + (pass-if (equal? + (sdocbook-flatten '(refsect1 (refsect2 (para "foo")))) + '((refsect1) (refsect2) (para "foo"))))) diff --git a/test-suite/tests/texinfo.serialize.test b/test-suite/tests/texinfo.serialize.test new file mode 100644 index 000000000..fa17cf7a8 --- /dev/null +++ b/test-suite/tests/texinfo.serialize.test @@ -0,0 +1,188 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2007, 2009 Andy Wingo <wingo at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (texinfo serialize). +;; +;;; Code: + +(define-module (test-suite texinfo-serialize) + #:use-module (test-suite lib) + #:use-module (texinfo serialize)) + +(with-test-prefix "test-serialize" + (define (assert-serialize stexi str) + (pass-if str (equal? str (stexi->texi stexi)))) + + (assert-serialize '(para) + " + +") + + (assert-serialize '(para "foo") + "foo + +") + + (assert-serialize '(var "foo") + "@var{foo}") + + + ;; i don't remember why braces exists, but as long as it does, a test + ;; is in order + (assert-serialize '(*braces* "foo") + "@{foo@}") + + (assert-serialize '(value (% (key "foo"))) + "@value{foo}") + + (assert-serialize '(ref (% (node "foo"))) + "@ref{foo}") + (assert-serialize '(ref (% (node "foo") (name "bar"))) + "@ref{foo,bar}") + (assert-serialize '(ref (% (node "foo") (name "bar") + (section "qux") (info-file "xyzzy") + (manual "zarg"))) + "@ref{foo,bar,qux,xyzzy,zarg}") + (assert-serialize '(ref (% (section "qux") (info-file "xyzzy") + (node "foo") (name "bar") + (manual "zarg"))) + "@ref{foo,bar,qux,xyzzy,zarg}") + (assert-serialize '(ref (% (node "foo") + (manual "zarg"))) + "@ref{foo,,,,zarg}") + + (assert-serialize '(dots) "@dots{}") + + (assert-serialize '(node (% (name "foo"))) + "@node foo +") + + (assert-serialize '(node (% (name "foo bar"))) + "@node foo bar +") + (assert-serialize '(node (% (name "foo bar") (next "baz"))) + "@node foo bar, baz +") + + (assert-serialize '(title "Foo") + "@title Foo +") + (assert-serialize '(title "Foo is a " (var "bar")) + "@title Foo is a @var{bar} +") + + (assert-serialize '(title "Foo is a " (var "bar") " baz") + "@title Foo is a @var{bar} baz +") + + (assert-serialize '(cindex (% (entry "Bar baz, foo"))) + "@cindex Bar baz, foo +") + + ;; there is a space after @iftex, doesn't matter tho + (assert-serialize '(iftex + (para "This is only for tex.") + (para "Note. Foo.")) + "@iftex +This is only for tex. + +Note. Foo. + +@end iftex + +") + + (assert-serialize '(defun (% (name "frob")) + (para "foo?")) + "@defun frob +foo? + +@end defun + +") + + (assert-serialize '(defun (% (name "frob") (arguments "bar")) + (para "foo?")) + "@defun frob bar +foo? + +@end defun + +") + + (assert-serialize '(defun (% (name "frob") (arguments "bar" " " "baz")) + (para "foo?")) + "@defun frob bar baz +foo? + +@end defun + +") + + (assert-serialize '(defun (% (name "frob") (arguments (var "bar"))) + (para "foo?")) + "@defun frob @var{bar} +foo? + +@end defun + +") + + (assert-serialize '(defunx (% (name "frob") (arguments (var "bar")))) + "@defunx frob @var{bar} +") + + (assert-serialize '(table (% (formatter (var))) + (entry (% (heading "Foo bar " (code "baz"))) + (para "Frobate") + (para "zzzzz"))) + "@table @var +@item Foo bar @code{baz} +Frobate + +zzzzz + +@end table + +") + + (assert-serialize '(verbatim "foo") + "@verbatim +foo +@end verbatim + +") + + (assert-serialize '(deffnx (% (name "foo") (category "bar"))) + "@deffnx bar foo +") + + (assert-serialize '(deffnx (% (name "foo") (category "bar") (arguments "x" " " "y"))) + "@deffnx bar foo x y +") + + (assert-serialize '(deffnx (% (name "foo") (category "bar") (arguments "(" "x" " " (code "int") ")"))) + "@deffnx bar foo (x @code{int}) +") + + ) diff --git a/test-suite/tests/texinfo.string-utils.test b/test-suite/tests/texinfo.string-utils.test new file mode 100644 index 000000000..8d7a80dc2 --- /dev/null +++ b/test-suite/tests/texinfo.string-utils.test @@ -0,0 +1,118 @@ +;; -*- scheme -*- +;;; ---------------------------------------------------------------------- +;;; unit test +;;; Copyright (C) 2003, 2009 Free Software Foundation, Inc. +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program; if not, write to the Free Software +;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +;;; ---------------------------------------------------------------------- +(define-module (test-suite test-string-utils) + #:use-module (test-suite lib) + #:use-module (texinfo string-utils)) + + +;; ********************************************************************** +;; Test for expand-tabs +;; ********************************************************************** +(with-test-prefix "test-beginning-expansion" + (pass-if (equal? " Hello" + (expand-tabs "\tHello"))) + (pass-if (equal? " Hello" + (expand-tabs "\t\tHello")))) + +(with-test-prefix "test-ending-expansion" + (pass-if (equal? "Hello " + (expand-tabs "Hello\t"))) + (pass-if (equal? "Hello " + (expand-tabs "Hello\t\t")))) + +(with-test-prefix "test-middle-expansion" + (pass-if (equal? "Hello there" (expand-tabs "Hello\tthere"))) + (pass-if (equal? "Hello there" (expand-tabs "Hello\t\tthere")))) + +(with-test-prefix "test-alternate-tab-size" + (pass-if (equal? "Hello there" + (expand-tabs "Hello\tthere" 3))) + (pass-if (equal? "Hello there" + (expand-tabs "Hello\tthere" 4))) + (pass-if (equal? "Hello there" + (expand-tabs "Hello\tthere" 5)))) + +;; ********************************************************************** +;; tests for escape-special-chars +;; ********************************************************************** +(with-test-prefix "test-single-escape-char" + (pass-if (equal? "HeElElo" + (escape-special-chars "Hello" #\l #\E)))) + +(with-test-prefix "test-multiple-escape-chars" + (pass-if (equal? "HEeElElo" + (escape-special-chars "Hello" "el" #\E)))) + + +;; ********************************************************************** +;; tests for collapsing-multiple-chars +;; ********************************************************************** +(with-test-prefix "collapse-repeated-chars" + (define test-string + "H e l l o t h e r e") + + (with-test-prefix "test-basic-collapse" + (pass-if (equal? "H e l l o t h e r e" + (collapse-repeated-chars test-string)))) + + (with-test-prefix "test-choose-other-char" + (pass-if (equal? "H-e-l-l-o-t-h-e-r-e" + (collapse-repeated-chars (transform-string test-string #\space #\-) + #\-)))) + + (with-test-prefix "test-choose-maximum-repeats" + (pass-if (equal? "H e l l o t h e r e" + (collapse-repeated-chars test-string #\space 2))) + (pass-if (equal? "H e l l o t h e r e" + (collapse-repeated-chars test-string #\space 3))))) + +;; ********************************************************************** +;; Test of the object itself... +;; ********************************************************************** +(with-test-prefix "text wrapping" + (define test-string " +The last language environment specified with +`set-language-environment'. This variable should be +set only with M-x customize, which is equivalent +to using the function `set-language-environment'. +") + + (with-test-prefix "runs-without-exception" + (pass-if (->bool (fill-string test-string))) + (pass-if (->bool (fill-string test-string #:line-width 20))) + (pass-if (->bool (fill-string test-string #:initial-indent " * " #:tab-width 3)))) + + (with-test-prefix "test-fill-equivalent-to-joined-lines" + (pass-if (equal? (fill-string test-string) + (string-join (string->wrapped-lines test-string) "\n" 'infix)))) + + (with-test-prefix "test-no-collapse-ws" + (pass-if (equal? (fill-string test-string #:collapse-whitespace? #f) + "The last language environment specified with `set-language-environment'. This +variable should be set only with M-x customize, which is equivalent to using +the function `set-language-environment'."))) + + (with-test-prefix "test-no-word-break" + (pass-if (equal? "thisisalongword +blah +blah" + (fill-string "thisisalongword blah blah" + #:line-width 8 + #:break-long-words? #f))))) diff --git a/test-suite/tests/texinfo.test b/test-suite/tests/texinfo.test new file mode 100644 index 000000000..dbc07e4ca --- /dev/null +++ b/test-suite/tests/texinfo.test @@ -0,0 +1,407 @@ +;; -*- scheme -*- +;; guile-lib +;; Copyright (C) 2004, 2009 Andy Wingo <wingo at pobox dot com> +;; Copyright (C) 2001,2002 Oleg Kiselyov <oleg at pobox dot com> + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, contact: +;; +;; Free Software Foundation Voice: +1-617-542-5942 +;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 +;; Boston, MA 02111-1307, USA gnu@gnu.org + +;;; Commentary: +;; +;; Unit tests for (sxml texinfo). Adapted from xml.ssax.scm. +;; +;;; Code: + +(define-module (test-suite texinfo) + #:use-module (test-suite lib) + #:use-module (texinfo)) + +(define exception:eof-while-reading-token + '(parser-error . "^EOF while reading a token")) +(define exception:wrong-character + '(parser-error . "^Wrong character")) +(define exception:eof-while-reading-char-data + '(parser-error . "^EOF while reading char data")) +(define exception:no-settitle + '(parser-error . "^No \\\\n@settitle found")) +(define exception:unexpected-arg + '(parser-error . "^@-command didn't expect more arguments")) +(define exception:bad-enumerate + '(parser-error . "^Invalid")) + +(define nl (string #\newline)) + +(define texinfo:read-verbatim-body + (@@ (texinfo) read-verbatim-body)) +(with-test-prefix "test-read-verbatim-body" + (define (read-verbatim-body-from-string str) + (define (consumer fragment foll-fragment seed) + (cons* (if (equal? foll-fragment (string #\newline)) + (string-append " NL" nl) + foll-fragment) + fragment seed)) + (reverse + (call-with-input-string + str + (lambda (port) (texinfo:read-verbatim-body port consumer '()))))) + + (pass-if (equal? '() + (read-verbatim-body-from-string "@end verbatim\n"))) + + ;; after @verbatim, the current position will always directly after + ;; the newline. + (pass-if-exception "@end verbatim needs a newline" + exception:eof-while-reading-token + (read-verbatim-body-from-string "@end verbatim")) + + (pass-if (equal? '("@@end verbatim" " NL\n") + (read-verbatim-body-from-string "@@end verbatim\n@end verbatim\n"))) + + (pass-if (equal? '("@@@@faosfasf adsfas " " NL\n" " asf @foo{asdf}" " NL\n") + (read-verbatim-body-from-string + "@@@@faosfasf adsfas \n asf @foo{asdf}\n@end verbatim\n"))) + + (pass-if (equal? '("@end verbatim " " NL\n") + (read-verbatim-body-from-string "@end verbatim \n@end verbatim\n")))) + +(define texinfo:read-arguments + (@@ (texinfo) read-arguments)) +(with-test-prefix "test-read-arguments" + (define (read-arguments-from-string str) + (call-with-input-string + str + (lambda (port) (texinfo:read-arguments port #\})))) + + (define (test str expected-res) + (pass-if (equal? expected-res + (read-arguments-from-string str)))) + + (test "}" '()) + (test "foo}" '("foo")) + (test "foo,bar}" '("foo" "bar")) + (test " foo , bar }" '("foo" "bar")) + (test " foo , , bar }" '("foo" #f "bar")) + (test "foo,,bar}" '("foo" #f "bar")) + (pass-if-exception "need a } when reading arguments" + exception:eof-while-reading-token + (call-with-input-string + "foo,,bar" + (lambda (port) (texinfo:read-arguments port #\}))))) + +(define texinfo:complete-start-command + (@@ (texinfo) complete-start-command)) +(with-test-prefix "test-complete-start-command" + (define (test command str) + (call-with-input-string + str + (lambda (port) + (call-with-values + (lambda () + (texinfo:complete-start-command command port)) + list)))) + + (pass-if (equal? '(section () EOL-TEXT) + (test 'section "foo bar baz bonzerts"))) + (pass-if (equal? '(deffnx ((category "Function") (name "foo") (arguments)) EOL-TEXT-ARGS) + (test 'deffnx "Function foo"))) + (pass-if-exception "@emph missing a start brace" + exception:wrong-character + (test 'emph "no brace here")) + (pass-if (equal? '(emph () INLINE-TEXT) + (test 'emph "{foo bar baz bonzerts"))) + (pass-if (equal? '(ref ((node "foo bar") (section "baz") (info-file "bonzerts")) + INLINE-ARGS) + (test 'ref "{ foo bar ,, baz, bonzerts}"))) + (pass-if (equal? '(node ((name "referenced node")) EOL-ARGS) + (test 'node " referenced node\n")))) + +(define texinfo:read-char-data + (@@ (texinfo) read-char-data)) +(define make-texinfo-token cons) +(with-test-prefix "test-read-char-data" + (let* ((code (make-texinfo-token 'START 'code)) + (ref (make-texinfo-token 'EMPTY 'ref)) + (title (make-texinfo-token 'LINE 'title)) + (node (make-texinfo-token 'EMPTY 'node)) + (eof-object (with-input-from-string "" read)) + (str-handler (lambda (fragment foll-fragment seed) + (if (string-null? foll-fragment) + (cons fragment seed) + (cons* foll-fragment fragment seed))))) + (define (test str expect-eof? preserve-ws? expected-data expected-token) + (call-with-values + (lambda () + (call-with-input-string + str + (lambda (port) + (texinfo:read-char-data + port expect-eof? preserve-ws? str-handler '())))) + (lambda (seed token) + (let ((result (reverse seed))) + (pass-if (equal? expected-data result)) + (pass-if (equal? expected-token token)))))) + + ;; add some newline-related tests here + (test "" #t #f '() eof-object) + (test "foo bar baz" #t #f '("foo bar baz") eof-object) + (pass-if-exception "eof reading char data" + exception:eof-while-reading-token + (test "" #f #f '() eof-object)) + (test " " #t #f '(" ") eof-object) + (test " @code{foo} " #f #f '(" ") code) + (test " @code" #f #f '(" ") code) + (test " {text here} asda" #f #f '(" ") (make-texinfo-token 'START '*braces*)) + (test " blah blah} asda" #f #f '(" blah blah") (make-texinfo-token 'END #f)))) + + +(with-test-prefix "test-texinfo->stexinfo" + (define (test str expected-res) + (pass-if (equal? expected-res + (call-with-input-string str texi->stexi)))) + (define (try-with-title title str) + (call-with-input-string + (string-append "foo bar baz\n@settitle " title "\n" str) + texi->stexi)) + (define (test-with-title title str expected-res) + (test (string-append "foo bar baz\n@settitle " title "\n" str) + expected-res)) + (define (test-body str expected-res) + (pass-if (equal? expected-res + (cddr (try-with-title "zog" str))))) + + (define (list-intersperse src-l elem) + (if (null? src-l) src-l + (let loop ((l (cdr src-l)) (dest (cons (car src-l) '()))) + (if (null? l) (reverse dest) + (loop (cdr l) (cons (car l) (cons elem dest))))))) + (define (join-lines . lines) + (apply string-append (list-intersperse lines "\n"))) + + (pass-if-exception "missing @settitle" + exception:no-settitle + (call-with-input-string "@dots{}\n" texi->stexi)) + + (test "\\input texinfo\n@settitle my title\n@dots{}\n" + '(texinfo (% (title "my title")) (para (dots)))) + (test-with-title "my title" "@dots{}\n" + '(texinfo (% (title "my title")) (para (dots)))) + (test-with-title "my title" "@dots{}" + '(texinfo (% (title "my title")) (para (dots)))) + + (pass-if-exception "arg to @dots{}" + exception:unexpected-arg + (call-with-input-string + "foo bar baz\n@settitle my title\n@dots{arg}" + texi->stexi)) + + (test-body "@code{arg}" + '((para (code "arg")))) + (test-body "@code{ }" + '((para (code)))) + (test-body "@code{ @code{} }" + '((para (code (code))))) + (test-body "@code{ abc @code{} }" + '((para (code "abc " (code))))) + (test-body "@code{ arg }" + '((para (code "arg")))) + (test-body "@example\n foo asdf asd sadf asd \n@end example\n" + '((example " foo asdf asd sadf asd "))) + (test-body (join-lines + "@quotation" + "@example" + " foo asdf asd sadf asd " + "@end example" + "@end quotation" + "") + '((quotation (example " foo asdf asd sadf asd ")))) + (test-body (join-lines + "@quotation" + "@example" + " foo asdf @var{asd} sadf asd " + "@end example" + "@end quotation" + "") + '((quotation (example " foo asdf " (var "asd") " sadf asd ")))) + (test-body (join-lines + "@quotation" + "@example" + " foo asdf @var{asd} sadf asd " + "" + "not in new para, this is an example" + "@end example" + "@end quotation" + "") + '((quotation + (example + " foo asdf " (var "asd") + " sadf asd \n\nnot in new para, this is an example")))) + (test-body (join-lines + "@titlepage" + "@quotation" + " foo asdf @var{asd} sadf asd " + "" + "should be in new para" + "@end quotation" + "@end titlepage" + "") + '((titlepage + (quotation (para "foo asdf " (var "asd") " sadf asd") + (para "should be in new para"))))) + (test-body (join-lines + "" + "@titlepage" + "" + "@quotation" + " foo asdf @var{asd} sadf asd " + "" + "should be in new para" + "" + "" + "@end quotation" + "@end titlepage" + "" + "@bye" + "" + "@foo random crap at the end" + "") + '((titlepage + (quotation (para "foo asdf " (var "asd") " sadf asd") + (para "should be in new para"))))) + (test-body (join-lines + "" + "random notes" + "@quotation" + " foo asdf @var{asd} sadf asd " + "" + "should be in new para" + "" + "" + "@end quotation" + "" + " hi mom" + "") + '((para "random notes") + (quotation (para "foo asdf " (var "asd") " sadf asd") + (para "should be in new para")) + (para "hi mom"))) + (test-body (join-lines + "@enumerate" + "@item one" + "@item two" + "@item three" + "@end enumerate" + ) + '((enumerate (item (para "one")) + (item (para "two")) + (item (para "three"))))) + (test-body (join-lines + "@enumerate 44" + "@item one" + "@item two" + "@item three" + "@end enumerate" + ) + '((enumerate (% (start "44")) + (item (para "one")) + (item (para "two")) + (item (para "three"))))) + (pass-if-exception "bad enumerate formatter" + exception:bad-enumerate + (try-with-title "foo" (join-lines + "@enumerate string" + "@item one" + "@item two" + "@item three" + "@end enumerate" + ))) + (pass-if-exception "bad itemize formatter" + exception:bad-enumerate + (try-with-title "foo" (join-lines + "@itemize string" + "@item one" + "@item two" + "@item three" + "@end itemize" + ))) + (test-body (join-lines + "@itemize" ;; no formatter, should default to bullet + "@item one" + "@item two" + "@item three" + "@end itemize" + ) + '((itemize (% (bullet (bullet))) + (item (para "one")) + (item (para "two")) + (item (para "three"))))) + (test-body (join-lines + "@itemize @bullet" + "@item one" + "@item two" + "@item three" + "@end itemize" + ) + '((itemize (% (bullet (bullet))) + (item (para "one")) + (item (para "two")) + (item (para "three"))))) + (test-body (join-lines + "@itemize -" + "@item one" + "@item two" + "@item three" + "@end itemize" + ) + '((itemize (% (bullet "-")) + (item (para "one")) + (item (para "two")) + (item (para "three"))))) + (test-body (join-lines + "@table @code" + "preliminary text -- should go in a pre-item para" + "@item one" + "item one text" + "@item two" + "item two text" + "" + "includes a paragraph" + "@item three" + "@end itemize" + ) + '((table (% (formatter (code))) + (para "preliminary text -- should go in a pre-item para") + (entry (% (heading "one")) + (para "item one text")) + (entry (% (heading "two")) + (para "item two text") + (para "includes a paragraph")) + (entry (% (heading "three")))))) + (test-body (join-lines + "@chapter @code{foo} bar" + "text that should be in a para" + ) + '((chapter (code "foo") " bar") + (para "text that should be in a para"))) + (test-body (join-lines + "@deffnx Method foo bar @code{baz}" + "text that should be in a para" + ) + '((deffnx (% (category "Method") + (name "foo") + (arguments "bar " (code "baz")))) + (para "text that should be in a para"))) + ) |