1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; ======================================================================
3 ;;;; File: test-init.lisp
4 ;;;; Authors: Marcus Pearce <m.t.pearce@city.ac.uk>, Kevin Rosenberg
5 ;;;; Created: 30/03/2004
7 ;;;; ======================================================================
9 ;;;; Description ==========================================================
10 ;;;; ======================================================================
12 ;;;; Initialisation utilities for running regression tests on CLSQL.
14 ;;;; ======================================================================
16 ;;; This test suite looks for a configuration file named ".clsql-test.config"
17 ;;; located in the users home directory.
19 ;;; This file contains a single a-list that specifies the connection
20 ;;; specs for each database type to be tested. For example, to test all
21 ;;; platforms, a sample "test.config" may look like:
23 ;;; ((:mysql ("localhost" "a-mysql-db" "user1" "secret"))
24 ;;; (:aodbc ("my-dsn" "a-user" "pass"))
25 ;;; (:postgresql ("localhost" "another-db" "user2" "dont-tell"))
26 ;;; (:postgresql-socket ("pg-server" "a-db-name" "user" "secret-password"))
27 ;;; (:sqlite ("path-to-sqlite-db")))
29 (in-package #:clsql-tests)
31 (defvar *config-pathname*
32 (make-pathname :defaults (user-homedir-pathname)
36 (defvar *rt-connection*)
43 (defvar *test-database-type* nil)
44 (defvar *test-database-user* nil)
47 ((extraterrestrial :initform nil :initarg :extraterrestrial)))
49 (def-view-class person (thing)
50 ((height :db-kind :base :accessor height :type float :nulls-ok t
52 (married :db-kind :base :accessor married :type boolean :nulls-ok t
54 (birthday :nulls-ok t :type clsql-base:wall-time :initarg :birthday)
55 (hobby :db-kind :virtual :initarg :hobby :initform nil)))
57 (def-view-class employee (person)
60 :db-constraints :not-null
66 :db-constraints :not-null
79 :accessor employee-email
86 :accessor employee-company
88 :db-info (:join-class company
90 :foreign-key companyid
96 :accessor employee-manager
98 :db-info (:join-class employee
102 (:base-table employee))
104 (def-view-class company ()
107 :db-constraints :not-null
112 :db-constraints :not-null
123 :db-info (:join-class employee
124 :home-key presidentid
128 :reader company-employees
130 :db-info (:join-class employee
131 :home-key (companyid groupid)
132 :foreign-key (companyid groupid)
134 (:base-table company))
136 (defparameter company1 (make-instance 'company
139 :name "Widgets Inc."))
141 (defparameter employee1 (make-instance 'employee
145 :height (1+ (random 1.00))
146 :birthday (clsql-base:get-time)
147 :first-name "Vladamir"
149 :email "lenin@soviet.org"))
151 (defparameter employee2 (make-instance 'employee
154 :height (1+ (random 1.00))
156 :birthday (clsql-base:get-time)
159 :email "stalin@soviet.org"))
161 (defparameter employee3 (make-instance 'employee
164 :height (1+ (random 1.00))
166 :birthday (clsql-base:get-time)
169 :email "trotsky@soviet.org"))
171 (defparameter employee4 (make-instance 'employee
174 :height (1+ (random 1.00))
176 :birthday (clsql-base:get-time)
178 :last-name "Kruschev"
179 :email "kruschev@soviet.org"))
181 (defparameter employee5 (make-instance 'employee
185 :height (1+ (random 1.00))
186 :birthday (clsql-base:get-time)
188 :last-name "Brezhnev"
189 :email "brezhnev@soviet.org"))
191 (defparameter employee6 (make-instance 'employee
195 :height (1+ (random 1.00))
196 :birthday (clsql-base:get-time)
198 :last-name "Andropov"
199 :email "andropov@soviet.org"))
201 (defparameter employee7 (make-instance 'employee
204 :height (1+ (random 1.00))
206 :birthday (clsql-base:get-time)
207 :first-name "Konstantin"
208 :last-name "Chernenko"
209 :email "chernenko@soviet.org"))
211 (defparameter employee8 (make-instance 'employee
214 :height (1+ (random 1.00))
216 :birthday (clsql-base:get-time)
217 :first-name "Mikhail"
218 :last-name "Gorbachev"
219 :email "gorbachev@soviet.org"))
221 (defparameter employee9 (make-instance 'employee
225 :height (1+ (random 1.00))
226 :birthday (clsql-base:get-time)
229 :email "yeltsin@soviet.org"))
231 (defparameter employee10 (make-instance 'employee
235 :height (1+ (random 1.00))
236 :birthday (clsql-base:get-time)
237 :first-name "Vladamir"
239 :email "putin@soviet.org"))
241 (defun test-connect-to-database (database-type spec)
242 (setf *test-database-type* database-type)
243 (when (>= (length spec) 3)
244 (setq *test-database-user* (third spec)))
246 ;; Connect to the database
248 :database-type database-type
252 (defmacro with-ignore-errors (&rest forms)
255 (lambda (x) (list 'ignore-errors x))
258 (defun test-initialise-database ()
259 ;; Delete the instance records
261 (clsql:delete-instance-records company1)
262 (clsql:delete-instance-records employee1)
263 (clsql:delete-instance-records employee2)
264 (clsql:delete-instance-records employee3)
265 (clsql:delete-instance-records employee4)
266 (clsql:delete-instance-records employee5)
267 (clsql:delete-instance-records employee6)
268 (clsql:delete-instance-records employee7)
269 (clsql:delete-instance-records employee8)
270 (clsql:delete-instance-records employee9)
271 (clsql:delete-instance-records employee10)
272 ;; Drop the required tables if they exist
273 (clsql:drop-view-from-class 'employee)
274 (clsql:drop-view-from-class 'company))
275 ;; Create the tables for our view classes
276 (clsql:create-view-from-class 'employee)
277 (clsql:create-view-from-class 'company)
278 ;; Lenin manages everyone
279 (clsql:add-to-relation employee2 'manager employee1)
280 (clsql:add-to-relation employee3 'manager employee1)
281 (clsql:add-to-relation employee4 'manager employee1)
282 (clsql:add-to-relation employee5 'manager employee1)
283 (clsql:add-to-relation employee6 'manager employee1)
284 (clsql:add-to-relation employee7 'manager employee1)
285 (clsql:add-to-relation employee8 'manager employee1)
286 (clsql:add-to-relation employee9 'manager employee1)
287 (clsql:add-to-relation employee10 'manager employee1)
288 ;; Everyone works for Widgets Inc.
289 (clsql:add-to-relation company1 'employees employee1)
290 (clsql:add-to-relation company1 'employees employee2)
291 (clsql:add-to-relation company1 'employees employee3)
292 (clsql:add-to-relation company1 'employees employee4)
293 (clsql:add-to-relation company1 'employees employee5)
294 (clsql:add-to-relation company1 'employees employee6)
295 (clsql:add-to-relation company1 'employees employee7)
296 (clsql:add-to-relation company1 'employees employee8)
297 (clsql:add-to-relation company1 'employees employee9)
298 (clsql:add-to-relation company1 'employees employee10)
299 ;; Lenin is president of Widgets Inc.
300 (clsql:add-to-relation company1 'president employee1)
301 ;; store these instances
302 (clsql:update-records-from-instance employee1)
303 (clsql:update-records-from-instance employee2)
304 (clsql:update-records-from-instance employee3)
305 (clsql:update-records-from-instance employee4)
306 (clsql:update-records-from-instance employee5)
307 (clsql:update-records-from-instance employee6)
308 (clsql:update-records-from-instance employee7)
309 (clsql:update-records-from-instance employee8)
310 (clsql:update-records-from-instance employee9)
311 (clsql:update-records-from-instance employee10)
312 (clsql:update-records-from-instance company1))
314 (defclass conn-specs ()
315 ((aodbc-spec :accessor aodbc :initform nil)
316 (mysql-spec :accessor mysql :initform nil)
317 (pgsql-spec :accessor postgresql :initform nil)
318 (pgsql-socket-spec :accessor postgresql-socket :initform nil)
319 (sqlite-spec :accessor sqlite :initform nil))
320 (:documentation "Connection specifications for CLSQL testing"))
323 (let ((specs (read-specs)))
325 (warn "Not running tests because test configuration file is missing")
326 (return-from run-tests :skipped))
327 (dolist (accessor '(postgresql postgresql-socket sqlite aodbc mysql))
328 (unless (find-package (symbol-name accessor))
329 (asdf:operate 'asdf:load-op
330 (intern (concatenate 'string
331 (symbol-name '#:clsql-)
332 (symbol-name accessor)))))
334 (dolist (test (append *rt-connection* *rt-fddl* *rt-fdml*
335 *rt-ooddl* *rt-oodml* *rt-syntax*))
338 (let ((spec (funcall accessor specs))
339 (backend (intern (symbol-name accessor) (find-package :keyword))))
341 (format t "~&Running CLSQL tests with ~A backend.~%" backend)
342 (test-connect-to-database backend spec)
343 (test-initialise-database)
344 (rtest:do-tests))))))
346 (defun read-specs (&optional (path *config-pathname*))
347 (if (probe-file path)
348 (with-open-file (stream path :direction :input)
349 (let ((config (read stream))
350 (specs (make-instance 'conn-specs)))
351 (setf (aodbc specs) (cadr (assoc :aodbc config)))
352 (setf (mysql specs) (cadr (assoc :mysql config)))
353 (setf (postgresql specs) (cadr (assoc :postgresql config)))
354 (setf (postgresql-socket specs)
355 (cadr (assoc :postgresql-socket config)))
356 (setf (sqlite specs) (cadr (assoc :sqlite config)))
359 (warn "CLSQL tester config file ~S not found" path)