aboutsummaryrefslogtreecommitdiff
;;; Excercise the `resolve' routines.                  -*- Scheme -*-
;;;
;;; Copyright (C) 2009, 2021  Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of Skribilo.
;;;
;;; Skribilo 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 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Skribilo 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, see <http://www.gnu.org/licenses/>.

(define-module (tests resolve)
  #:use-module (skribilo ast)
  #:use-module (skribilo engine)
  #:use-module (skribilo resolve)
  #:use-module (skribilo package base)
  #:use-module (srfi srfi-64))

(define %engine
  (find-engine 'base))


(test-begin "resolve")

(test-assert "parents"
  (let* ((doc (document #:title "Doc"
                (chapter #:title "C"
                  (section #:title "S"
                    (p "par")))))
         (ch  (car (markup-body doc)))
         (sec (car (markup-body ch)))
         (par (car (markup-body sec))))
    (and (is-markup? ch 'chapter)
         (eq? (ast-parent ch) 'unspecified)
         (begin
           (resolve! doc %engine '())
           (and (eq? (ast-parent ch) doc)
                (eq? (ast-parent sec) ch)
                (eq? (ast-parent par) sec))))))

(test-assert "root document has no parent"
  (let ((doc (document #:title "Doc")))
    (resolve! doc %engine '())
    (and (not (ast-parent doc))
         (eq? doc (ast-document doc)))))

(test-assert "nested document has a parent"
  ;; Nested documents are sometimes used in the manual.
  (let* ((doc (document #:title "Doc"
                (document #:title "Nested Doc"
                  (chapter #:title "C"))))
         (sub (car (markup-body doc)))
         (ch  (car (markup-body sub))))
    (resolve! doc %engine '())
    (and (not (ast-parent doc))
         (document? sub)
         (eq? doc (ast-document doc))
         (eq? doc (ast-parent sub)))))

(test-assert "nested document is its own `ast-document'"
  (let* ((doc (document #:title "Doc"
                (document #:title "Nested Doc"
                  (chapter #:title "C"))))
         (sub (car (markup-body doc)))
         (ch  (car (markup-body sub))))
    (resolve! doc %engine '())
    (and (document? sub)
         (eq? sub (ast-document sub))
         (eq? sub (ast-document ch)))))

(test-assert "unresolved node in body"
  (let* ((resolved? #f)
         (doc (document #:title "Doc"
                (resolve (lambda (n e env)
                           (set! resolved? #t))))))
    (and (not resolved?)
         (begin
           (resolve! doc %engine '())
           resolved?))))

(test-assert "unresolved node in unresolved node in body"
  (let* ((resolved? #f)
         (doc (document #:title "Doc"
                (resolve (lambda (n e env)
                           (resolve (lambda (n e env)
                                      (set! resolved? #t))))))))
    (and (not resolved?)
         (begin
           (resolve! doc %engine '())
           resolved?))))

(test-assert "unresolved node in options"
  (let* ((resolved? #f)
         (doc (document #:title
                (resolve (lambda (n e env)
                           (set! resolved? #t)))
                "body...")))
    (and (not resolved?)
         (begin
           (resolve! doc %engine '())
           resolved?))))

(test-assert "unresolved node in processor body"
  (let* ((resolved? #f)
         (doc (document #:title "Doc"
                (processor #:combinator (lambda (e1 e2) e1)
                           (resolve (lambda (n e env)
                                      (set! resolved? #t)))))))
    (and (not resolved?)
         (begin
           (resolve! doc %engine '())
           resolved?))))

(test-assert "unresolved node in nested document"
  (let* ((resolved? #f)
         (doc (document #:title "Outer"
                (document #:title "Inner"
                  (resolve (lambda (n e env)
                             (set! resolved? #t)))))))
    (and (not resolved?)
         (begin
           (resolve! doc %engine '())
           resolved?))))

(test-assert "unresolved node product has a parent"
  (let* ((doc (document #:title "Doc"
                (resolve (lambda (n e env)
                           (chapter #:title "C"))))))
    (resolve! doc %engine '())

    (let ((ch (car (markup-body doc))))
      (and (is-markup? ch 'chapter)
           (eq? (ast-parent ch) doc)))))

(test-assert "node bindings"
  (let* ((doc (document #:title "Doc"
                (chapter #:title "C" #:ident "c"
                  (section #:title "S" #:ident "s"))))
         (ch  (car (markup-body doc)))
         (sec (car (markup-body ch))))
    (and (not (document-lookup-node doc "c"))
         (not (document-lookup-node doc "s"))
         (begin
           (resolve! doc %engine '())
           (and (eq? (document-lookup-node doc "c") ch)
                (eq? (document-lookup-node doc "s") sec))))))

(test-assert "unresolved node bindings"
  ;; Make sure nodes returned by `unresolved' nodes are eventually bound.
  (let* ((doc (document #:title "Doc"
                (resolve (lambda (n e env)
                           (chapter #:title "C" #:ident "c"
                             (section #:title "S" #:ident "s")))))))
    (and (not (document-lookup-node doc "c"))
         (not (document-lookup-node doc "s"))
         (begin
           (resolve! doc %engine '())
           (and (is-markup? (document-lookup-node doc "c") 'chapter)
                (is-markup? (document-lookup-node doc "s") 'section))))))

(test-assert "nested document bindings"
  ;; Bindings in nested documents are scoped.  This was not the case prior
  ;; to 0.9.2.
  (let* ((doc (document #:title "Doc"
                (chapter #:ident "outer")
                (document #:title "Nested Doc"
                  (chapter #:ident "inner"))))
         (out (car  (markup-body doc)))
         (sub (cadr (markup-body doc)))
         (in  (car  (markup-body sub))))
    (resolve! doc %engine '())
    (and (let ((x (document-lookup-node doc "outer")))
           (and (is-markup? x 'chapter)
                (eq? (ast-document x) doc)))
         (not (document-lookup-node doc "inner"))
         (let ((x (document-lookup-node sub "inner")))
           (and (is-markup? x 'chapter)
                (eq? (ast-document x) sub))))))

(test-assert "resolved nested document bindings"
  ;; Prior to 0.9.2, nodes of a sub-document returned by an `unresolved' node
  ;; would be bound in the root document.
  (let* ((doc (document #:title "Doc"
                (resolve (lambda (n e env)
                           (document #:title "Nested Doc"
                             (chapter #:ident "inner")))))))
    (resolve! doc %engine '())
    (and (not (document-lookup-node doc "inner"))
         (let* ((sub (car (markup-body doc)))
                (ch  (car (markup-body sub)))
                (x   (document-lookup-node sub "inner")))
           (and (document? sub)
                (is-markup? x 'chapter)
                (eq? x ch)
                (eq? (ast-parent x) sub)
                (eq? (ast-document x) sub))))))

(test-assert "node bindings in processor body"
  (let* ((doc (document #:title "Doc"
                (processor #:combinator (lambda (e1 e2) e1)
                  (chapter #:ident "c")))))
    (resolve! doc %engine '())
    (let* ((proc (car (markup-body doc)))
           (ch   (car (markup-body proc)))
           (ch*  (document-lookup-node doc "c")))
      (eq? ch ch*))))

(test-end "resolve")