2022-01-06 23:58:57 -05:00
|
|
|
;;; dag-test.el --- Examples for DAG API -*- lexical-binding: t -*-
|
|
|
|
|
|
|
|
;; Copyright (C) 2015 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; run with 'emacs --batch -l ../../../init.el -l test/dag-test.el -f ert'
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(require 'ht)
|
|
|
|
(require 'dash)
|
|
|
|
(require 'dag)
|
|
|
|
|
|
|
|
;; useful bits
|
|
|
|
|
|
|
|
(defun dag-test-ht-keys (h)
|
|
|
|
(-some-> h (ht-keys)))
|
|
|
|
|
|
|
|
(defun dag-test-ht-get (h k)
|
|
|
|
(-some-> h (ht-get k)))
|
|
|
|
|
|
|
|
(defun dag-test-sets-equal-p (a b)
|
|
|
|
(should (seq-set-equal-p a b #'equal)))
|
|
|
|
|
|
|
|
;; DAG testing predicates
|
|
|
|
;;
|
|
|
|
;; by convention, the curated test value is always the first in binary
|
|
|
|
;; comparisons
|
|
|
|
|
|
|
|
(defun dag-test-has-valid-adjlist-p (dag adjlist-alist)
|
|
|
|
(-let (((&plist :adjlist b) dag))
|
|
|
|
(--each adjlist-alist
|
|
|
|
(-let (((&plist :parents p :children c) (dag-test-ht-get b (car it)))
|
|
|
|
((&plist :parents p* :children c*) (cdr it)))
|
|
|
|
(dag-test-sets-equal-p p* p)
|
|
|
|
(dag-test-sets-equal-p c* c)))
|
|
|
|
(dag-test-sets-equal-p (-map #'car adjlist-alist) (dag-test-ht-keys b))))
|
|
|
|
|
|
|
|
(defun dag-test-has-valid-broken-edges-p (dag broken-edges-alist)
|
|
|
|
(-let (((&plist :broken-edges b) dag))
|
|
|
|
(--each broken-edges-alist
|
|
|
|
(dag-test-sets-equal-p (cdr it) (dag-test-ht-get b (car it))))
|
|
|
|
(dag-test-sets-equal-p (-map #'car broken-edges-alist)
|
|
|
|
(dag-test-ht-keys b))))
|
|
|
|
|
2022-03-06 22:41:12 -05:00
|
|
|
;; (defun dag-test-has-valid-floating-nodes-p (dag floating-nodes)
|
|
|
|
;; (-let (((&plist :floating-nodes f) dag))
|
|
|
|
;; (dag-test-sets-equal-p floating-nodes (dag-test-ht-keys f))))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(defun dag-test-has-valid-order-p (dag order)
|
|
|
|
(-let (((&plist :order o) dag))
|
|
|
|
(should (equal order o))))
|
|
|
|
|
|
|
|
;; test macros
|
|
|
|
|
2022-03-06 22:41:12 -05:00
|
|
|
(defmacro dag-test-dag-is-valid-p (dag adjlist broken-edges order)
|
2022-01-06 23:58:57 -05:00
|
|
|
(declare (indent 1))
|
|
|
|
`(progn
|
|
|
|
(dag-test-has-valid-adjlist-p ,dag ',adjlist)
|
|
|
|
(dag-test-has-valid-broken-edges-p ,dag ',broken-edges)
|
|
|
|
(dag-test-has-valid-order-p ,dag ',order)))
|
|
|
|
|
2022-03-06 22:41:12 -05:00
|
|
|
(defmacro dag-test-alist-is-valid-p (alist adjlist broken-edges order)
|
2022-01-06 23:58:57 -05:00
|
|
|
(declare (indent 1))
|
|
|
|
`(let ((dag (dag-alist-to-dag ',alist)))
|
|
|
|
(dag-test-dag-is-valid-p dag
|
2022-03-06 22:41:12 -05:00
|
|
|
,adjlist ,broken-edges ,order)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(defmacro dag-test-alist-remove-is-valid-p (alist to-remove adjlist broken-edges
|
2022-03-06 22:41:12 -05:00
|
|
|
order)
|
2022-01-06 23:58:57 -05:00
|
|
|
(declare (indent 2))
|
|
|
|
`(let ((dag (->> (dag-alist-to-dag ',alist)
|
|
|
|
(dag-remove-nodes ',to-remove))))
|
|
|
|
(dag-test-dag-is-valid-p dag
|
2022-03-06 22:41:12 -05:00
|
|
|
,adjlist ,broken-edges ,order)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(defmacro dag-test-alist-insert-is-valid-p (alist to-insert adjlist broken-edges
|
2022-03-06 22:41:12 -05:00
|
|
|
order)
|
2022-01-06 23:58:57 -05:00
|
|
|
(declare (indent 2))
|
|
|
|
`(let ((dag (->> (dag-alist-to-dag ',alist)
|
|
|
|
(dag-insert-nodes ',to-insert))))
|
|
|
|
(dag-test-dag-is-valid-p dag
|
2022-03-06 22:41:12 -05:00
|
|
|
,adjlist ,broken-edges ,order)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(defmacro dag-test-alist-edit-is-valid-p (alist to-remove to-insert adjlist
|
2022-03-06 22:41:12 -05:00
|
|
|
broken-edges order)
|
2022-01-06 23:58:57 -05:00
|
|
|
(declare (indent 3))
|
|
|
|
`(let ((dag (->> (dag-alist-to-dag ',alist)
|
|
|
|
(dag-edit-nodes ',to-remove ',to-insert))))
|
|
|
|
(dag-test-dag-is-valid-p dag
|
2022-03-06 22:41:12 -05:00
|
|
|
,adjlist ,broken-edges ,order)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
;; tests
|
|
|
|
|
|
|
|
(ert-deftest dag-test-null ()
|
|
|
|
(dag-test-alist-is-valid-p nil
|
|
|
|
nil
|
|
|
|
nil
|
|
|
|
nil))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-one ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a))
|
2022-03-06 22:41:12 -05:00
|
|
|
((a :children nil :parents nil))
|
2022-01-06 23:58:57 -05:00
|
|
|
nil
|
2022-03-06 22:41:12 -05:00
|
|
|
(a)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-one-cycle ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a :parents (a)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (a) :parents (a)))
|
|
|
|
nil
|
|
|
|
nil))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-one-broken ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a :parents (b)))
|
2022-03-06 22:41:12 -05:00
|
|
|
((a :children nil :parents nil))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a b))
|
2022-03-06 22:41:12 -05:00
|
|
|
(a)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-two ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a) (:id b :parents (a)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b) :parents nil)
|
|
|
|
(b :children nil :parents (a)))
|
|
|
|
nil
|
|
|
|
(a b)))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-two-cycle ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a :parents (b)) (:id b :parents (a)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b) :parents (b))
|
|
|
|
(b :children (a) :parents (a)))
|
|
|
|
nil
|
|
|
|
nil))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-two-floating ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a) (:id b))
|
2022-03-06 22:41:12 -05:00
|
|
|
((a :children nil :parents nil)
|
|
|
|
(b :children nil :parents nil))
|
2022-01-06 23:58:57 -05:00
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-two-broken ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a) (:id b :parents (a c)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b) :parents nil)
|
|
|
|
(b :children nil :parents (a)))
|
|
|
|
((b c))
|
|
|
|
(a b)))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-three-linear ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (b)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b) :parents nil)
|
|
|
|
(b :children (c) :parents (a))
|
|
|
|
(c :children nil :parents (b)))
|
|
|
|
nil
|
|
|
|
(a b c)))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-three-tree ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children nil :parents (a))
|
|
|
|
(c :children nil :parents (a)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-complicated ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (c b))
|
|
|
|
(:id e :parents (c b))
|
|
|
|
(:id x :parents (y))
|
|
|
|
(:id z))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (d e) :parents (a))
|
|
|
|
(c :children (d e) :parents (a))
|
|
|
|
(d :children nil :parents (b c))
|
2022-03-06 22:41:12 -05:00
|
|
|
(e :children nil :parents (b c))
|
|
|
|
(x :children nil :parents nil)
|
|
|
|
(z :children nil :parents nil))
|
2022-01-06 23:58:57 -05:00
|
|
|
((x y))
|
2022-03-25 23:31:41 -04:00
|
|
|
(a x z b c d e)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-remove ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-remove-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (c b))
|
|
|
|
(:id e :parents (c b)))
|
2022-01-06 23:58:57 -05:00
|
|
|
(e)
|
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (d) :parents (a))
|
|
|
|
(c :children (d) :parents (a))
|
|
|
|
(d :children nil :parents (b c)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-remove-break ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-remove-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (c b))
|
|
|
|
(:id e :parents (c b)))
|
2022-01-06 23:58:57 -05:00
|
|
|
(e c)
|
|
|
|
((a :children (b) :parents nil)
|
|
|
|
(b :children (d) :parents (a))
|
|
|
|
(d :children nil :parents (b)))
|
|
|
|
((d c))
|
|
|
|
(a b d)))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-remove-break-float ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-remove-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (b))
|
|
|
|
(:id d :parents (c)))
|
2022-01-06 23:58:57 -05:00
|
|
|
(b)
|
|
|
|
((c :children (d) :parents nil)
|
2022-03-06 22:41:12 -05:00
|
|
|
(d :children nil :parents (c))
|
|
|
|
(a :children nil :parents nil))
|
2022-01-06 23:58:57 -05:00
|
|
|
((c b))
|
2022-03-25 23:31:41 -04:00
|
|
|
(a c d)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-insert ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-insert-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a)))
|
|
|
|
((:id d :parents (c b))
|
|
|
|
(:id e :parents (c b)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (d e) :parents (a))
|
|
|
|
(c :children (d e) :parents (a))
|
|
|
|
(d :children nil :parents (b c))
|
|
|
|
(e :children nil :parents (b c)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d e)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-insert-overwrite ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-insert-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (b)))
|
|
|
|
((:id d :parents (b c x)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (d) :parents (a))
|
|
|
|
(c :children (d) :parents (a))
|
|
|
|
(d :children nil :parents (b c)))
|
|
|
|
((d x))
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-insert-floating ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-insert-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a)))
|
|
|
|
((:id d))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children nil :parents (a))
|
2022-03-06 22:41:12 -05:00
|
|
|
(c :children nil :parents (a))
|
|
|
|
(d :children nil :parents nil))
|
2022-01-06 23:58:57 -05:00
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a d b c)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-insert-broken ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-insert-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a)))
|
|
|
|
((:id d :parents (c x)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children nil :parents (a))
|
|
|
|
(c :children (d) :parents (a))
|
|
|
|
(d :children nil :parents (c)))
|
|
|
|
((d x))
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-insert-fix-broken ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-insert-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id d :parents (c)))
|
|
|
|
((:id c :parents (b)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children (b) :parents nil)
|
|
|
|
(b :children (c) :parents (a))
|
|
|
|
(c :children (d) :parents (b))
|
|
|
|
(d :children nil :parents (c)))
|
|
|
|
nil
|
|
|
|
(a b c d)))
|
|
|
|
|
|
|
|
(ert-deftest dag-test-edit ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-edit-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (b c))
|
|
|
|
(:id e :parents (b c)))
|
2022-01-06 23:58:57 -05:00
|
|
|
(b)
|
2022-03-25 23:31:41 -04:00
|
|
|
((:id c)
|
|
|
|
(:id d :parents (c))
|
|
|
|
(:id a :parents (c)))
|
2022-01-06 23:58:57 -05:00
|
|
|
((a :children nil :parents (c))
|
|
|
|
(c :children (a d e) :parents nil)
|
|
|
|
(d :children nil :parents (c))
|
|
|
|
(e :children nil :parents (c)))
|
|
|
|
((e b))
|
2022-03-25 23:31:41 -04:00
|
|
|
(c a d e)))
|
2022-01-06 23:58:57 -05:00
|
|
|
|
2022-01-15 20:18:23 -05:00
|
|
|
(ert-deftest dag-test-edit-remove ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-edit-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (b c))
|
|
|
|
(:id e :parents (b c)))
|
2022-01-15 20:18:23 -05:00
|
|
|
(e)
|
|
|
|
nil
|
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (d) :parents (a))
|
|
|
|
(c :children (d) :parents (a))
|
|
|
|
(d :children nil :parents (b c)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d)))
|
2022-01-15 20:18:23 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-edit-insert ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-edit-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a)))
|
2022-01-15 20:18:23 -05:00
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
((:id d :parents (c b))
|
|
|
|
(:id e :parents (c b)))
|
2022-01-15 20:18:23 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (d e) :parents (a))
|
|
|
|
(c :children (d e) :parents (a))
|
|
|
|
(d :children nil :parents (b c))
|
|
|
|
(e :children nil :parents (b c)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d e)))
|
2022-01-15 20:18:23 -05:00
|
|
|
|
|
|
|
(ert-deftest dag-test-edit-null ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-edit-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (b c))
|
|
|
|
(:id e :parents (b c)))
|
2022-01-15 20:18:23 -05:00
|
|
|
nil
|
|
|
|
nil
|
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (e d) :parents (a))
|
|
|
|
(c :children (e d) :parents (a))
|
|
|
|
(d :children nil :parents (b c))
|
|
|
|
(e :children nil :parents (b c)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d e)))
|
2022-01-15 20:18:23 -05:00
|
|
|
|
2022-01-22 18:03:34 -05:00
|
|
|
(ert-deftest dag-test-edit-cancel ()
|
2022-03-25 23:31:41 -04:00
|
|
|
(dag-test-alist-edit-is-valid-p ((:id a)
|
|
|
|
(:id b :parents (a))
|
|
|
|
(:id c :parents (a))
|
|
|
|
(:id d :parents (b c))
|
|
|
|
(:id e :parents (b c)))
|
2022-01-22 18:03:34 -05:00
|
|
|
(b d)
|
2022-03-25 23:31:41 -04:00
|
|
|
((:id b :parents (a))
|
|
|
|
(:id d :parents (b c)))
|
2022-01-22 18:03:34 -05:00
|
|
|
((a :children (b c) :parents nil)
|
|
|
|
(b :children (e d) :parents (a))
|
|
|
|
(c :children (e d) :parents (a))
|
|
|
|
(d :children nil :parents (b c))
|
|
|
|
(e :children nil :parents (b c)))
|
|
|
|
nil
|
2022-03-25 23:31:41 -04:00
|
|
|
(a b c d e)))
|
2022-01-22 18:03:34 -05:00
|
|
|
|
2022-01-06 23:58:57 -05:00
|
|
|
;; TODO add test for transitive reduction
|
|
|
|
|
|
|
|
(provide 'dag-test)
|
|
|
|
;;; dag-test.el ends here
|