60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
-
-
+
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
final_logf TEXT DEFAULT 'logs/final.log',
logdat BLOB,
run_duration INTEGER DEFAULT 0,
comment TEXT DEFAULT '',
event_time TIMESTAMP,
fail_count INTEGER DEFAULT 0,
pass_count INTEGER DEFAULT 0,
tags TEXT DEFAULT '',
CONSTRAINT testsconstraint UNIQUE (run_id, testname, item_path)
);")
(sqlite3:execute db "CREATE INDEX tests_index ON tests (run_id, testname);")
(sqlite3:execute db "CREATE VIEW runs_tests AS SELECT * FROM runs INNER JOIN tests ON runs.id=tests.run_id;")
(sqlite3:execute db "CREATE TABLE test_steps
(id INTEGER PRIMARY KEY,
test_id INTEGER,
stepname TEXT,
state TEXT DEFAULT 'NOT_STARTED',
status TEXT DEFAULT 'n/a',event_time TIMESTAMP,
comment TEXT DEFAULT '',
CONSTRAINT test_steps_constraint UNIQUE (test_id,stepname,state));")
(sqlite3:execute db "CREATE TABLE extradat (id INTEGER PRIMARY KEY, run_id INTEGER, key TEXT, val TEXT);")
(sqlite3:execute db "CREATE TABLE metadat (id INTEGER PRIMARY KEY, var TEXT, val TEXT,
CONSTRAINT metadat_constraint UNIQUE (id,var));")
(db:set-var db "MEGATEST_VERSION" megatest-version)
(sqlite3:execute db "CREATE TABLE access_log (id INTEGER PRIMARY KEY, user TEXT, accessed TIMESTAMP, args TEXT);")))
(sqlite3:execute db "CREATE TABLE access_log (id INTEGER PRIMARY KEY, user TEXT, accessed TIMESTAMP, args TEXT);")
(patch-db db)))
db))
;;======================================================================
;; TODO:
;; put deltas into an assoc list with version numbers
;; apply all from last to current
;;======================================================================
(define (patch-db db)
(handle-exceptions
exn
(begin
(print "Exception: " exn)
(print "ERROR: Possible out of date schema, attempting to add table metadata...")
(sqlite3:execute db "CREATE TABLE metadat (id INTEGER PRIMARY KEY, var TEXT, val TEXT,
CONSTRAINT metadat_constraint UNIQUE (id,var));")
(sqlite3:execute db "ALTER TABLE tests ADD COLUMN tags TEXT DEFAULT '';")
(db:set-var db "MEGATEST_VERSION" 1.17)
)
(let ((mver (db:get-var db "MEGATEST_VERSION")))
(print "Current schema version: " mver " current megatest version: " megatest-version)
(if(not mver)
(if (not mver)
(begin
(print "Adding megatest-version to metadata")
(sqlite3:execute db (db:set-var db "MEGATEST_VERSION" megatest-version))))
(if (< mver 1.18)
(begin
(print "Adding tags column to tests table")
(sqlite3:execute db "ALTER TABLE tests ADD COLUMN tags TEXT DEFAULT '';")))
(db:set-var db "MEGATEST_VERSION" megatest-version)
)))
;; (if (< mver 1.18)
;; (begin
;; (print "Adding tags column to tests table")
;; (sqlite3:execute db "ALTER TABLE tests ADD COLUMN tags TEXT DEFAULT '';")))
(if (< mver 1.20)
(begin
(sqlite3:execute db "CREATE TABLE test_meta (id INTEGER PRIMARY KEY,
testname TEXT DEFAULT '',
author TEXT DEFAULT '',
owner TEXT DEFAULT '',
description TEXT DEFAULT '',
reviewed TIMESTAMP,
iterated TEXT DEFAULT '',
avg_runtime REAL,
avg_disk REAL,
tags TEXT DEFAULT '',
CONSTRAINT test_meta_contstraint UNIQUE (id,testname));")
(for-each
(lambda (stmt)
(sqlite3:execute db stmt))
(list
"ALTER TABLE tests ADD COLUMN expected_value REAL;" ;; DO NOT Add a default, we want it to be NULL
"ALTER TABLE tests ADD COLUMN value REAL;"
"ALTER TABLE tests ADD COLUMN tol REAL;"
"ALTER TABLE tests ADD COLUMN tol_perc REAL;"
"ALTER TABLE tests ADD COLUMN first_err TEXT;"
"ALTER TABLE tests ADD COLUMN first_warn TEXT;"
))))
(if (< mver megatest-version)
(db:set-var db "MEGATEST_VERSION" megatest-version)))))
;;======================================================================
;; meta get and set vars
;;======================================================================
;; returns number if string->number is successful, string otherwise
(define (db:get-var db var)
|
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
"")
(if (and (> (length count) 1)
(number? (cadr count)))
(conc " OFFSET " (cadr count))
""))
runpatt)
(vector header res)))
;; replace header and keystr with a call to runs:get-std-run-fields
;; keypatt: '(("key1" "patt1")("key2" "patt2")...)
(define (db:get-runs db keys keypatts runpatt)
(let* ((res '())
(remfields (list "id" "runname" "state" "status" "owner" "event_time"))
(header (append (map key:get-fieldname keys)
remfields))
(keystr (conc (keys->keystr keys) ","
(string-intersperse remfields ","))))
(sqlite3:for-each-row
(lambda (a . x) ;; turn all the fields returned into a vector and add to the list
(set! res (cons (apply vector a x) res)))
db
(conc "SELECT " keystr " FROM runs WHERE runname LIKE ? "
(map (lambda (keypatt)
(conc "AND " (car keypatt) " LIKE " (cadr keypatt) " "))
keypatts)
"ORDER BY event_time DESC;")
runpatt)
(vector header res)))
;; use this one for db-get-run-info
(define-inline (db:get-row vec)(vector-ref vec 1))
;; use (get-value-by-header (db:get-header runinfo)(db:get-row runinfo))
(define (db:get-run-info db run-id)
(let* ((res #f)
|
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
|
-
-
+
+
|
;; done with run when:
;; 0 tests in LAUNCHED, NOT_STARTED, REMOTEHOSTSTART, RUNNING
(define (db:estimated-tests-remaining db run-id)
(let ((res 0))
(sqlite3:for-each-row
(lambda (count)
(set! res count))
db
"SELECT count(id) FROM tests WHERE state in ('LAUNCHED','NOT_STARTED','REMOTEHOSTSTART','RUNNING') AND run_id=?;" run-id)
db ;; NB// KILLREQ means the jobs is still probably running
"SELECT count(id) FROM tests WHERE state in ('LAUNCHED','NOT_STARTED','REMOTEHOSTSTART','RUNNING','KILLREQ') AND run_id=?;" run-id)
res))
;; NB// Sync this with runs:get-test-info
(define (db:get-test-info db run-id testname item-path)
(let ((res #f))
(sqlite3:for-each-row
(lambda (id run-id testname state status event-time host cpuload diskfree uname rundir item-path run_duration final_logf comment)
|
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
;;
(define (db:test-set-rundir! db run-id testname item-path rundir)
(sqlite3:execute
db
"UPDATE tests SET rundir=? WHERE run_id=? AND testname=? AND item_path=?;"
rundir run-id testname item-path))
;;======================================================================
;; Tests meta data
;;======================================================================
;; make-vector-record db testmeta id testname author owner description reviewed iterated avg_runtime avg_disk
(define (make-db:testmeta)(make-vector 10 ""))
(define-inline (db:testmeta-get-id vec) (vector-ref vec 0))
(define-inline (db:testmeta-get-testname vec) (vector-ref vec 1))
(define-inline (db:testmeta-get-author vec) (vector-ref vec 2))
(define-inline (db:testmeta-get-owner vec) (vector-ref vec 3))
(define-inline (db:testmeta-get-description vec) (vector-ref vec 4))
(define-inline (db:testmeta-get-reviewed vec) (vector-ref vec 5))
(define-inline (db:testmeta-get-iterated vec) (vector-ref vec 6))
(define-inline (db:testmeta-get-avg_runtime vec) (vector-ref vec 7))
(define-inline (db:testmeta-get-avg_disk vec) (vector-ref vec 8))
(define-inline (db:testmeta-get-tags vec) (vector-ref vec 9))
(define-inline (db:testmeta-set-id! vec val)(vector-set! vec 0 val))
(define-inline (db:testmeta-set-testname! vec val)(vector-set! vec 1 val))
(define-inline (db:testmeta-set-author! vec val)(vector-set! vec 2 val))
(define-inline (db:testmeta-set-owner! vec val)(vector-set! vec 3 val))
(define-inline (db:testmeta-set-description! vec val)(vector-set! vec 4 val))
(define-inline (db:testmeta-set-reviewed! vec val)(vector-set! vec 5 val))
(define-inline (db:testmeta-set-iterated! vec val)(vector-set! vec 6 val))
(define-inline (db:testmeta-set-avg_runtime! vec val)(vector-set! vec 7 val))
(define-inline (db:testmeta-set-avg_disk! vec val)(vector-set! vec 8 val))
;; read the record given a testname
(define (db:testmeta-get-record db testname)
(let ((res #f))
(sqlite3:for-each-row
(lambda (id testname author owner description reviewed iterated avg_runtime avg_disk tags)
(set! res (vector id testname author owner description reviewed iterated avg_runtime avg_disk tags)))
db "SELECT id,testname,author,owner,description,reviewed,iterated,avg_runtime,avg_disk,tags FROM test_meta WHERE testname=?;"
testname)
res))
;; create a new record for a given testname
(define (db:testmeta-add-record db testname)
(sqlite3:execute db "INSERT OR IGNORE INTO test_meta (testname,author,owner,description,reviewed,iterated,avg_runtime,avg_disk,tags) VALUES (?,'','','','','','','','');" testname))
;; update one of the testmeta fields
(define (db:testmeta-update-field db testname field value)
(sqlite3:execute db (conc "UPDATE test_meta SET " field "=? WHERE testname=?;") value testname))
;;======================================================================
;; Steps
;;======================================================================
;; Run steps
;; make-vector-record "Run steps" db step id test_id stepname step_complete step_pass event_time
(define (make-db:step)(make-vector 6))
(define-inline (db:step-get-id vec) (vector-ref vec 0))
|
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
(lambda (id test-id stepname state status event-time)
(set! res (cons (vector id test-id stepname state status event-time) res)))
db
"SELECT id,test_id,stepname,state,status,event_time FROM test_steps WHERE test_id=? ORDER BY id ASC;" ;; event_time DESC,id ASC;
test-id)
(reverse res)))
;; check that *all* the prereqs are "COMPLETED"
(define (db-get-prereqs-met db run-id waiton)
(let ((res #f)
(not-complete 0)
(tests (db-get-tests-for-run db run-id)))
(for-each
(lambda (test-name)
(for-each
(lambda (test)
(if (equal? (db:test-get-testname test) test-name)
(begin
(set! res #t)
(if (not (equal? (db:test-get-state test) "COMPLETED"))
(set! not-complete (+ 1 not-complete))))))
tests))
waiton)
(and (or (null? waiton) res)
(eq? not-complete 0))))
;; ;; check that *all* the prereqs are "COMPLETED"
;; (define (db-get-prereqs-met db run-id waiton)
;; (let ((res #f)
;; (not-complete 0)
;; (tests (db-get-tests-for-run db run-id)))
;; (for-each
;; (lambda (test-name)
;; (for-each
;; (lambda (test)
;; (if (equal? (db:test-get-testname test) test-name)
;; (begin
;; (set! res #t)
;; (if (not (equal? (db:test-get-state test) "COMPLETED"))
;; (set! not-complete (+ 1 not-complete))))))
;; tests))
;; waiton)
;; (and (or (null? waiton) res)
;; (eq? not-complete 0))))
;; USE: (lset-difference string=? '("a" "b" "c") '("d" "c" "e" "a"))
;;
;; Return a list of prereqs that were NOT met
;; Tests (and all items) in waiton list must be "COMPLETED" and "PASS"
(define (db-get-prereqs-not-met db run-id waiton)
(if (null? waiton)
|