1 ;;;; -*- Mode: Lisp -*- 2 3 ;;;; unification-tests.lisp -- 4 ;;;; CL-UNIFICATION test suite. Requires ptester, the public version of 5 ;;;; Franz's util.test package. 6 7 (defpackage "IT.UNIMIB.DISCO.MA.CL.EXT.DACF.UNIFICATION.TESTS" 8 (:use "CL" "UNIFY" "PTESTER") 9 (:nicknames "CL.EXT.DACF.UNIFICATION.TESTS" "UNIFY.TESTS")) 10 11 (in-package "UNIFY.TESTS") 12 13 ;; nil seems like a lousy default for this 14 (setf *error-protect-tests* t) 15 16 (with-tests (:name "basic constant unification") 17 (test t (unify:environment-p (unify 42 42))) 18 19 (test-error (unify 42 12) :condition-type 'unification-failure) 20 21 (test-error (unify 42 'a) :condition-type 'unification-failure) 22 23 (test t (unify:environment-p (unify 'a 'a))) 24 25 (test t (unify:environment-p (unify '(a s d) '(a s d)))) 26 27 (test t (unify:environment-p (unify '(a (s 42) d) '(a (s 42) d)))) 28 29 (test-error (unify '(a (s forty-two) d) '(a (s 42) z)) 30 :condition-type 'unification-failure) 31 32 (test t (unify:environment-p (unify #(a s d) #(a s d)))) 33 34 (test t (unify:environment-p (unify #2a((a s d) (a s d)) 35 #2a((a s d) (a s d))))) 36 37 (test-error (unify #2a((a s d) (a s d)) 38 #2a((a s d) (a 42 d))) 39 :condition-type 'unification-failure) 40 41 (test t (unify:environment-p (unify "I am a string" "I am a string"))) 42 43 (test-error (unify "I am a string" "I am A string") 44 :condition-type 'unification-failure) 45 46 (test t (let ((*unify-string-case-sensitive-p* nil)) 47 (unify:environment-p (unify "I am a string" "I am A string")))) 48 49 ) 50 51 52 (with-tests (:name "variables unification") 53 (test '(42 T) (find-variable-value '?x (unify 42 '?x)) 54 :multiple-values t) 55 (test '(NIL NIL) (find-variable-value '?y (unify 42 '?x)) 56 :multiple-values t) 57 58 (test '(42 T) (find-variable-value '?x (unify '?x 42)) 59 :multiple-values t) 60 61 (test '(s T) (v? '?x (unify '(a (?x 42) d) '(a (s 42) d))) 62 :multiple-values t) 63 (test '(s T) (v? '?x (unify '(a (?x 42) d) '(a (s 42) d))) 64 :multiple-values t) 65 66 (test '((?x 42) T) (v? '?z (unify '(a (?x 42) d) '(a ?z d))) 67 :multiple-values t :test 'equal) 68 69 (test '(NIL T) (v? '?x (unify '(a (?x 42) d) '(a (() 42) d))) 70 :multiple-values t) 71 72 (test '(NIL NIL) (v? '?variable (unify '(a (() 42) d) '(a (?x 42) d))) 73 :multiple-values t) 74 75 (test t (unify:environment-p (unify '_ '(1 2 3)))) 76 77 (test t (unify:environment-p (unify '_ '(1 _ 3)))) 78 79 (test t (unify:environment-p (unify '(1 2 _) '(1 _ 3)))) 80 81 (test t (unify:environment-p (unify '(1 2 _) '(1 _ 3)))) 82 83 (test '(2 T) (v? '?x (unify #(1 2 _) #(1 ?x 3))) 84 :multiple-values t) 85 86 (test-error (unify '(1 2 _) #(1 _ 3)) 87 :condition-type 'unification-failure 88 :known-failure t 89 :fail-info "Unification on SEQUENCEs does not discriminate type.") 90 ) 91 92 93 (with-tests (:name "basic templates unification") 94 95 (with-tests (:name "number templates unification") 96 (test t (unify:environment-p (unify #T(number 42) 42))) 97 (test t (unify:environment-p (unify 42 #T(number 42)))) 98 (test t (unify:environment-p (unify 42 #T(integer 42)))) 99 (test t (unify:environment-p (unify 42 #T(fixnum 42)))) 100 101 (test t (unify:environment-p (unify 42.0 #T(real 42)))) 102 (test t (unify:environment-p (unify #C(0 1) #T(complex #C(0 1))))) 103 104 (test '(42 T) (v? '?x (unify #T(number ?x) 42)) :multiple-values t) 105 (test '(42 T) (v? '?x (unify #(0 1 42 3 4 5) #T(sequence 0 1 ?x 3 4 5))) 106 :multiple-values t) 107 108 (test-error (unify 42 #T(float 42.0)) 109 :condition-type 'unification-failure 110 :known-failure t 111 :fail-info "Check rules for unification on numeric tower.") 112 ) 113 ) 114 115 116 (eval-when (:compile-toplevel :load-toplevel :execute) 117 118 (defclass test1 () 119 ((a :initarg :a :accessor a) 120 (b :initarg :b :accessor b))) 121 122 (defstruct s-root a) 123 (defstruct (s-child (:include s-root)) b) 124 125 ) 126 127 (with-tests (:name "advanced templates unification") 128 129 (test '(a T) (v? '?x (unify #2A((1 #T(symbol ?x) 3) (_ _ _)) 130 #2A((1 a 3) (q w e)))) 131 :multiple-values t) 132 133 (test '(#\Space T) (ignore-errors (v? '?x (unify "This is a string!" #T(elt 4 ?x)))) 134 :multiple-values t) 135 136 (test '(42 T) (ignore-errors (v? '?x (unify '(0 1 42 3 4 5) #T(nth 2 ?x)))) 137 :multiple-values t) 138 139 (test '(42 T) (ignore-errors (v? '?x (unify '(0 1 42 3 4 5) #T(elt 2 ?x)))) 140 :multiple-values t) 141 142 (test '(42 T) (ignore-errors (v? '?x (unify #(0 1 42 3 4 5) #T(aref 2 ?x)))) 143 :multiple-values t) 144 145 (test '(42 T) (ignore-errors (v? '?x (unify #(0 1 42 3 4 5) #T(elt 2 ?x)))) 146 :multiple-values t) 147 148 (test '(42 T) (v? '?x (unify #2a((0 1 42 3 4 5)) #T(aref (0 2) ?x))) 149 :multiple-values t) 150 151 (test '(42 T) (v? '?x (unify #T(aref (0 2) 42) #2a((0 1 ?x 3 4 5)))) 152 :multiple-values t) 153 154 (test '(42 T) (v? '?x (unify #2a((0 1 ?x 3 4 5)) #T(aref (0 2) 42))) 155 :multiple-values t) 156 157 (test-error (unify #(0 1 42 3 4 5) #T(nth 2 ?x)) 158 :condition-type 'unification-failure 159 :announce t) 160 161 (test '(foo (1) (2) (3)) (let ((result-env (unify '(0 1 #T(list foo _ &rest ?z) 42) 162 '(0 1 (?y bar (1) (2) (3)) 42))) 163 ) 164 (cons (v? '?y result-env) 165 (v? '?z result-env))) 166 :test #'equal) 167 168 (test '(2 T) (v? '?x (unify #T(test1 a #T(list 1 ?x 3 &rest) b "woot") 169 (make-instance 'test1 :a '(1 2 3) :b "woot"))) 170 :multiple-values t) 171 172 (test-error (unify #T(s-root s-root-a '(1 ?x 3 4)) 173 (make-s-root :a '(1 2 3 4))) 174 :condition-type 'unification-failure 175 :announce t 176 ;; #T reader non evaluating sub forms. 177 ) 178 179 (test '(2 T) (v? '?x (unify #T(s-root s-root-a #T(list 1 ?x 3 4)) 180 (make-s-root :a '(1 2 3 4)))) 181 :multiple-values t) 182 183 (test '(2 T) (v? '?x (unify #T(s-root s-root-a (1 ?x 3 4)) 184 (make-s-root :a '(1 2 3 4)))) 185 :multiple-values t) 186 187 (test '(2 T) (v? '?x (unify #T(s-root s-root-a #T(list 1 ?x 3 &rest)) 188 (make-s-root :a '(1 2 3 4)))) 189 :multiple-values t) 190 191 (test '(2 T) (v? '?x (unify #T(s-root s-root-a #(1 ?x 3 4)) 192 (make-s-root :a #(1 2 3 4)))) 193 :multiple-values t) 194 195 (test '(2 T) (v? '?x (unify #T(s-root s-root-a #T(vector 1 ?x 3 &rest)) 196 (make-s-root :a #(1 2 3 4)))) 197 :multiple-values t) 198 199 ) 200 201 (define-condition inner-unification-failure (unification-failure) () 202 (:default-initargs :format-control "Inner unification-failure.")) 203 (define-condition inner-error (simple-error) () 204 (:default-initargs :format-control "Inner error.")) 205 (define-condition outer-error (simple-error) () 206 (:default-initargs :format-control "Outer error.")) 207 208 (defun nested-match-cases (input) 209 (match-case (input) 210 ('(:a ?a :b #T(list &rest ?bs)) 211 (loop for b in ?bs 212 collect (match-case (b) 213 ('(:c ?c) ?c) 214 ('(:d ?d) ?d) 215 (otherwise (error 'inner-error))))) 216 (otherwise (error 'outer-error)))) 217 218 (defun nested-matchf-cases (input) 219 (matchf-case (input) 220 ((:a ?a :b #T(list &rest ?bs)) 221 (loop for b in ?bs 222 collect (matchf-case (b) 223 ((:c ?c) ?c) 224 ((:d ?d) ?d) 225 (otherwise (error 'inner-error))))) 226 (otherwise (error 'outer-error)))) 227 228 (with-tests (:name "control flow") 229 (test-error (nested-match-cases '(:a 42 :b 33)) :condition-type 'outer-error) 230 (test-error (nested-match-cases '(:a 42 :b (33 42))) :condition-type 'inner-error) 231 (test '(42 43 44) (nested-match-cases '(:a 42 :b ((:d 42) (:c 43) (:c 44)))) 232 :test #'equal) 233 234 (test-error (nested-matchf-cases '(:a 42 :b 33)) :condition-type 'outer-error) 235 (test-error (nested-matchf-cases '(:a 42 :b (33 42))) :condition-type 'inner-error) 236 (test '(42 43 44) (nested-matchf-cases '(:a 42 :b ((:d 42) (:c 43) (:c 44)))) 237 :test #'equal) 238 239 (test-error (match ('(x) '(x) :errorp nil) 240 (error 'inner-unification-failure)) 241 :condition-type 'inner-unification-failure) 242 243 (test-error (matchf ((x) '(x) :errorp nil) 244 (error 'inner-unification-failure)) 245 :condition-type 'inner-unification-failure) 246 247 (with-tests (:name "final t-or-otherwise") 248 (test :success (matching () 249 (('x 'y) :fail) 250 (t :success))) 251 (test :success (matching () 252 (('x 'y) :fail) 253 (otherwise :success))) 254 (test :success (match-case ('x) 255 ('y :fail) 256 (t :success))) 257 (test :success (match-case ('x) 258 ('y :fail) 259 (otherwise :success))) 260 (test :success (matchf-case ('(x)) 261 ((y) :fail) 262 (t :success))) 263 (test :success (matchf-case ('(x)) 264 ((y) :fail) 265 (otherwise :success)))) 266 267 (test-error (matching () 268 (('x 'y) :fail) 269 (('x 'x) (error 'inner-unification-failure)) 270 (('?x 'x) x)) 271 :condition-type 'inner-unification-failure) 272 273 (test-error (match-case ('(x)) 274 ('(y) :fail) 275 ('(x) (error 'inner-unification-failure)) 276 ('(?x) x)) 277 :condition-type 'inner-unification-failure) 278 279 (test-error (matchf-case ('(x)) 280 ((y) :fail) 281 ((x) (error 'inner-unification-failure)) 282 ((?x) x)) 283 :condition-type 'inner-unification-failure) 284 285 (test 'sym (match-case ('(sym)) 286 ('(a) :fail) 287 ('(b) :fail) 288 ('(?x) x))) 289 290 (test 'sym (matchf-case ('(sym)) 291 ((a) :fail) 292 ((b) :fail) 293 ((?x) x))) 294 ) 295 296 297 ;;;; end of file -- unification-tests.lisp --