Index: common.scm ================================================================== --- common.scm +++ common.scm @@ -39,10 +39,11 @@ (define *globalexitstatus* 0) ;; attempt to work around possible thread issues (define *passnum* 0) ;; when running track calls to run-tests or similar (define *verbosity* 1) (define *rpc:listener* #f) ;; if set up for server communication this will hold the tcp port (define *runremote* #f) ;; if set up for server communication this will hold +(define *last-db-access* 0) ;; update when db is accessed via server (define (get-with-default val default) (let ((val (args:get-arg val))) (if val val default))) Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -38,11 +38,13 @@ (define (open-db) ;; (conc *toppath* "/megatest.db") (car *configinfo*))) (let* ((dbpath (conc *toppath* "/megatest.db")) ;; fname) (dbexists (file-exists? dbpath)) (db (sqlite3:open-database dbpath)) ;; (never-give-up-open-db dbpath)) - (handler (make-busy-timeout 3600))) ;; 136000))) + (handler (make-busy-timeout (if (args:get-arg "-override-timeout") + (string->number (args:get-arg "-override-timeout")) + 36000)))) ;; 136000))) (sqlite3:set-busy-handler! db handler) (if (not dbexists) (db:initialize db)) db)) @@ -538,27 +540,27 @@ "SELECT id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment FROM tests WHERE id=?;" test-id) res)) -(define (db:test-set-comment db run-id test-name item-path comment) +(define (db:test-set-comment db test-id comment) (sqlite3:execute db - "UPDATE tests SET comment=? WHERE run_id=? AND testname=? AND item_path=?;" - comment run-id test-name item-path)) + "UPDATE tests SET comment=? WHERE id=?;" + comment test-id)) ;; (define (db:test-set-rundir! db run-id test-name item-path rundir) (sqlite3:execute db "UPDATE tests SET rundir=? WHERE run_id=? AND testname=? AND item_path=?;" rundir run-id test-name item-path)) -(define (db:test-set-log! db run-id test-name item-path logf) +(define (db:test-set-log! db test-id logf) (if (string? logf) - (sqlite3:execute db "UPDATE tests SET final_logf=? WHERE run_id=? AND testname=? AND item_path=?;" - logf run-id test-name item-path) + (sqlite3:execute db "UPDATE tests SET final_logf=? WHERE id=?;" + logf test-id) (debug:print 0 "ERROR: db:test-set-log! called with non-string log file name " logf))) ;;====================================================================== ;; Misc. test related queries ;;====================================================================== @@ -682,14 +684,14 @@ ((step-status) (apply sqlite3:execute step-stmt (vector-ref entry 2))) (else (debug:print 0 "ERROR: Queued entry not recognised " entry)))) data))) + (sqlite3:finalize! meta-stmt) ;; sqlite is the bottleneck, clear the statements asap? + (sqlite3:finalize! step-stmt) (set! *incoming-data* '()) - (mutex-unlock! *incoming-mutex*) - (sqlite3:finalize! meta-stmt) - (sqlite3:finalize! step-stmt))) + (mutex-unlock! *incoming-mutex*))) (define (db:roll-up-pass-fail-counts db run-id test-name item-path status) (if (and (not (equal? item-path "")) (or (equal? status "PASS") (equal? status "WARN") @@ -713,11 +715,13 @@ SET state=CASE WHEN (SELECT count(id) FROM tests WHERE run_id=? AND testname=? AND item_path != '' AND state in ('RUNNING','NOT_STARTED')) > 0 THEN 'RUNNING' ELSE 'COMPLETED' END, status=CASE WHEN fail_count > 0 THEN 'FAIL' WHEN pass_count > 0 AND fail_count=0 THEN 'PASS' ELSE 'UNKNOWN' END WHERE run_id=? AND testname=? AND item_path='';" - run-id test-name run-id test-name))))) + run-id test-name run-id test-name)) + #f) + #f)) ;;====================================================================== ;; Tests meta data ;;====================================================================== @@ -809,26 +813,20 @@ (set! res (cons (vector id test_id category variable value expected tol units comment status type) res))) db "SELECT id,test_id,category,variable,value,expected,tol,units,comment,status,type FROM test_data WHERE test_id=? AND category LIKE ? ORDER BY category,variable;" test-id categorypatt) (reverse res))) -(define (db:load-test-data db run-id test-name itemdat) - (let* ((item-path (item-list->path itemdat)) - (testdat (rdb:get-test-info db run-id test-name item-path)) - (test-id (if testdat (db:test-get-id testdat) #f))) - ;; (debug:print 1 "Enter records to insert in the test_data table, seven fields, comma separated per line") - (debug:print 4 "itemdat: " itemdat ", test-name: " test-name ", test-id: " test-id) - (if test-id - (let loop ((lin (read-line))) - (if (not (eof-object? lin)) - (begin - (debug:print 4 lin) - (rdb:csv->test-data db test-id lin) - (loop (read-line)))))) - ;; roll up the current results. - ;; FIXME: Add the status to - (rdb:test-data-rollup db test-id #f))) +(define (db:load-test-data db test-id) + (let loop ((lin (read-line))) + (if (not (eof-object? lin)) + (begin + (debug:print 4 lin) + (rdb:csv->test-data db test-id lin) + (loop (read-line))))) + ;; roll up the current results. + ;; FIXME: Add the status to + (rdb:test-data-rollup db test-id #f)) ;; WARNING: Do NOT call this for the parent test on an iterated test ;; Roll up test_data pass/fail results ;; look at the test_data status field, ;; if all are pass (any case) and the test status is PASS or NULL or '' then set test status to PASS. @@ -1176,24 +1174,24 @@ (port (vector-ref *runremote* 1))) ((rpc:procedure 'rdb:roll-up-pass-fail-counts host port) run-id test-name item-path status)) (db:roll-up-pass-fail-counts db run-id test-name item-path status))) -(define (rdb:test-set-comment db run-id test-name item-path comment) +(define (rdb:test-set-comment db test-id comment) (if *runremote* (let ((host (vector-ref *runremote* 0)) (port (vector-ref *runremote* 1))) ((rpc:procedure 'rdb:test-set-comment host port) - run-id test-name item-path comment)) - (db:test-set-comment db run-id test-name item-path comment))) + test-id comment)) + (db:test-set-comment db test-id comment))) -(define (rdb:test-set-log! db run-id test-name item-path logf) +(define (rdb:test-set-log! db test-id logf) (if *runremote* (let ((host (vector-ref *runremote* 0)) (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-set-log! host port) run-id test-name item-path logf)) - (db:test-set-log! db run-id test-name item-path logf))) + ((rpc:procedure 'rdb:test-set-log! host port) test-id logf)) + (db:test-set-log! db test-id logf))) (define (rdb:get-runs db runnamepatt numruns startrunoffset keypatts) (if *runremote* (let ((host (vector-ref *runremote* 0)) (port (vector-ref *runremote* 1))) Index: launch.scm ================================================================== --- launch.scm +++ launch.scm @@ -206,11 +206,11 @@ (let ((exinfo (vector-ref exit-info 2)) (logfna (if logpro-used (conc stepname ".html") ""))) ;; testing if procedures called in a remote call cause problems (ans: no or so I suspect) (rdb:teststep-set-status! db test-id stepname "end" exinfo itemdat #f logfna)) (if logpro-used - (test-set-log! db run-id test-name itemdat (conc stepname ".html"))) + (rdb:test-set-log! db test-id (conc stepname ".html"))) ;; set the test final status (let* ((this-step-status (cond ((and (eq? (vector-ref exit-info 2) 2) logpro-used) 'warn) ((eq? (vector-ref exit-info 2) 0) 'pass) (else 'fail))) Index: megatest.scm ================================================================== --- megatest.scm +++ megatest.scm @@ -161,10 +161,11 @@ "-extract-ods" "-pathmod" "-env2file" "-setvars" "-debug" ;; for *verbosity* > 2 + "-override-timeout" ) (list "-h" "-force" "-xterm" "-showkeys" @@ -339,12 +340,16 @@ (args:get-arg "-runtests")))) (let* ((toppath (setup-for-run)) (db (if toppath (open-db) #f))) (debug:print 0 "INFO: Starting the standalone server") (if db - (let ((th2 (server:start db (args:get-arg "-server")))) - (thread-join! th2)) + (let* ((host:port (db:get-var "SERVER")) ;; this doen't support multiple servers BUG!!!! + (th2 (server:start db (args:get-arg "-server"))) + (th3 (lambda () + (server:keep-going db)))) + (thread-start! th3) + (thread-join! th3)) (debug:print 0 "ERROR: Failed to setup for megatest")))) ;;====================================================================== ;; full run ;;====================================================================== @@ -619,13 +624,13 @@ (set! db (open-db)) (if (not (args:get-arg "-server")) (server:client-setup db)) (if (args:get-arg "-load-test-data") ;; has sub commands that are rdb: - (db:load-test-data db run-id test-name itemdat)) + (db:load-test-data db test-id)) (if (args:get-arg "-setlog") - (rdb:test-set-log! db run-id test-name itemdat (args:get-arg "-setlog"))) + (rdb:test-set-log! db test-id (args:get-arg "-setlog"))) (if (args:get-arg "-set-toplog") (rdb:test-set-toplog! db run-id test-name (args:get-arg "-set-toplog"))) (if (args:get-arg "-summarize-items") (rdb:tests:summarize-items db run-id test-name #t)) ;; do force here (if (args:get-arg "-runstep") @@ -669,11 +674,11 @@ (debug:print 2 "INFO: running \"" cmd "\"") (change-directory startingdir) (set! exitstat (system cmd)) (set! *globalexitstatus* exitstat) ;; no necessary (change-directory testpath) - (rdb:test-set-log! db run-id test-name itemdat htmllogfile))) + (rdb:test-set-log! db test-id htmllogfile))) (rdb:teststep-set-status! db test-id stepname "end" exitstat itemdat (args:get-arg "-m") logfile) (sqlite3:finalize! db) (if (not (eq? exitstat 0)) (exit 254)) ;; (exit exitstat) doesn't work?!? ;; open the db Index: runs.scm ================================================================== --- runs.scm +++ runs.scm @@ -259,10 +259,11 @@ (if (not (null? required-tests)) (debug:print 1 "INFO: Adding " required-tests " to the run queue")) ;; NOTE: these are all parent tests, items are not expanded yet. (runs:run-tests-queue db run-id runname test-records keyvallst flags) + (if *rpc:listener* (server:keep-running db)) (debug:print 4 "INFO: All done by here"))) (define (runs:run-tests-queue db run-id runname test-records keyvallst flags) ;; At this point the list of parent tests is expanded ;; NB// Should expand items here and then insert into the run queue. @@ -362,12 +363,13 @@ ;; we get here on "drop through" - loop for next test in queue (if (null? tal) (begin ;; FIXME!!!! THIS SHOULD NOT REQUIRE AN EXIT!!!!!!! - (debug:print 1 "INFO: All tests launched, exiting") - (exit 0)) + (debug:print 1 "INFO: All tests launched") + ;; (exit 0) + ) (loop (car tal)(cdr tal)))))) ;; parent-test is there as a placeholder for when parent-tests can be run as a setup step (define (run:test db run-id runname keyvallst test-record flags parent-test) ;; All these vars might be referenced by the testconfig file reader @@ -597,11 +599,11 @@ (set! db (open-db)) (if (args:get-arg "-server") (server:start db (args:get-arg "-server")) (if (not (or (args:get-arg "-runall") (args:get-arg "-runtests"))) - (set! th1 (server:client-setup db)))) + (server:client-setup db))) (set! keys (rdb:get-keys db)) ;; have enough to process -target or -reqtarg here (if (args:get-arg "-reqtarg") (let* ((runconfigf (conc *toppath* "/runconfigs.config")) ;; DO NOT EVALUATE ALL (runconfig (read-config runconfigf #f #f environ-patt: #f))) Index: server.scm ================================================================== --- server.scm +++ server.scm @@ -62,154 +62,183 @@ ;;====================================================================== ;; ** set-tests-state-status (rpc:publish-procedure! 'rdb:set-tests-state-status (lambda (run-id testnames currstate currstatus newstate newstatus) + (set! *last-db-access* (current-seconds)) (db:set-tests-state-status db run-id testnames currstate currstatus newstate newstatus))) (rpc:publish-procedure! 'rdb:teststep-set-status! (lambda (test-id teststep-name state-in status-in item-path comment logfile) + (set! *last-db-access* (current-seconds)) (db:teststep-set-status! db test-id teststep-name state-in status-in item-path comment logfile))) (rpc:publish-procedure! 'rdb:test-update-meta-info (lambda (run-id testname item-path minutes cpuload diskfree tmpfree) + (set! *last-db-access* (current-seconds)) (db:test-update-meta-info db run-id testname item-path minutes cpuload diskfree tmpfree))) (rpc:publish-procedure! 'rdb:test-set-state-status-by-run-id-testname (lambda (run-id test-name item-path status state) + (set! *last-db-access* (current-seconds)) (db:test-set-state-status-by-run-id-testname db run-id test-name item-path status state))) (rpc:publish-procedure! 'rdb:csv->test-data (lambda (test-id csvdata) + (set! *last-db-access* (current-seconds)) (db:csv->test-data db test-id csvdata))) (rpc:publish-procedure! 'rdb:roll-up-pass-fail-counts (lambda (run-id test-name item-path status) + (set! *last-db-access* (current-seconds)) (db:roll-up-pass-fail-counts db run-id test-name item-path status))) (rpc:publish-procedure! 'rdb:test-set-comment (lambda (run-id test-name item-path comment) + (set! *last-db-access* (current-seconds)) (db:test-set-comment db run-id test-name item-path comment))) (rpc:publish-procedure! 'rdb:test-set-log! (lambda (run-id test-name item-path logf) - (db:test-set-log! db run-id test-name item-path logf))) + (set! *last-db-access* (current-seconds)) + (db:test-set-log! db test-id logf))) (rpc:publish-procedure! 'rdb:get-test-data-by-id (lambda (test-id) + (set! *last-db-access* (current-seconds)) (db:get-test-data-by-id db test-id))) (rpc:publish-procedure! 'serve:get-toppath (lambda () + (set! *last-db-access* (current-seconds)) *toppath*)) (rpc:publish-procedure! 'serve:login (lambda (toppath) + (set! *last-db-access* (current-seconds)) (if (equal? *toppath* toppath) (begin (debug:print 2 "INFO: login successful") #t) #f))) (rpc:publish-procedure! 'rdb:get-runs (lambda (runnamepatt numruns startrunoffset keypatts) + (set! *last-db-access* (current-seconds)) (db:get-runs db runnamepatt numruns startrunoffset keypatts))) (rpc:publish-procedure! 'rdb:get-tests-for-run (lambda (run-id testpatt itempatt states statuses) + (set! *last-db-access* (current-seconds)) (db:get-tests-for-run db run-id testpatt itempatt states statuses))) (rpc:publish-procedure! 'rdb:get-keys (lambda () + (set! *last-db-access* (current-seconds)) (db:get-keys db))) (rpc:publish-procedure! 'rdb:get-num-runs (lambda (runpatt) + (set! *last-db-access* (current-seconds)) (db:get-num-runs db runpatt))) (rpc:publish-procedure! 'rdb:test-set-state-status-by-id (lambda (test-id newstate newstatus newcomment) + (set! *last-db-access* (current-seconds)) (db:test-set-state-status-by-id db test-id newstate newstatus newcomment))) (rpc:publish-procedure! 'rdb:get-key-val-pairs (lambda (run-id) + (set! *last-db-access* (current-seconds)) (db:get-key-val-pairs db run-id))) (rpc:publish-procedure! 'rdb:get-key-vals (lambda (run-id) + (set! *last-db-access* (current-seconds)) (db:get-key-vals db run-id))) (rpc:publish-procedure! 'rdb:testmeta-get-record (lambda (run-id) + (set! *last-db-access* (current-seconds)) (db:testmeta-get-record db run-id))) (rpc:publish-procedure! 'rdb:get-test-data-by-id (lambda (test-id) + (set! *last-db-access* (current-seconds)) (db:get-test-data-by-id db test-id))) (rpc:publish-procedure! 'rdb:get-run-info (lambda (run-id) + (set! *last-db-access* (current-seconds)) (db:get-run-info db run-id))) (rpc:publish-procedure! 'rdb:get-steps-for-test (lambda (test-id) + (set! *last-db-access* (current-seconds)) (db:get-steps-for-test db test-id))) (rpc:publish-procedure! 'rdb:get-steps-table (lambda (test-id) + (set! *last-db-access* (current-seconds)) (db:get-steps-table db test-id))) (rpc:publish-procedure! 'rdb:read-test-data (lambda (test-id categorypatt) + (set! *last-db-access* (current-seconds)) (db:read-test-data db test-id categorypatt))) (rpc:publish-procedure! 'rdb:get-test-info (lambda (run-id testname item-path) + (set! *last-db-access* (current-seconds)) (db:get-test-info db run-id testname item-path))) (rpc:publish-procedure! 'rdb:delete-test-records (lambda (test-id) + (set! *last-db-access* (current-seconds)) (db:delete-test-records db test-id))) (rpc:publish-procedure! 'rtests:register-test (lambda (run-id test-name item-path) + (set! *last-db-access* (current-seconds)) (tests:register-test db run-id test-name item-path))) (rpc:publish-procedure! 'rdb:test-data-rollup (lambda (test-id status) + (set! *last-db-access* (current-seconds)) (db:test-data-rollup db test-id status))) (rpc:publish-procedure! 'rtests:test-set-status! (lambda (run-id test-name state status itemdat-or-path comment dat) + (set! *last-db-access* (current-seconds)) (test-set-status! db run-id test-name state status itemdat-or-path comment dat))) ;;====================================================================== ;; end of publish-procedure section ;;====================================================================== @@ -222,10 +251,27 @@ (thread-start! th2) ;; (thread-join! th2) ;; return th2 for the calling process to do a join with th2 )) ;; rpc:server))) + +(define (server:keep-running db) + ;; if none running or if > 20 seconds since + ;; server last used then start shutdown + (let loop ((count 0)) + (thread-sleep! 20) ;; no need to do this very often + (let ((numrunning (db:get-count-tests-running db))) + (if (or (not (> numrunning 0)) + (> *last-db-access* (+ (current-seconds) 20))) + (begin + (debug:print 0 "INFO: Starting to shutdown the server side") + (sqlite3:execute db "DELETE FROM metadat WHERE var='SERVER'"); ;; AND val like ?;" + ;; host:port) ;; need to delete only *my* server entry (future use) + (thread-sleep! 10) + (debug:print 0 "INFO: Server shutdown complete. Exiting") + (exit)))) + (loop (+ 1 count)))) (define (server:find-free-port-and-open port) (handle-exceptions exn (begin @@ -234,11 +280,13 @@ (rpc:default-server-port port) (tcp-listen (rpc:default-server-port)))) (define (server:client-setup db) (if *runremote* - (debug:print 0 "ERROR: Attempt to connect to server but already connected") + (begin + (debug:print 0 "ERROR: Attempt to connect to server but already connected") + #f) (let* ((hostinfo (db:get-var db "SERVER")) (hostdat (if hostinfo (string-split hostinfo ":"))) (host (if hostinfo (car hostdat))) (port (if (and hostinfo (> (length hostdat) 1))(cadr hostdat) #f))) (if (and port Index: tests.scm ================================================================== --- tests.scm +++ tests.scm @@ -165,33 +165,31 @@ (dcomment (hash-table-ref/default otherdat ":comment" ""))) (debug:print 4 "category: " category ", variable: " variable ", value: " value ", expected: " expected ", tol: " tol ", units: " units) (if (and value expected tol) ;; all three required - (rdb:csv->test-data db test-id - (conc category "," - variable "," - value "," - expected "," - tol "," - units "," - dcomment ",," ;; extra comma for status - type )))) - + (let ((dat (conc category "," + variable "," + value "," + expected "," + tol "," + units "," + dcomment ",," ;; extra comma for status + type ))) + (rdb:csv->test-data db test-id + dat)))) + ;; need to update the top test record if PASS or FAIL and this is a subtest (rdb:roll-up-pass-fail-counts db run-id test-name item-path status) (if (or (and (string? comment) (string-match (regexp "\\S+") comment)) waived) - (rdb:test-set-comment db run-id test-name item-path (if waived waived comment))) + (let ((cmt (if waived waived comment))) + (rdb:test-set-comment db test-id cmt))) )) -(define (test-set-log! db run-id test-name itemdat logf) - (let ((item-path (item-list->path itemdat))) - (rdb:test-set-log! db run-id test-name item-path logf))) - (define (test-set-toplog! db run-id test-name logf) (sqlite3:execute db "UPDATE tests SET final_logf=? WHERE run_id=? AND testname=? AND item_path='';" logf run-id test-name)) (define (tests:summarize-items db run-id test-name force) Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -3,21 +3,36 @@ BINPATH=$(shell realpath ../bin) MEGATEST=$(BINPATH)/megatest PATH := $(BINPATH):$(PATH) RUNNAME := $(shell date +w%V.%u.%H) -runall : - @echo WARNING: These tests will kill megatest and dashboard! - @sleep 3 - killall -9 dboard || true - killall -9 megatest || true - cd ../;make install +runall : test1 test2 + +test1 : cleanprep + $(MEGATEST) -runtests ez_pass -target ubuntu/nfs/none :runname $(RUNNAME)_a -server - + +test2 : cleanprep + $(MEGATEST) -runtests runfirst -target ubuntu/nfs/none :runname $(RUNNAME)_b -server - -debug 10 + +test3 : cleanprep + $(MEGATEST) -runall -target ubuntu/nfs/none :runname $(RUNNAME)_b -m "This is a comment specific to a run" -v -server - + +cleanprep : ../*.scm + sqlite3 megatest.db "delete from metadat where var='SERVER';" mkdir -p /tmp/mt_runs /tmp/mt_links + cd ..;make + @sleep 1 + @if ps -def |awk '{print $8}'|grep megatest; then \ + echo WARNING: These tests will kill megatest and dashboard!; \ + sleep 3; \ + killall -9 dboard || true; \ + killall -9 megatest || true; \ + fi + cd ../;make install $(MEGATEST) -remove-runs :runname $(RUNNAME)% -target %/%/% -testpatt % -itempatt % $(BINPATH)/dboard -rows 15 & - $(MEGATEST) -runall -target ubuntu/nfs/none :runname $(RUNNAME)_a - $(MEGATEST) -runall -target ubuntu/nfs/none :runname $(RUNNAME)_b -m "This is a comment specific to a run" -v -server - + touch cleanprep test : csi -b -I .. ../megatest.scm -- -runall -target ubuntu/afs/tmp :runname blah cd ../;make test make runall