Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -25,11 +25,11 @@ # Special dependencies for the includes tests.o db.o launch.o runs.o dashboard-tests.o dashboard-guimonitor.o monitor.o dashboard.o megatest.o : db_records.scm tests.o runs.o dashboard.o dashboard-tests.o : run_records.scm db.o ezsteps.o keys.o launch.o megatest.o monitor.o runs-for-ref.o runs.o tests.o : key_records.scm tests.o tasks.o dashboard-tasks.o : task_records.scm -runs.o : old-runs.scm test_records.scm +runs.o : test_records.scm $(OFILES) $(GOFILES) : common_records.scm %.o : %.scm csc $(CSCOPTS) -c $< Index: launch.scm ================================================================== --- launch.scm +++ launch.scm @@ -371,13 +371,17 @@ (key-vals (get-key-vals db run-id)) (key-str (string-intersperse key-vals "/")) (dfullp (conc disk-path "/" key-str "/" runname "/" testname item-path)) (toptest-path (conc disk-path "/" key-str "/" runname "/" testname)) - (runsdir (config-lookup *configdat* "setup" "runsdir")) - (lnkpath (conc (if runsdir runsdir (conc *toppath* "/runs")) - "/" key-str "/" runname item-path))) + (runsdir (let ((rd (config-lookup *configdat* "setup" "runsdir"))) + (if rd rd (conc *toppath* "/runs")))) + (lnkpath (conc runsdir "/" key-str "/" runname item-path))) + (if (not (file-exists? runsdir)) + (begin + (debug:print 0 "WARNING: runsdir did not exist! Creating it now at " runsdir) + (system (conc "mkdir -p " runsdir)))) ;; since this is an iterated test this is as good a place as any to ;; update the toptest record with its location rundir (if (not (equal? item-path "")) (db:test-set-rundir! db run-id testname "" toptest-path)) (debug:print 2 "Setting up test run area") @@ -384,15 +388,15 @@ (debug:print 2 " - creating run area in " dfullp) (system (conc "mkdir -p " dfullp)) (debug:print 2 " - creating link from " dfullp "/" testname " to " lnkpath) (system (conc "mkdir -p " lnkpath)) -;; I suspect this section was deleting test directories under some -;; wierd sitations + ;; I suspect this section was deleting test directories under some + ;; wierd sitations? This doesn't make sense - reenabling the rm -f -;; (if (file-exists? (conc lnkpath "/" testname)) -;; (system (conc "rm -f " lnkpath "/" testname))) + (if (file-exists? (conc lnkpath "/" testname)) + (system (conc "rm -f " lnkpath "/" testname))) (system (conc "ln -sf " dfullp " " lnkpath "/" testname)) (if (directory? dfullp) (begin (let* ((cmd (conc "rsync -av" (if (> *verbosity* 1) "" "q") " " test-path "/ " dfullp "/")) (status (system cmd))) Index: megatest.scm ================================================================== --- megatest.scm +++ megatest.scm @@ -324,26 +324,48 @@ ;; run all tests are are Not COMPLETED and PASS or CHECK (if (args:get-arg "-runall") (general-run-call "-runall" "run all tests" - (lambda (db keys keynames keyvallst) - (let* (;; (test-names (get-all-legal-tests))) ;; "PROD" is ignored for now - (runname (args:get-arg ":runname")) - (target (args:get-arg "-target"))) - (if (not target) - (begin - (debug:print 0 "ERROR: -target is a required parameter") - (exit 0))) - (runs:run-tests db - target - runname - (args:get-arg "-testpatt") - (args:get-arg "-itempatt") - user - (make-hash-table)))))) -;; (run-tests db test-names))))) + (lambda (db target runname keys keynames keyvallst) + (runs:run-tests db + target + runname + (args:get-arg "-testpatt") + (args:get-arg "-itempatt") + user + (make-hash-table))))) + +;;====================================================================== +;; run one test +;;====================================================================== + +;; 1. find the config file +;; 2. change to the test directory +;; 3. update the db with "test started" status, set running host +;; 4. process launch the test +;; - monitor the process, update stats in the db every 2^n minutes +;; 5. as the test proceeds internally it calls megatest as each step is +;; started and completed +;; - step started, timestamp +;; - step completed, exit status, timestamp +;; 6. test phone home +;; - if test run time > allowed run time then kill job +;; - if cannot access db > allowed disconnect time then kill job + +(if (args:get-arg "-runtests") + (general-run-call + "-runtests" + "run a test" + (lambda (db target runname keys keynames keyvallst) + (runs:run-tests db + target + runname + (args:get-arg "-runtests") + (args:get-arg "-itempatt") + user + (make-hash-table))))) ;;====================================================================== ;; Rollup into a run ;;====================================================================== (if (args:get-arg "-rollup") @@ -370,35 +392,10 @@ (runspatt (args:get-arg ":runname")) (pathmod (args:get-arg "-pathmod")) (keyvalalist (keys->alist keys "%"))) (db:extract-ods-file db outputfile keyvalalist (if runspatt runspatt "%") pathmod))))) -;;====================================================================== -;; run one test -;;====================================================================== - -;; 1. find the config file -;; 2. change to the test directory -;; 3. update the db with "test started" status, set running host -;; 4. process launch the test -;; - monitor the process, update stats in the db every 2^n minutes -;; 5. as the test proceeds internally it calls megatest as each step is -;; started and completed -;; - step started, timestamp -;; - step completed, exit status, timestamp -;; 6. test phone home -;; - if test run time > allowed run time then kill job -;; - if cannot access db > allowed disconnect time then kill job - -(if (args:get-arg "-runtests") - (general-run-call - "-runtests" - "run a test" - (lambda (db keys keynames keyvallst) - (let ((test-names (string-split (args:get-arg "-runtests") ","))) - (run-tests db test-names))))) - ;;====================================================================== ;; execute the test ;; - gets called on remote host ;; - receives info from the -execute param ;; - passes info to steps via MT_CMDINFO env var (future is to use a dot file) DELETED old-runs.scm Index: old-runs.scm ================================================================== --- old-runs.scm +++ /dev/null @@ -1,305 +0,0 @@ -;; register a test run with the db -(define (register-run db keys) ;; test-name) - (let* ((keystr (keys->keystr keys)) - (comma (if (> (length keys) 0) "," "")) - (andstr (if (> (length keys) 0) " AND " "")) - (valslots (keys->valslots keys)) ;; ?,?,? ... - (keyvallst (keys->vallist keys)) ;; extracts the values from remainder of (argv) - (runname (get-with-default ":runname" #f)) - (state (get-with-default ":state" "no")) - (status (get-with-default ":status" "n/a")) - (allvals (append (list runname state status user) keyvallst)) - (qryvals (append (list runname) keyvallst)) - (key=?str (string-intersperse (map (lambda (k)(conc (key:get-fieldname k) "=?")) keys) " AND "))) - (debug:print 3 "keys: " keys " allvals: " allvals " keyvallst: " keyvallst) - (debug:print 2 "NOTE: using key " (string-intersperse keyvallst "/") " for this run") - (if (and runname (null? (filter (lambda (x)(not x)) keyvallst))) ;; there must be a better way to "apply and" - (let ((res #f)) - (apply sqlite3:execute db (conc "INSERT OR IGNORE INTO runs (runname,state,status,owner,event_time" comma keystr ") VALUES (?,?,?,?,strftime('%s','now')" comma valslots ");") - allvals) - (apply sqlite3:for-each-row - (lambda (id) - (set! res id)) - db - (let ((qry (conc "SELECT id FROM runs WHERE (runname=? " andstr key=?str ");"))) - ;(debug:print 4 "qry: " qry) - qry) - qryvals) - (sqlite3:execute db "UPDATE runs SET state=?,status=? WHERE id=?;" state status res) - res) - (begin - (debug:print 0 "ERROR: Called without all necessary keys") - #f)))) - -;; This is original run-tests, this routine is deprecated and we will transition to using runs:run-tests (see below) -;; -(define (run-tests db test-names) - (let* ((keys (db-get-keys db)) - (keyvallst (keys->vallist keys #t)) - (run-id (register-run db keys)) ;; test-name))) - (deferred '()) ;; delay running these since they have a waiton clause - (runconfigf (conc *toppath* "/runconfigs.config")) - (required-tests '())) - - ;; now add non-directly referenced dependencies (i.e. waiton) - ;; could cache all these since they need to be read again ... - ;; FIXME SOMEDAY - (if (not (null? test-names)) - (let loop ((hed (car test-names)) - (tal (cdr test-names))) - (let* ((config (test:get-testconfig hed #f)) - (waitons (string-split (let ((w (config-lookup config "requirements" "waiton"))) - (if w w ""))))) - (for-each - (lambda (waiton) - (if (and waiton (not (member waiton test-names))) - (begin - (set! required-tests (cons waiton required-tests)) - (set! test-names (append test-names (list waiton)))))) - waitons) - (let ((remtests (delete-duplicates (append waitons tal)))) - (if (not (null? remtests)) - (loop (car remtests)(cdr remtests))))))) - - (if (not (null? required-tests)) - (debug:print 1 "INFO: Adding " required-tests " to the run queue") - (debug:print 1 "INFO: No prerequisites added")) - - ;; on the first pass or call to run-tests set FAILS to NOT_STARTED if - ;; -keepgoing is specified - - (set-megatest-env-vars db run-id) ;; these may be needed by the launching process - - (if (file-exists? runconfigf) - (setup-env-defaults db runconfigf run-id *already-seen-runconfig-info* environ-patt: ".*") - (debug:print 0 "WARNING: You do not have a run config file: " runconfigf)) - - (if (and (eq? *passnum* 0) - (args:get-arg "-keepgoing")) - (begin - ;; have to delete test records where NOT_STARTED since they can cause -keepgoing to - ;; get stuck due to becoming inaccessible from a failed test. I.e. if test B depends - ;; on test A but test B reached the point on being registered as NOT_STARTED and test - ;; A failed for some reason then on re-run using -keepgoing the run can never complete. - (db:delete-tests-in-state db run-id "NOT_STARTED") - (db:set-tests-state-status db run-id test-names #f "FAIL" "NOT_STARTED" "FAIL"))) - (set! *passnum* (+ *passnum* 1)) - (let loop ((numtimes 0)) - (for-each - (lambda (test-name) - (if (runs:can-run-more-tests db) - (run-one-test db run-id test-name keyvallst) - ;; add some delay - ;(sleep 2) - )) - (tests:sort-by-priority-and-waiton test-names)) - ;; (run-waiting-tests db) - (if (args:get-arg "-keepgoing") - (let ((estrem (db:estimated-tests-remaining db run-id))) - (if (and (> estrem 0) - (eq? *globalexitstatus* 0)) - (begin - (debug:print 1 "Keep going, estimated " estrem " tests remaining to run, will continue in 3 seconds ...") - (thread-sleep! 3) - (run-waiting-tests db) - (loop (+ numtimes 1))))))))) - -;; VERY INEFFICIENT! Move stuff that should be done once up to calling proc -(define (run-one-test db run-id test-name keyvallst) - (debug:print 1 "Launching test " test-name) - ;; All these vars might be referenced by the testconfig file reader - (setenv "MT_TEST_NAME" test-name) ;; - (setenv "MT_RUNNAME" (args:get-arg ":runname")) - - ;; (set-megatest-env-vars db run-id) ;; these may be needed by the launching process - - (change-directory *toppath*) - (let* ((test-path (conc *toppath* "/tests/" test-name)) ;; could use test:get-testconfig here ... - (test-configf (conc test-path "/testconfig")) - (testexists (and (file-exists? test-configf)(file-read-access? test-configf))) - (test-conf (if testexists (read-config test-configf #f #t) (make-hash-table))) - (waiton (let ((w (config-lookup test-conf "requirements" "waiton"))) - (if (string? w)(string-split w)'()))) - (tags (let ((t (config-lookup test-conf "setup" "tags"))) - ;; we want our tags to be separated by commas and fully delimited by commas - ;; so that queries with "like" can tie to the commas at either end of each tag - ;; while also allowing the end user to freely use spaces and commas to separate tags - (if (string? t)(string-substitute (regexp "[,\\s]+") "," (conc "," t ",") #t) - '())))) - (if (not testexists) - (begin - (debug:print 0 "ERROR: Can't find config file " test-configf) - (exit 2)) - ;; put top vars into convenient variables and open the db - (let* (;; db is always at *toppath*/db/megatest.db - (items (hash-table-ref/default test-conf "items" '())) - (itemstable (hash-table-ref/default test-conf "itemstable" '())) - (allitems (if (or (not (null? items))(not (null? itemstable))) - (append (item-assoc->item-list items) - (item-table->item-list itemstable)) - '(())))) ;; a list with one null list is a test with no items -;; (runconfigf (conc *toppath* "/runconfigs.config"))) - (debug:print 1 "items: ") - (if (>= *verbosity* 1)(pp allitems)) - (if (>= *verbosity* 5) - (begin - (print "items: ")(pp (item-assoc->item-list items)) - (print "itestable: ")(pp (item-table->item-list itemstable)))) - (if (args:get-arg "-m") - (db:set-comment-for-run db run-id (args:get-arg "-m"))) - - ;; Here is where the test_meta table is best updated - (runs:update-test_meta db test-name test-conf) - - ;; braindead work-around for poorly specified allitems list BUG!!! FIXME - (if (null? allitems)(set! allitems '(()))) - (let loop ((itemdat (car allitems)) - (tal (cdr allitems))) - ;; (lambda (itemdat) ;;; ((ripeness "overripe") (temperature "cool") (season "summer")) - ;; Handle lists of items - (let* ((item-path (item-list->path itemdat)) ;; (string-intersperse (map cadr itemdat) "/")) - (new-test-path (string-intersperse (cons test-path (map cadr itemdat)) "/")) - (new-test-name (if (equal? item-path "") test-name (conc test-name "/" item-path))) ;; just need it to be unique - (testdat #f) - (num-running (db:get-count-tests-running db)) - (max-concurrent-jobs (config-lookup *configdat* "setup" "max_concurrent_jobs")) - (parent-test (and (not (null? items))(equal? item-path ""))) - (single-test (and (null? items) (equal? item-path ""))) - (item-test (not (equal? item-path ""))) - (item-patt (args:get-arg "-itempatt")) - (patt-match (if item-patt - (string-search (glob->regexp - (string-translate item-patt "%" "*")) - item-path) - #t))) - (debug:print 3 "max-concurrent-jobs: " max-concurrent-jobs ", num-running: " num-running) - (if (and patt-match (runs:can-run-more-tests db)) - (begin - (let loop2 ((ts (db:get-test-info db run-id test-name item-path)) ;; #f) - (ct 0)) - (if (and (not ts) - (< ct 10)) - (begin - (register-test db run-id test-name item-path) - (db:test-set-comment db run-id test-name item-path "") - (loop2 (db:get-test-info db run-id test-name item-path) - (+ ct 1))) - (if ts - (set! testdat ts) - (begin - (debug:print 0 "WARNING: Couldn't register test " test-name " with item path " item-path ", skipping") - (if (not (null? tal)) - (loop (car tal)(cdr tal))))))) - (change-directory test-path) - ;; this block is here only to inform the user early on - - ;; NB// Moving the setting of runconfig.config vars to *before* the - ;; the calling of each test. - ;; (if (file-exists? runconfigf) - ;; (setup-env-defaults db runconfigf run-id *already-seen-runconfig-info*) - ;; (debug:print 0 "WARNING: You do not have a run config file: " runconfigf)) - (debug:print 4 "run-id: " run-id " test-name: " test-name " item-path: " item-path " testdat: " (test:get-status testdat) " test-state: " (test:get-state testdat)) - (case (if (args:get-arg "-force") - 'NOT_STARTED - (if testdat - (string->symbol (test:get-state testdat)) - 'failed-to-insert)) - ((failed-to-insert) - (debug:print 0 "ERROR: Failed to insert the record into the db")) - ((NOT_STARTED COMPLETED) - (debug:print 6 "Got here, " (test:get-state testdat)) - (let ((runflag #f)) - (cond - ;; i.e. this is the parent test to a suite of items, never "run" it - (parent-test - (set! runflag #f)) - ;; -force, run no matter what - ((args:get-arg "-force")(set! runflag #t)) - ;; NOT_STARTED, run no matter what - ((equal? (test:get-state testdat) "NOT_STARTED")(set! runflag #t)) - ;; not -rerun and PASS, WARN or CHECK, do no run - ((and (or (not (args:get-arg "-rerun")) - (args:get-arg "-keepgoing")) - (member (test:get-status testdat) '("PASS" "WARN" "CHECK"))) - (set! runflag #f)) - ;; -rerun and status is one of the specifed, run it - ((and (args:get-arg "-rerun") - (let ((rerunlst (string-split (args:get-arg "-rerun") ","))) ;; FAIL, - (member (test:get-status testdat) rerunlst))) - (set! runflag #t)) - ;; -keepgoing, do not rerun FAIL - ((and (args:get-arg "-keepgoing") - (member (test:get-status testdat) '("FAIL"))) - (set! runflag #f)) - ((and (not (args:get-arg "-rerun")) - (member (test:get-status testdat) '("FAIL" "n/a"))) - (set! runflag #t)) - (else (set! runflag #f))) - (debug:print 6 "RUNNING => runflag: " runflag " STATE: " (test:get-state testdat) " STATUS: " (test:get-status testdat)) - (if (not runflag) - (if (not parent-test) - (debug:print 1 "NOTE: Not starting test " new-test-name " as it is state \"COMPLETED\" and status \"" (test:get-status testdat) "\", use -force to override")) - (let* ((get-prereqs-cmd (lambda () - (db-get-prereqs-not-met db run-id waiton))) ;; check before running .... - (launch-cmd (lambda () - (launch-test db run-id (args:get-arg ":runname") test-conf keyvallst test-name test-path itemdat args:arg-hash))) - (testrundat (list get-prereqs-cmd launch-cmd))) - (if (or (args:get-arg "-force") - (let ((preqs-not-yet-met ((car testrundat)))) - (debug:print 2 "Preqrequesites for " test-name ": " preqs-not-yet-met) - (null? preqs-not-yet-met))) ;; are there any tests that must be run before this one... - (if (not ((cadr testrundat))) ;; this is the line that launches the test to the remote host - (begin - (print "ERROR: Failed to launch the test. Exiting as soon as possible") - (set! *globalexitstatus* 1) ;; - (process-signal (current-process-id) signal/kill) - ;(exit 1) - )) - (if (not (args:get-arg "-keepgoing")) - (hash-table-set! *waiting-queue* new-test-name testrundat))))))) - ((KILLED) - (debug:print 1 "NOTE: " new-test-name " is already running or was explictly killed, use -force to launch it.")) - ((LAUNCHED REMOTEHOSTSTART RUNNING) - (if (> (- (current-seconds)(+ (db:test-get-event_time testdat) - (db:test-get-run_duration testdat))) - 100) ;; i.e. no update for more than 100 seconds - (begin - (debug:print 0 "WARNING: Test " test-name " appears to be dead. Forcing it to state INCOMPLETE and status STUCK/DEAD") - (test-set-status! db run-id test-name "INCOMPLETE" "STUCK/DEAD" itemdat "Test is stuck or dead" #f)) - (debug:print 2 "NOTE: " test-name " is already running"))) - (else (debug:print 0 "ERROR: Failed to launch test " new-test-name ". Unrecognised state " (test:get-state testdat)))))) - (if (not (null? tal)) - (loop (car tal)(cdr tal))))))))) - -(define (run-waiting-tests db) - (let ((numtries 0) - (last-try-time (current-seconds)) - (times (list 1))) ;; minutes to wait before trying again to kick off runs - ;; BUG this hack of brute force retrying works quite well for many cases but - ;; what is needed is to check the db for tests that have failed less than - ;; N times or never been started and kick them off again - (let loop ((waiting-test-names (hash-table-keys *waiting-queue*))) - (cond - ((not (runs:can-run-more-tests db)) - (thread-sleep! 2) - (loop waiting-test-names)) - ((null? waiting-test-names) - (debug:print 1 "All tests launched")) - (else - (set! numtries (+ numtries 1)) - (for-each (lambda (testname) - (if (runs:can-run-more-tests db) - (let* ((testdat (hash-table-ref *waiting-queue* testname)) - (prereqs ((car testdat))) - (ldb (if db db (open-db)))) - (debug:print 2 "prereqs remaining: " prereqs) - (if (null? prereqs) - (begin - (debug:print 2 "Prerequisites met, launching " testname) - ((cadr testdat)) - (hash-table-delete! *waiting-queue* testname))) - (if (not db) - (sqlite3:finalize! ldb))))) - waiting-test-names) - ;; (sleep 10) ;; no point in rushing things at this stage? - (loop (hash-table-keys *waiting-queue*))))))) Index: runs.scm ================================================================== --- runs.scm +++ runs.scm @@ -23,14 +23,10 @@ (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") (include "test_records.scm") - -;; stuff to be deprecated then removed -(include "old-runs.scm") - ;; runs:get-runs-by-patt ;; get runs by list of criteria ;; register a test run with the db ;; @@ -221,14 +217,25 @@ (if (not (hash-table-ref/default test-records hed #f)) (hash-table-set! test-records hed (vector hed ;; 0 config ;; 1 waitons ;; 2 - (config-lookup config "requirements" "priority") - #f ;; 4 - #f ;; 5 - #f ;; spare + (config-lookup config "requirements" "priority") ;; priority 3 + (let ((items (hash-table-ref/default config "items" #f)) ;; items 4 + (itemstable (hash-table-ref/default config "itemstable" #f))) + ;; if either items or items table is a proc return it so test running + ;; process can know to call items:get-items-from-config + ;; if either is a list and none is a proc go ahead and call get-items + ;; otherwise return #f - this is not an iterated test + (cond + ((procedure? items) items) ;; calc later + ((procedure? itemstable) itemstable) ;; calc later + ((or (list? items)(list? itemstable)) ;; calc now + (items:get-items-from-config config)) + (else #f))) ;; not iterated + #f ;; itemsdat 5 + ;; #f ;; spare ))) (for-each (lambda (waiton) (if (and waiton (not (member waiton test-names))) (begin @@ -246,11 +253,12 @@ (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. (debug:print 5 "test-records: " test-records ", keyvallst: " keyvallst) - (let ((sorted-test-names (tests:sort-by-priority-and-waiton test-records))) + (let ((sorted-test-names (tests:sort-by-priority-and-waiton test-records)) + (item-patts (hash-table-ref/default flags "-itempatt" #f))) (let loop (; (numtimes 0) ;; shouldn't need this (hed (car sorted-test-names)) (tal (cdr sorted-test-names))) (let* ((test-record (hash-table-ref test-records hed)) (tconfig (tests:testqueue-get-testconfig test-record)) @@ -258,18 +266,22 @@ (priority (tests:testqueue-get-priority test-record)) (itemdat (tests:testqueue-get-itemdat test-record)) (items (tests:testqueue-get-items test-record)) (item-path (item-list->path itemdat))) (debug:print 0 "WHERE TO DO: (items:get-items-from-config config)") + (debug:print 6 + "itemdat: " itemdat + "\n items: " items + "\n item-path: " item-path) (cond - ((not items) ;; when false the test is ok to be handed off to launch + ((not items) ;; when false the test is ok to be handed off to launch (but not before) (let ((have-resources (runs:can-run-more-tests db test-record)) ;; look at the test jobgroup and tot jobs running (prereqs-not-met (db:get-prereqs-not-met db run-id waitons item-path))) (if (and have-resources (null? prereqs-not-met)) ;; no loop - drop though and use the loop at the bottom - (run:test db run-id runname keyvallst test-record flags) + (run:test db run-id runname keyvallst test-record flags #f) ;; else the run is stuck, temporarily or permanently (let ((newtal (append tal (list hed)))) ;; couldn't run, take a breather (thread-sleep! 1) (loop (car tal)(cdr tal)))))) @@ -282,11 +294,13 @@ ;; (begin ;; (print "items: ") (pp (item-assoc->item-list items)) ;; (print "itemstable: ")(pp (item-table->item-list itemstable)))) (for-each (lambda (my-itemdat) - (let* ((new-test-record (vector-copy! test-record (make-tests:testqueue))) + (let* ((new-test-record (let ((newrec (make-tests:testqueue))) + (vector-copy! test-record newrec) + newrec)) (my-item-path (item-list->path my-itemdat)) (item-matches (if item-patts ;; here we are filtering for matches with -itempatt (let ((res #f)) ;; look through all the item-patts if defined, format is patt1,patt2,patt3 ... wildcard is % (for-each (lambda (patt) @@ -296,23 +310,23 @@ (set! res #t))) (string-split item-patts ",")) res) #t))) (if item-matches ;; yes, we want to process this item - (begin + (let ((newtestname (conc hed "/" my-item-path))) (tests:testqueue-set-items! new-test-record #f) (tests:testqueue-set-itemdat! new-test-record my-itemdat) - (set! tal (cons (conc hed "/" my-item-path) tal)))))) ;; since these are itemized create new test names testname/itempath + (hash-table-set! test-records newtestname new-test-record) + (set! tal (cons newtestname tal)))))) ;; since these are itemized create new test names testname/itempath items) (loop (car tal)(cdr tal))) - ;; if items is a proc then need to evaluate, get the list and loop - but only do that if - ;; resources exist to kick off the job + ;; if items is a proc then need to run items:get-items-from-config, get the list and loop + ;; - but only do that if resources exist to kick off the job ((procedure? items) (if (runs:can-run-more-tests db test-record) - (let ((items-list (items))) - + (let ((items-list (items:get-items-from-config tconfig))) (if (list? items-list) (begin (tests:testqueue-set-items test-record items-list) (loop hed tal)) (begin @@ -331,16 +345,18 @@ ;; we get here on "drop through" - loop for next test in queue (if (null? tal) (debug:print 1 "INFO: All tests launched") (loop (car tal)(cdr tal))))))) -(define (run:test db run-id runname keyvallst test-record flags) +;; 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 - (let* ((test-name (tests:testqueue-get-testname test-record)) - (test-path (conc *toppath* "/tests/" test-name)) ;; could use test:get-testconfig here ... + (let* ((test-name (tests:testqueue-get-testname test-record)) + (test-waitons (tests:testqueue-get-waitons test-record)) (test-conf (tests:testqueue-get-testconfig test-record)) (itemdat (tests:testqueue-get-itemdat test-record)) + (test-path (conc *toppath* "/tests/" test-name)) ;; could use test:get-testconfig here ... (force (hash-table-ref/default flags "-force" #f)) (rerun (hash-table-ref/default flags "-rerun" #f)) (keepgoing (hash-table-ref/default flags "-keepgoing" #f))) (debug:print 1 "Launching test " test-name) (debug:print 5 @@ -359,13 +375,15 @@ ;; (lambda (itemdat) ;;; ((ripeness "overripe") (temperature "cool") (season "summer")) (let* ((item-path (item-list->path itemdat)) ;; (string-intersperse (map cadr itemdat) "/")) (new-test-path (string-intersperse (cons test-path (map cadr itemdat)) "/")) (new-test-name (if (equal? item-path "") test-name (conc test-name "/" item-path))) ;; just need it to be unique - (testdat #f) - (test-info (db:get-test-info db run-id test-name item-path))) - (if (not test-info)(register-test db run-id test-name item-path)) + (testdat (db:get-test-info db run-id test-name item-path))) + (if (not testdat) + (begin + (register-test db run-id test-name item-path) + (set! testdat (db:get-test-info db run-id test-name item-path)))) (change-directory test-path) (case (if force ;; (args:get-arg "-force") 'NOT_STARTED (if testdat (string->symbol (test:get-state testdat)) @@ -400,28 +418,17 @@ (else (set! runflag #f))) (debug:print 6 "RUNNING => runflag: " runflag " STATE: " (test:get-state testdat) " STATUS: " (test:get-status testdat)) (if (not runflag) (if (not parent-test) (debug:print 1 "NOTE: Not starting test " new-test-name " as it is state \"COMPLETED\" and status \"" (test:get-status testdat) "\", use -force to override")) - (let* ((get-prereqs-cmd (lambda () - (db-get-prereqs-not-met db run-id waitons))) ;; check before running .... - (launch-cmd (lambda () - (launch-test db run-id runname test-conf keyvallst test-name test-path itemdat flags))) - (testrundat (list get-prereqs-cmd launch-cmd))) - (if (or force - (let ((preqs-not-yet-met ((car testrundat)))) - (debug:print 2 "Preqrequesites for " test-name ": " preqs-not-yet-met) - (null? preqs-not-yet-met))) ;; are there any tests that must be run before this one... - (if (not ((cadr testrundat))) ;; this is the line that launches the test to the remote host - (begin - (print "ERROR: Failed to launch the test. Exiting as soon as possible") - (set! *globalexitstatus* 1) ;; - (process-signal (current-process-id) signal/kill) - ;(exit 1) - )) - (if (not keepgoing) - (hash-table-set! *waiting-queue* new-test-name testrundat))))))) + ;; NOTE: No longer be checking prerequisites here! Will never get here unless prereqs are + ;; already met. + (if (not (launch-test db run-id runname test-conf keyvallst test-name test-path itemdat flags)) + (begin + (print "ERROR: Failed to launch the test. Exiting as soon as possible") + (set! *globalexitstatus* 1) ;; + (process-signal (current-process-id) signal/kill)))))) ((KILLED) (debug:print 1 "NOTE: " new-test-name " is already running or was explictly killed, use -force to launch it.")) ((LAUNCHED REMOTEHOSTSTART RUNNING) (if (> (- (current-seconds)(+ (db:test-get-event_time testdat) (db:test-get-run_duration testdat))) @@ -529,14 +536,22 @@ ;;====================================================================== ;; Since many calls to a run require pretty much the same setup ;; this wrapper is used to reduce the replication of code (define (general-run-call switchname action-desc proc) - (if (not (args:get-arg ":runname")) - (begin - (debug:print 0 "ERROR: Missing required parameter for " switchname ", you must specify the run name with :runname runname") - (exit 2)) + (let ((runname (args:get-arg ":runname")) + (target (if (args:get-arg "-target") + (args:get-arg "-target") + (args:get-arg "-reqtarg")))) + (cond + ((not target) + (debug:print 0 "ERROR: Missing required parameter for " switchname ", you must specify the target with -target") + (exit 3)) + ((not runname) + (debug:print 0 "ERROR: Missing required parameter for " switchname ", you must specify the run name with :runname runname") + (exit 3)) + (else (let ((db #f) (keys #f)) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") @@ -561,13 +576,13 @@ (exit 1)) ;; Extract out stuff needed in most or many calls ;; here then call proc (let* ((keynames (map key:get-fieldname keys)) (keyvallst (keys->vallist keys #t))) - (proc db keys keynames keyvallst))) + (proc db target runname keys keynames keyvallst))) (sqlite3:finalize! db) - (set! *didsomething* #t)))) + (set! *didsomething* #t)))))) ;;====================================================================== ;; Rollup runs ;;======================================================================