TODO
====
1. Confirm that branch transaction-for-sequential-writes content was added to trunk/development2. Add a host chooser for ssh to launch-tests3. Try making static executable
Migration to inmem db plus per run db
-------------------------------------
. Re-work the dbstruct data structure?
.. Move main.db to global?
.. [ run-id.db inmemdb last-mod last-read last-sync inuse ]
. Re-work all queries to use run-id to dereference server
. Open main.db directly in calls to -runtests etc. No need to talk remote?
;;
;; There are two scenarios.
;; 1. We are a test manager and we received *transport-type* and *runremote* via cmdline
;; 2. We are a run tests, list runs or other interactive process and we must figure out
;; *transport-type* and *runremote* from the monitor.db
;;
;; client:setup
(define (client:setup #!key (numtries 3))
(define (client:setup run-id #!key (remaining-tries 3))
(if (not *toppath*)
(if (not (setup-for-run))
(begin
(debug:print 0 "ERROR: failed to find megatest.config, exiting")
(exit))))
(push-directory *toppath*) ;; This is probably NOT needed
;; (push-directory *toppath*) ;; This is probably NOT needed
;; clients get the sdb:qry proc created here
;; (if (not sdb:qry)
;; (begin
;; (set! sdb:qry (make-sdb:qry (conc *toppath* "/db/strings.db"))) ;; we open the normalization helpers here
;; (sdb:qry 'setup #f)))
(debug:print-info 11 "*transport-type* is " *transport-type* ", *runremote* is " *runremote*)
(let* ((hostinfo (open-run-close tasks:get-best-server tasks:open-db)))
(let ((hostinfo (and run-id (hash-table-ref/default *runremote* run-id #f))))
(debug:print-info 11 "for run-id=" run-id ", *transport-type* is " *transport-type*)
(if hostinfo
hostinfo ;; have hostinfo - just return it
(let* ((hostinfo (open-run-close tasks:get-server tasks:open-db run-id))
(debug:print-info 11 "CLIENT SETUP, hostinfo=" hostinfo)
(set! *transport-type* (if hostinfo
(string->symbol (tasks:hostinfo-get-transport hostinfo))
'fs))
(debug:print-info 11 "Using transport type of " *transport-type* (if hostinfo (conc " to connect to " hostinfo) ""))
(case *transport-type*
;; ((fs)(if (not *megatest-db*)(set! *megatest-db* (open-db))))
((http)
(http-transport:client-connect (tasks:hostinfo-get-interface hostinfo) (tasks:hostinfo-get-port hostinfo)))
((zmq)
(zmq-transport:client-connect (tasks:hostinfo-get-interface hostinfo)
(tasks:hostinfo-get-port hostinfo)
(tasks:hostinfo-get-pubport hostinfo)))
(else ;; default to fs
(debug:print 0 "ERROR: unrecognised transport type " *transport-type* " exiting now.")
(exit)))
(pop-directory)))
(transport (if hostinfo
(string->symbol (tasks:hostinfo-get-transport hostinfo))
'http)))
(if (not hostinfo)
(if (> remaining-tries 0)
(begin
(server:ensure-running run-id)
(client:setup run-id remaining-tries: (- remaining-tries 1)))
(begin
(debug:print 0 "ERROR: Expected to be able to connect to a server by now. No server available for run-id = " run-id)
(exit 1)))
(begin
(hash-table-set! *runremote* run-id hostinfo)
(debug:print-info 11 "CLIENT SETUP, hostinfo=" hostinfo)
(debug:print-info 11 "Using transport type of " transport (if hostinfo (conc " to connect to " hostinfo) ""))
(case *transport-type*
;; ((fs)(if (not *megatest-db*)(set! *megatest-db* (open-db))))
((http)
;; this saves the hostinfo in the *runremote* hash and returns it
(http-transport:client-connect run-id
(tasks:hostinfo-get-interface hostinfo)
(tasks:hostinfo-get-port hostinfo)))
((zmq)
(zmq-transport:client-connect (tasks:hostinfo-get-interface hostinfo)
(tasks:hostinfo-get-port hostinfo)
(tasks:hostinfo-get-pubport hostinfo)))
(else ;; default to fs
(debug:print 0 "ERROR: unrecognised transport type " *transport-type* " exiting now.")
(exit)))))))))
;; (pop-directory)))
;; client:signal-handler
(define (client:signal-handler signum)
(handle-exceptions
exn
(debug:print " ... exiting ...")
(let ((th1 (make-thread (lambda ()
"") ;; do nothing for now (was flush out last call if applicable)
"eat response"))
(th2 (make-thread (lambda ()
(debug:print 0 "ERROR: Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
(thread-sleep! 1) ;; give the flush one second to do it's stuff
(debug:print 0 " Done.")
(exit 4))
"exit on ^C timer")))
(thread-start! th2)
(thread-start! th1)
(thread-join! th2))))
;; client:launch
;; Need to set the signal handler somewhere other than here as this
;; routine will go away.
;;
(define (client:launch)
(define (client:launch run-id)
(set-signal-handler! signal/int client:signal-handler)
(if (client:setup)
(debug:print-info 2 "connected as client")
(begin
(debug:print 0 "ERROR: Failed to connect as client")
(exit))))
(if (client:setup run-id)
(debug:print-info 2 "connected as client")
(begin
(debug:print 0 "ERROR: Failed to connect as client")
(exit))))
(define *passnum* 0) ;; when running track calls to run-tests or similar
;; DATABASE
(define *open-dbs* (vector #f (make-hash-table))) ;; megatestdb run-id-dbs
;; SERVER
(define *my-client-signature* #f)
(define *transport-type* 'fs)
(define *transport-type* 'http)
(define *megatest-db* #f)
(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 <host port>
(define *runremote* (make-hash-table)) ;; if set up for server communication this will hold <host port>
(define *last-db-access* (current-seconds)) ;; update when db is accessed via server
(define *max-cache-size* 0)
(define *logged-in-clients* (make-hash-table))
(define *client-non-blocking-mode* #f)
(define *server-id* #f)
(define *server-info* #f)
(define *time-to-exit* #f)
(define *received-response* #f)
(define *default-numtries* 10)
(define *server-run* #t)
(define *db-write-access* #t)
(define *inmemdb* #f)
(define *run-id* #f)
(define *target* (make-hash-table)) ;; cache the target here; target is keyval1/keyval2/.../keyvalN
(define *keys* (make-hash-table)) ;; cache the keys here
(define *keyvals* (make-hash-table))
(define *toptest-paths* (make-hash-table)) ;; cache toptest path settings here
(define *test-paths* (make-hash-table)) ;; cache test-id to test run paths here
(define *test-ids* (make-hash-table)) ;; cache run-id, testname, and item-path => test-id
(if (not testdat)
(begin
(debug:print 2 "ERROR: No test data found for test " test-id ", exiting")
(exit 1))
(let* (;; (run-id (if testdat (db:test-get-run_id testdat) #f))
(keydat (if testdat (db:get-key-val-pairs dbstruct run-id) #f))
(rundat (if testdat (db:get-run-info dbstruct run-id) #f))
(runname (if testdat (db:get-value-by-header (db:get-row rundat)
(runname (if testdat (db:get-value-by-header (db:get-rows rundat)
(db:get-header rundat)
"runname") #f))
(tdb (tdb:open-test-db-by-test-id-local dbstruct run-id test-id))
;; These next two are intentional bad values to ensure errors if they should not
;; get filled in properly.
(logfile "/this/dir/better/not/exist")
(rundir logfile)
(include "db_records.scm")
(include "run_records.scm")
(include "megatest-fossil-hash.scm")
(define help (conc
"Megatest Dashboard, documentation at http://www.kiatoa.com/fossils/megatest
version " megatest-version "
license GPL, Copyright (C) Matt Welland 2013 license GPL, Copyright (C) Matt Welland 2012-2014
Usage: dashboard [options]
-h : this help
-server host:port : connect to host:port instead of db access
-test run-id,test-id : control test identified by testid
-guimonitor : control panel for runs
(if (not dbexists)
(db:initialize-main-db db))
(dbr:dbstruct-set-main! dbstruct db)
db))))
;; Make the dbstruct, setup up auxillary db's and call for main db at least once
;;
(define (db:setup #!key (local #f))
(define (db:setup run-id #!key (local #f))
(let ((dbstruct (make-dbr:dbstruct path: *toppath* local: local)))
(db:get-db dbstruct #f) ;; force one call to main
;; (if (not sdb:qry) ;; (begin ;; (set! sdb:qry (make-sdb:qry (conc *toppath* "/db/strings.db"))) ;; we open the normalization helpers here ;; (sdb:qry 'setup #f) ;; ;; Initialize with some known needed strings, NOTE: set this up to only execute on first db initialization ;; (for-each ;; (lambda (str) ;; (sdb:qry 'get-id str)) ;; (list "" "logs/final.log")))) ;; (set! *fdb* (filedb:open-db (conc *toppath* "/db/paths.db"))) dbstruct))
;; Open the classic megatest.db file in toppath
;;
(define (db:open-megatest-db)
(let* ((dbpath (conc *toppath* "/megatest.db"))
(dbexists (file-exists? dbpath))
(conc fieldname " " wildtype " '" patt "'")))
(if (null? patts)
'("")
patts))
comparator)))
;; register a test run with the db
;; register a test run with the db, this accesses the main.db and does NOT
;; use server api
;;
(define (db:register-run dbstruct keyvals runname state status user)
(debug:print 3 "runs:register-run runname: " runname " state: " state " status: " status " user: " user) (let* ((db (db:get-db dbstruct #f))
(keys (map car keyvals))
(keystr (keys->keystr keys))
(comma (if (> (length keys) 0) "," ""))
(andstr (if (> (length keys) 0) " AND " ""))
(valslots (keys->valslots keys)) ;; ?,?,? ...
(allvals (append (list runname state status user) (map cadr keyvals)))
runs-info)
res))
;; db:get-runs-by-patt
;; get runs by list of criteria
;; register a test run with the db
;;
;; Use: (db-get-value-by-header (db:get-header runinfo)(db:get-row runinfo))
;; Use: (db:get-value-by-header (db:get-header runinfo)(db:get-rows runinfo))
;; to extract info from the structure returned
;;
(define (db:get-runs-by-patt dbstruct keys runnamepatt targpatt offset limit) ;; test-name)
(let* ((tmp (runs:get-std-run-fields keys '("id" "runname" "state" "status" "owner" "event_time")))
(keystr (car tmp))
(header (cadr tmp))
(res '())
((and newstate newstatus)
(sqlite3:execute db "UPDATE tests SET state=?,status=? WHERE id=?;" newstate newstatus test-id))
(else
(if newstate (sqlite3:execute db "UPDATE tests SET state=? WHERE id=?;" newstate test-id))
(if newstatus (sqlite3:execute db "UPDATE tests SET status=? WHERE id=?;" newstatus test-id))
(if newcomment (sqlite3:execute db "UPDATE tests SET comment=? WHERE id=?;" newcomment ;; (sdb:qry 'getid newcomment)
test-id))))
(mt:process-triggers test-id newstate newstatus)))
(mt:process-triggers run-id test-id newstate newstatus)))
;; Never used, but should be?
(define (db:test-set-state-status-by-run-id-testname db run-id test-name item-path status state)
(sqlite3:execute db "UPDATE tests SET state=?,status=?,event_time=strftime('%s','now') WHERE run_id=? AND testname=? AND item_path=?;"
state status run-id test-name item-path))
;; NEW BEHAVIOR: Count tests running in only one run!
;;
(define (db:get-count-tests-running dbstruct run-id)
(let ((res 0))
(sqlite3:for-each-row
(lambda (count)
(set! res count))
(db:get-db dbstruct run-id)
"SELECT count(id) FROM tests WHERE state in ('RUNNING','LAUNCHED','REMOTEHOSTSTART');") "SELECT count(id) FROM tests WHERE state in ('RUNNING','LAUNCHED','REMOTEHOSTSTART') AND run_id=?;"
run-id) ;; NOT IN (SELECT id FROM runs WHERE state='deleted');")
res))
;; NEW BEHAVIOR: Look only at single run with run-id
;;
;; (define (db:get-running-stats dbstruct run-id)
(define (db:get-count-tests-running-for-run-id dbstruct run-id)
(let ((res 0))
(sqlite3:for-each-row
(lambda (count)
(set! res count))
(db:get-db dbstruct run-id)
"SELECT count(id) FROM tests WHERE state in ('RUNNING','LAUNCHED','REMOTEHOSTSTART') AND run_id=?;" run-id)
res))
(define (db:get-count-tests-running-in-jobgroup dbstruct run-id jobgroup)
(if (not jobgroup)
0 ;;
(let ((res 0))
(let ((res 0)
(testnames '()))
;; get the testnames
(sqlite3:for-each-row
(lambda (testname)
(set! testnames (cons testname testnames)))
(db:get-db dbstruct #f)
"SELECT testname FROM test_meta WHERE jobgroup=?"
jobgroup)
;; get the jobcount NB// EXTEND THIS TO OPPERATE OVER ALL RUNS?
(if (not (null? testnames))
(sqlite3:for-each-row
(lambda (count)
(set! res count))
(db:get-db dbstruct run-id)
"SELECT count(id) FROM tests WHERE state = 'RUNNING' OR state = 'LAUNCHED' OR state = 'REMOTEHOSTSTART'
AND testname in (SELECT testname FROM test_meta WHERE jobgroup=?);"jobgroup)
(lambda (count)
(set! res count))
(db:get-db dbstruct run-id)
(conc "SELECT count(id) FROM tests WHERE state in ('RUNNING','LAUNCHED','REMOTEHOSTSTART') AND testname in ('"
(string-intersperse testnames "','")
"');")))
res)))
;; done with run when:
;; 0 tests in LAUNCHED, NOT_STARTED, REMOTEHOSTSTART, RUNNING
(define (db:estimated-tests-remaining dbstruct run-id)
(let ((res 0))
(sqlite3:for-each-row
;; Tests meta data
;;======================================================================
;; read the record given a testname
(define (db:testmeta-get-record dbstruct 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)))
(lambda (id testname author owner description reviewed iterated avg_runtime avg_disk tags jobgroup)
(set! res (vector id testname author owner description reviewed iterated avg_runtime avg_disk tags jobgroup)))
(db:get-db dbstruct #f)
"SELECT id,testname,author,owner,description,reviewed,iterated,avg_runtime,avg_disk,tags FROM test_meta WHERE testname=?;"
"SELECT id,testname,author,owner,description,reviewed,iterated,avg_runtime,avg_disk,tags,jobgroup FROM test_meta WHERE testname=?;"
testname)
res))
;; create a new record for a given testname
(define (db:testmeta-add-record dbstruct testname)
(sqlite3:execute (db:get-db dbstruct #f) "INSERT OR IGNORE INTO test_meta (testname,author,owner,description,reviewed,iterated,avg_runtime,avg_disk,tags) VALUES (?,'','','','','','','','');" testname))
<h2 class="Subsection">
<a class="toc" name="toc-Subsection-13.1">13.1</a> Monitor logic
</h2>
<div class="Standard">
Note: The monitor is usable but incomplete as of Megatest v1.31. Click on the “Monitor” button on the dashboard to start the monitor and give it a try.
</div>
<div class="Standard">
<img class="embedded" src="monitor-state-diagram.png" alt="figure monitor-state-diagram.png" style="max-width: 383px; max-height: 335px;"/>
<img class="embedded" src="monitor-state-diagram.png" alt="figure monitor-state-diagram.png" style="max-width: 531px; max-height: 465px;"/>
</div>
<h1 class="Section">
<a class="toc" name="toc-Section-14">14</a> Reference
</h1>
<h2 class="Subsection">
<a class="toc" name="toc-Subsection-14.1">14.1</a> Configuration file Syntax
~~~~~~~~~~~~~~~~~~~~~~~~~
During Config File Processing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Organising Your Tests and Tasks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/nfs/ch/disks/ch_unienv_disk005/qa_mrwellan/interim/src/megatest/tests/fdktestqa/testqa
----------------------------
[tests-paths]
1 #{get misc parent}/simplerun/tests
----------------------------
-------------------
[setup]
-------------------
The runscript method is a brute force way to run scripts where the
user is responsible for setting STATE and STATUS
-------------------
runscript main.csh
-------------------
ww30.2cellname/LVS/cellname.LAYOUT_ERRORSError: text openww31.3cellname/LVS/cellname.LAYOUT_ERRORSError: text open
which can launch jobs on local and remote Linux hosts. Currently
megatest uses the network filesystem to call home to your master
sqlite3 database.</p></div>
</div>
</div>
</div>
<h1 id="_road_map">Road Map</h1>
<div class="paragraph"><p>Note: This road-map is tentative and subject to change without notice.</p></div>
<div class="paragraph"><p>Note 1: This road-map is tentative and subject to change without notice.</p></div>
<div class="paragraph"><p>Note 2: Starting over. Old plan is commented out.</p></div>
<div class="sect1">
<h2 id="_current_items">Current Items</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_ww32">ww32</h3>
<h3 id="_ww05_migrate_to_inmem_db">ww05 - migrate to inmem-db</h3>
<div class="paragraph"><p>Keep as much the same as possible. Add internal reference to almost
eliminate contention on db(s).</p></div>
<div class="olist arabic"><ol class="arabic">
<li>
<p>
Rerun step and or subsequent steps from gui</p></li><li><p>Refresh test area files from gui</p></li><li><p>Clean and re-run button</p></li><li><p>Clean up STATE and STATUS handling.</p><div class="olist loweralpha"><ol class="loweralpha"><li><p>Dashboard and Test control panel are reverse order - choose and fix</p></li><li><p>Move seldom used states and status to drop down selector</p></li></ol></div></li><li><p>Access test control panel when clicking on Run Summary testsAdd internal reference db
</p>
</li>
<li>
<p>
Feature:-generate-index-treeVerify that actions are accessing correct db
</p></li><li><p>Change specifing of state and status to use STATE1/STATUS1,STATE2/STATUS2</p></li></ol></div></div><div class="sect2"><h3 id="_ww33">ww33</h3><div class="olist arabic"><ol class="arabic"><li><p>http api available for use with Perl, Ruby etc. scripts</p></li><li><p>megatest.config setup entries for:</p><div class="olist loweralpha"><ol class="loweralpha"><li><p>run launching (e.g. /bin/sh %CMD% > /dev/null)</p></li><li><p>browser "konqueror %FNAME%</p></li></ol></div></li></ol></div></div><div class="sect2"><h3 id="_ww34">ww34</h3><div class="olist arabic"><ol class="arabic"><li><p>Mark dependent tests for clean/rerun -rerun-downstream</p>
</li><li><p>On run start check for defunct tests in RUNNING, LAUNCHED or REMOTEHOSTSTART and correct or notify</p></li><li><p>Fix: refresh of gui sometimes fails on last item (race condition?)</p></li></ol></div></div>
<div class="sect2">
<div class="olist loweralpha"><ol class="loweralpha">
<h3 id="_ww35">ww35</h3><div class="olist arabic"><ol class="arabic"><li>
<p>
refdb: Add export of csv, json and sexp</p></li><li><p>Convert to using call-with-environment-variables where possible. Should allow handling of parallel runs in same process.</p></li><li><p>Re-work text interface wizards. Several bugs on record. Possibly convert to gui based.</p></li><li><p>Add to testconfig requirements section; launchlimiter scriptname, calls scriptname to check if ok to launch test</p></li><li><p>Refactor Run Summary view, currently very clumsy</p></li><li><p>Add option to show steps in Run Summary view</p></li></ol></div></div><div class="sect2"><h3 id="_ww36">ww36</h3>-runtests - inmem
<div class="olist arabic"><ol class="arabic"><li><p>Refactor guis for resizeablity</p>
</li>
<li>
<p>
Add filters to Run Summary view and Run Control view</p></li><li><p>Addto megatest.config or testconfig; rerunok STATE/STATUS,STATE/STATUS…-list-runs - local (but not megatest.db)
</p>
</li>
<li>
<p>
Launch gates for diskspace; /path/one>1G,/path/two>200M,/tmp>5G,#{scheme <strong>toppath</strong>}>1Gdashboard - local (but not megatest.db)
</p></li></ol></div></div><div class="sect2"><h3 id="_bin_list">Bin List</h3><div class="olist arabic"><ol class="arabic"><li><p>Quality improvements</p><div class="olist loweralpha"><ol class="loweralpha"><li><p>Server stutters occasionally</p></li><li><p>Large number of items or tests still has some issues.</p></li><li><p>Code refactoring</p></li><li><p>Replace remote process with true API using json (supports Web app also)</p>
</li>
</ol></div>
</li>
<li>
<p>
Streamline the gui</p><div class="olist loweralpha"><ol class="loweralpha"><li><p>Everything resizable</p></li><li><p>Less clutter</p></li><li><p>Tool tipsMirror db to /var/tmp…
</p>
</li>
<li>
<p>
Filters on Run Summary, Summary and Run Control panelDashboard read db from per-run db.
</p>
</li>
<li>
<p>
Built in log viewer (partially implemented)</p></li><li><p>Refactor the test control panel</p></li></ol></div></li><li><p>Help and documentationDashboard read db from /var/tmp
</p>
<div class="olist loweralpha"><ol class="loweralpha"><li><p>Complete the user manual (I’ve been working on this lately).</p></li>
<li>
<p>
Online help in the guiRuns register in tasks table in monitor.db
</p>
</li>
</ol></div></li><li>
<p>
Streamlined install</p><div class="olist loweralpha"><ol class="loweralpha"><li><p>Deployed version (download a location independent ready to run binary bundle)</p></li><li><p>Install Makefile (in progress, needed for Mike to install on VMs)</p></li><li><p>Added option to compile IUP (needed for VMs)</p></li></ol></div></li><li><p>Server side run launching</p></li><li><p>
Support for re-running, cleaning etc. of individual steps (ezsteps makes this very easy to implement).Server polls tasks table for next action (in addition?)
</p>
</li>
<li>
<p>
Launch process needs built in daemonizing (easy to do, just need to test it thoroughly).Change run loop to execute in server, triggered by call to polling of tasks table
</p>
</li>
<li><p>Wizards for creating tests, regression areas (current ones are text only and limited).
</p>
</li>
</ol></div>
</div>
<li><p>Fully functional built in web service (currently you can browse runs but it is very simplistic).</p></li><li><p>Wildcards in runconfigs: e.g. [p1271/9/%/%]</p></li><li><p>Gui panels for editing megatest.config and runconfigs.config</p></li><li><p>Fully isolated tests (no use of NFS to see regression area files)</p></li><li><p>Windows version</p></li></ol></div>
</div>
</div>
<h1 id="_getting_started">Getting Started</h1>
<div class="openblock">
<div class="title">Getting started with Megatest</div>
<div class="content">
<div class="paragraph"><p>How to install Megatest and set it up for running your regressions and continuous integration process.</p></div>
</div></div>
</div>
<h1 id="_writing_tests">Writing Tests</h1>
<div class="sect1">
<h2 id="_the_first_chapter_of_the_second_part">The First Chapter of the Second Part</h2>
<div class="sectionbody">
<div class="paragraph"><p>Chapters grouped into book parts are at level 1 and can contain
sub-sections.</p></div>
</div>
</div>
<h1 id="_how_to_do_things">How To Do Things</h1>
<div class="sect1">
<h2 id="_tricks">Tricks</h2>
<div class="sectionbody">
<div class="paragraph"><p>This section is a compendium of a various useful tricks for debugging,
configuring and generally getting the most out of Megatest.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_debugging_tricks">Debugging Tricks</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_examining_the_environment">Examining The Environment</h3>
<div class="sect3">
<h4 id="_during_config_file_processing">During Config File Processing</h4>
</div>
<div class="sect3">
<h4 id="_organising_your_tests_and_tasks">Organising Your Tests and Tasks</h4>
<div class="listingblock">
<div class="content">
<pre><tt>[tests-paths]
1 #{get misc parent}/simplerun/tests</tt></pre>
</div></div>
<div class="listingblock">
<div class="content">
<pre><tt>[setup]</tt></pre>
</div></div>
<div class="paragraph"><p>The runscript method is a brute force way to run scripts where the
user is responsible for setting STATE and STATUS</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>runscript main.csh</tt></pre>
</div></div>
</div>
</div>
</div>
</div>
<h1 id="_reference">Reference</h1>
<div class="sect1">
<h2 id="_the_first_chapter_of_the_second_part_2">The First Chapter of the Second Part</h2>
<div class="sectionbody">
<div class="paragraph"><p>Chapters grouped into book parts are at level 1 and can contain
<h3 id="_ezsteps">Ezsteps</h3>
<div class="paragraph"><p>To transfer the environment to the next step you can do the following:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>$MT_MEGATEST -env2file .ezsteps/${stepname}</tt></pre>
</div></div>
</div>
<div class="sect2">
<h3 id="_megatest_internals">Megatest Internals</h3>
<div class="imageblock graphviz">
<div class="content">
<img src="server.png" alt="server.png" />
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_example_appendix">Appendix A: Example Appendix</h2>
<div class="sectionbody">
<div class="paragraph"><p>One or more optional appendixes go here at section level zero.</p></div>
<div class="sect2">
sqlite3 database.
include::../plan.txt[]
include::getting_started.txt[]
include::writing_tests.txt[]
include::howto.txt[]
include::reference.txt[]
Megatest Internals
~~~~~~~~~~~~~~~~~~
["graphviz", "server.png"]
----------------------------------------------------------------------
include::server.dot[]
----------------------------------------------------------------------
[appendix]
Example Appendix
================
One or more optional appendixes go here at section level zero.
Appendix Sub-section
Reference
=========
The First Chapter of the Second Part
------------------------------------
Chapters grouped into book parts are at level 1 and can contain
sub-sections.
The testconfig File
-------------------
Setup section
Road Map
========
Note: This road-map is tentative and subject to change without notice.
Note 1: This road-map is tentative and subject to change without notice.
Note 2: Starting over. Old plan is commented out.
ww32~~~~
Current Items
-------------
ww05 - migrate to inmem-db
~~~~~~~~~~~~~~~~~~~~~~~~~~
Keep as much the same as possible. Add internal reference to almost
eliminate contention on db(s).
. Rerun step and or subsequent steps from gui
. Refresh test area files from gui
. Clean and re-run button
. Add internal reference db
. Verify that actions are accessing correct db
.. -runtests - inmem
.. -list-runs - local (but not megatest.db)
.. dashboard - local (but not megatest.db)
. Mirror db to /var/tmp...
. Dashboard read db from per-run db.
. Clean up STATE and STATUS handling.
.. Dashboard and Test control panel are reverse order - choose and fix.. Move seldom used states and status to drop down selector. Dashboard read db from /var/tmp
. Runs register in tasks table in monitor.db
. Server polls tasks table for next action (in addition?)
. Change run loop to execute in server, triggered by call to polling of tasks table
. Access test control panel when clicking on Run Summary tests. Feature: -generate-index-tree. Change specifing of state and status to use STATE1/STATUS1,STATE2/STATUS2
// ww32
// ~~~~
//
// . Rerun step and or subsequent steps from gui
// . Refresh test area files from gui
// . Clean and re-run button
// . Clean up STATE and STATUS handling.
// .. Dashboard and Test control panel are reverse order - choose and fix
// .. Move seldom used states and status to drop down selector
// . Access test control panel when clicking on Run Summary tests
// . Feature: -generate-index-tree
// . Change specifing of state and status to use STATE1/STATUS1,STATE2/STATUS2
//
ww33
~~~~
. http api available for use with Perl, Ruby etc. scripts
. megatest.config setup entries for:
.. run launching (e.g. /bin/sh %CMD% > /dev/null)
.. browser "konqueror %FNAME%
ww34
~~~~
. Mark dependent tests for clean/rerun -rerun-downstream
. On run start check for defunct tests in RUNNING, LAUNCHED or REMOTEHOSTSTART and correct or notify
. Fix: refresh of gui sometimes fails on last item (race condition?)
ww35
~~~~
. refdb: Add export of csv, json and sexp
. Convert to using call-with-environment-variables where possible. Should allow handling of parallel runs in same process.
. Re-work text interface wizards. Several bugs on record. Possibly convert to gui based.
. Add to testconfig requirements section; launchlimiter scriptname, calls scriptname to check if ok to launch test
. Refactor Run Summary view, currently very clumsy
. Add option to show steps in Run Summary view
ww36
~~~~
. Refactor guis for resizeablity
. Add filters to Run Summary view and Run Control view
. Add to megatest.config or testconfig; rerunok STATE/STATUS,STATE/STATUS...
. Launch gates for diskspace; /path/one>1G,/path/two>200M,/tmp>5G,#{scheme *toppath*}>1G
Bin List
~~~~~~~~
. Quality improvements
.. Server stutters occasionally
.. Large number of items or tests still has some issues.
.. Code refactoring
.. Replace remote process with true API using json (supports Web app also)
. Streamline the gui
.. Everything resizable
.. Less clutter
.. Tool tips
.. Filters on Run Summary, Summary and Run Control panel
.. Built in log viewer (partially implemented)
.. Refactor the test control panel
. Help and documentation
.. Complete the user manual (I’ve been working on this lately).
.. Online help in the gui
. Streamlined install
.. Deployed version (download a location independent ready to run binary bundle)
.. Install Makefile (in progress, needed for Mike to install on VMs)
.. Added option to compile IUP (needed for VMs)
. Server side run launching
. Support for re-running, cleaning etc. of individual steps (ezsteps makes this very easy to implement).
. Launch process needs built in daemonizing (easy to do, just need to test it thoroughly).
. Wizards for creating tests, regression areas (current ones are text only and limited).
. Fully functional built in web service (currently you can browse runs but it is very simplistic).
. Wildcards in runconfigs: e.g. [p1271/9/%/%]
. Gui panels for editing megatest.config and runconfigs.config
. Fully isolated tests (no use of NFS to see regression area files)
. Windows version
// ww33
// ~~~~
//
// . http api available for use with Perl, Ruby etc. scripts
// . megatest.config setup entries for:
// .. run launching (e.g. /bin/sh %CMD% > /dev/null)
// .. browser "konqueror %FNAME%
//
// ww34
// ~~~~
//
// . Mark dependent tests for clean/rerun -rerun-downstream
// . On run start check for defunct tests in RUNNING, LAUNCHED or REMOTEHOSTSTART and correct or notify
// . Fix: refresh of gui sometimes fails on last item (race condition?)
//
// ww35
// ~~~~
//
// . refdb: Add export of csv, json and sexp
// . Convert to using call-with-environment-variables where possible. Should allow handling of parallel runs in same process.
// . Re-work text interface wizards. Several bugs on record. Possibly convert to gui based.
// . Add to testconfig requirements section; launchlimiter scriptname, calls scriptname to check if ok to launch test
// . Refactor Run Summary view, currently very clumsy
// . Add option to show steps in Run Summary view
//
// ww36
// ~~~~
//
// . Refactor guis for resizeablity
// . Add filters to Run Summary view and Run Control view
// . Add to megatest.config or testconfig; rerunok STATE/STATUS,STATE/STATUS...
// . Launch gates for diskspace; /path/one>1G,/path/two>200M,/tmp>5G,#{scheme *toppath*}>1G
//
// Bin List
// ~~~~~~~~
//
// . Quality improvements
// .. Server stutters occasionally
// .. Large number of items or tests still has some issues.
// .. Code refactoring
// .. Replace remote process with true API using json (supports Web app also)
// . Streamline the gui
// .. Everything resizable
// .. Less clutter
// .. Tool tips
// .. Filters on Run Summary, Summary and Run Control panel
// .. Built in log viewer (partially implemented)
// .. Refactor the test control panel
// . Help and documentation
// .. Complete the user manual (I’ve been working on this lately).
// .. Online help in the gui
// . Streamlined install
// .. Deployed version (download a location independent ready to run binary bundle)
// .. Install Makefile (in progress, needed for Mike to install on VMs)
// .. Added option to compile IUP (needed for VMs)
// . Server side run launching
// . Support for re-running, cleaning etc. of individual steps (ezsteps makes this very easy to implement).
// . Launch process needs built in daemonizing (easy to do, just need to test it thoroughly).
// . Wizards for creating tests, regression areas (current ones are text only and limited).
// . Fully functional built in web service (currently you can browse runs but it is very simplistic).
// . Wildcards in runconfigs: e.g. [p1271/9/%/%]
// . Gui panels for editing megatest.config and runconfigs.config
// . Fully isolated tests (no use of NFS to see regression area files)
// . Windows version
;;
;; All log file links should be stored relative to the top of link path
;;
;; <target> - <testname> [ - <itempath> ]
;;
(define (create-work-area run-id run-info keyvals test-id test-src-path disk-path testname itemdat)
(let* ((item-path (item-list->path itemdat))
(runname (db:get-value-by-header (db:get-row run-info)
(runname (db:get-value-by-header (db:get-rows run-info)
(db:get-header run-info)
"runname"))
;; convert back to db: from rdb: - this is always run at server end
(target (string-intersperse (map cadr keyvals) "/"))
(not-iterated (equal? "" item-path))
(declare (uses daemon))
(declare (uses db))
;; (declare (uses sdb))
;; (declare (uses filedb))
(declare (uses tdb))
(declare (uses mt))
(declare (uses api))
(declare (uses tasks)) ;; only used for debugging.
(define *db* #f) ;; this is only for the repl, do not use in general!!!!
(include "common_records.scm")
(include "key_records.scm")
(include "db_records.scm")
(include "run_records.scm")
transport-from-cmdinfo
transport-from-config
"fs"))))
(debug:print 2 "chosen-transport: " chosen-transport " have; config=" transport-from-config ", cmdln=" transport-from-cmdln ", cmdinfo=" transport-from-cmdinfo)
(case chosen-transport
((http)
(set! *transport-type 'http)
;; if we have a run-id (why would we?) start the server for that run.
;; otherwise it is up to other calls to start the server(s) dynamically
(if run-id
(begin
(server:ensure-running)
;; Get rid of this (client:launch))
(server:ensure-running run-id)
(client:launch run-id))
(begin
;; without run-id we'll start a server for "0"
(server:ensure-running 0)
(client:launch 0))))
(else ;; (fs)
(debug:print 0 "ERROR: Should NOT be getting here! fs transport is no longer supported")
(set! *transport-type* 'fs)
(set! *megatest-db* (make-dbr:dbstruct path: *toppath* local: #t))))))))))
(if (or (args:get-arg "-list-servers")
(args:get-arg "-stop-server"))
;; - if cannot access db > allowed disconnect time then kill job
(if (args:get-arg "-runtests")
(general-run-call
"-runtests"
"run a test"
(lambda (target runname keys keyvals)
;;
;; May or may not implement it this way ...
;;
;; Insert this run into the tasks queue
;; (open-run-close tasks:add tasks:open-db
;; "runtests"
;; user
;; target
;; runname
;; (args:get-arg "-runtests")
;; #f))))
(runs:run-tests target
runname
(args:get-arg "-runtests")
user
args:arg-hash))))
;;======================================================================
;; R U N S
;;======================================================================
;; runs:get-runs-by-patt
;; get runs by list of criteria
;; register a test run with the db
;;
;; Use: (db-get-value-by-header (db:get-header runinfo)(db:get-row runinfo))
;; Use: (db-get-value-by-header (db:get-header runinfo)(db:get-rows runinfo))
;; to extract info from the structure returned
;;
(define (mt:get-runs-by-patt keys runnamepatt targpatt)
(let loop ((runsdat (rmt:get-runs-by-patt keys runnamepatt targpatt 0 500))
(res '())
(offset 0)
(limit 500))
;;======================================================================
;; S U P P O R T F U N C T I O N S
;;======================================================================
;; cmd is a symbol
;; vars is a json string encoding the parameters for the call
;;
(define (rmt:send-receive cmd params)
(define (rmt:send-receive cmd run-id params)
(case *transport-type*
((fs-aint-here)
(debug:print 0 "ERROR: Not yet (re)supported")
(exit 1))
((fs http)
;; if run-id is #f send the request to run-id = 0 server. This will be for main.db
;;
(let* ((connection-info (client:setup (if run-id run-id 0)))
(let* ((jparams (db:obj->string params)) ;; (rmt:dat->json-str params))
(res (http-transport:client-api-send-receive *runremote* cmd jparams)))
(jparams (db:obj->string params)) ;; (rmt:dat->json-str params))
(res (http-transport:client-api-send-receive run-id connection-info cmd jparams)))
(if res
(db:string->obj res) ;; (rmt:json-str->dat res)
(begin
(debug:print 0 "ERROR: Bad value from http-transport:client-api-send-receive " res)
#f))
#f))))
)) (else
(debug:print 0 "ERROR: Transport " *transport-type* " not yet (re)supported")
(exit 1))))
;; Wrap json library for strings (why the ports crap in the first place?)
(define (rmt:dat->json-str dat)
(with-output-to-string
(define (runs:can-run-more-tests run-id jobgroup max-concurrent-jobs)
(thread-sleep! (cond
((> *runs:can-run-more-tests-count* 20) 2);; obviously haven't had any work to do for a while
(else 0)))
(let* ((num-running (rmt:get-count-tests-running run-id))
(num-running-in-jobgroup (rmt:get-count-tests-running-in-jobgroup run-id jobgroup))
(job-group-limit (config-lookup *configdat* "jobgroups" jobgroup)))
(job-group-limit (let ((jobg-count (config-lookup *configdat* "jobgroups" jobgroup)))
(if (string? jobg-count)
(string->number jobg-count)
jobg-count))))
(if (> (+ num-running num-running-in-jobgroup) 0)
(set! *runs:can-run-more-tests-count* (+ *runs:can-run-more-tests-count* 1)))
(if (not (eq? *last-num-running-tests* num-running))
(begin
(debug:print 2 "max-concurrent-jobs: " max-concurrent-jobs ", num-running: " num-running)
(set! *last-num-running-tests* num-running)))
(if (not (eq? 0 *globalexitstatus*))
(list #f num-running num-running-in-jobgroup max-concurrent-jobs job-group-limit)
(let ((can-not-run-more (cond
;; if max-concurrent-jobs is set and the number running is greater
;; than it than cannot run more jobs
((and max-concurrent-jobs (>= num-running max-concurrent-jobs))
(if (runs:lownoise "mcj msg" 60)
(debug:print 0 "WARNING: Max running jobs exceeded, current number running: " num-running
", max_concurrent_jobs: " max-concurrent-jobs))
#t)
;; if job-group-limit is set and number of jobs in the group is greater
;; than the limit then cannot run more jobs of this kind
((and job-group-limit
(>= num-running-in-jobgroup job-group-limit))
(if (runs:lownoise (conc "maxjobgroup " jobgroup) 60)
(debug:print 1 "WARNING: number of jobs " num-running-in-jobgroup
" in " jobgroup " exceeded, will not run " (tests:testqueue-get-testname test-record))
(debug:print 1 "WARNING: number of jobs " num-running-in-jobgroup
" in jobgroup \"" jobgroup "\" exceeds limit of " job-group-limit))
#t)
(else #f))))
(list (not can-not-run-more) num-running num-running-in-jobgroup max-concurrent-jobs job-group-limit)))))
;; test-names: Comma separated patterns same as test-patts but used in selection
;; of tests to run. The item portions are not respected.
;; FIXME: error out if /patt specified
;;
(define (runs:run-tests target runname test-patts user flags) ;; test-names
(common:clear-caches) ;; clear all caches (let* ((keys (keys:config-get-fields *configdat*))
(keyvals (keys:target->keyval keys target))
(run-id (rmt:register-run keyvals runname "new" "n/a" user)) ;; test-name)))
(deferred '()) ;; delay running these since they have a waiton clause
(runconfigf (conc *toppath* "/runconfigs.config"))
(required-tests '())
(test-records (make-hash-table))
;; Copyright 2006-2012, Matthew Welland.
;;
;; This program is made available under the GNU GPL version 2.0 or
;; greater. See the accompanying file COPYING for details.
;;
;; This program is distributed WITHOUT ANY WARRANTY; without even the
;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;; PURPOSE.
(require-extension (srfi 18) extras tcp s11n)
(use srfi-1 posix regex regex-case srfi-69 hostinfo md5 message-digest)
(use srfi-1 posix regex regex-case srfi-69 hostinfo md5 message-digest directory-utils)
;; (use zmq)
(use spiffy uri-common intarweb http-client spiffy-request-vars)
(declare (unit server))
(declare (uses common))
;; S E R V E R
;;======================================================================
;; Call this to start the actual server
;;
;; all routes though here end in exit ...
(define (server:launch transport)
(define (server:launch transport run-id)
(if (not *toppath*)
(if (not (setup-for-run))
(begin
(debug:print 0 "ERROR: cannot find megatest.config, exiting")
(exit))))
(debug:print-info 2 "Starting server using " transport " transport")
(set! *transport-type* transport)
(case transport
;; ((fs) (exit)) ;; there is no "fs" server transport
((fs http) (http-transport:launch))
((zmq) (zmq-transport:launch))
((fs http) (http-transport:launch run-id))
((zmq) (zmq-transport:launch run-id))
(else
(debug:print "WARNING: unrecognised transport " transport)
(exit))))
;;======================================================================
;; Q U E U E M A N A G E M E N T
;;======================================================================
(begin
(sqlite3:execute mdb "CREATE TABLE IF NOT EXISTS tasks_queue (id INTEGER PRIMARY KEY,
action TEXT DEFAULT '',
owner TEXT,
state TEXT DEFAULT 'new',
target TEXT DEFAULT '',
name TEXT DEFAULT '',
test TEXT DEFAULT '',
testpatt TEXT DEFAULT '',
item TEXT DEFAULT '', keylock TEXT,
params TEXT,
creation_time TIMESTAMP,
execution_time TIMESTAMP);")
(sqlite3:execute mdb "CREATE TABLE IF NOT EXISTS monitors (id INTEGER PRIMARY KEY,
pid INTEGER,
start_time TIMESTAMP,
(define (tasks:hostinfo-get-interface vec) (vector-ref vec 1))
(define (tasks:hostinfo-get-port vec) (vector-ref vec 2))
(define (tasks:hostinfo-get-pubport vec) (vector-ref vec 3))
(define (tasks:hostinfo-get-transport vec) (vector-ref vec 4))
(define (tasks:hostinfo-get-pid vec) (vector-ref vec 5))
(define (tasks:hostinfo-get-hostname vec) (vector-ref vec 6))
;; state: 'live, 'shutting-down, 'dead
(define (tasks:server-register mdb pid interface port priority state transport #!key (pubport -1))
(debug:print-info 11 "tasks:server-register " pid " " interface " " port " " priority " " state)(define (tasks:server-lock-slot mdb run-id)
(let ((res '())
(best #f))
(tasks:server-clean-out-old-records-for-run-id mdb run-id)
(tasks:server-set-available mdb run-id)
(thread-sleep! 2) ;; Try removing this. It may not be needed.
(tasks:server-am-i-the-server? mdb run-id)))
;; register that this server may come online (first to register goes though with the process)
(define (tasks:server-set-available mdb run-id)
(sqlite3:execute
mdb
"INSERT OR REPLACE INTO servers (pid,hostname,port,pubport,start_time,priority,state,mt_version,heartbeat,interface,transport)
VALUES(?, ?, ?, ?, strftime('%s','now'), ?, ?, ?, strftime('%s','now'),?,?);"
pid (get-host-name) port pubport priority (conc state)
(common:version-signature)
interface(conc transport)) "INSERT INTO servers (pid,hostname,port,pubport,start_time, priority,state,mt_version,heartbeat, interface,transport,run_id)
VALUES(?, ?, ?, ?, strftime('%s','now'), ?, ?, ?, strftime('%s','now'),?, ?, ?);"
(current-process-id) ;; pid
(get-host-name) ;; hostname
-1 ;; port
-1 ;; pubport
(random 1000) ;; priority (used a tiebreaker on get-available)
"available" ;; state
(common:version-signature) ;; mt_version
-1 ;; interface
"http" ;; transport
(vector (tasks:server-get-server-id mdb (get-host-name) interface port pid) interfaceport run-id
pubport transport ))
;; NB// two servers with same pid on different hosts will be removed from the list if pid: is used!
(define (tasks:server-deregister mdb hostname #!key (port #f)(pid #f)(action 'delete))
(debug:print-info 11 "server-deregister " hostname ", port " port ", pid " pid)
(if *db-write-access* (if pid(define (tasks:server-clean-out-old-records-for-run-id mdb run-id)
(sqlite3:execute mdb "DELETE FROM servers WHERE state in ('available','shutting-down') AND (strftime('%s','now') - start_time) > 30 AND run_id=?;" run-id)
(sqlite3:execute mdb "DELETE FROM servers WHERE state='running' AND (strftime('%s','now') - heartbeat) > 10 AND run_id=?;" run-id)
)
(case action ((delete)(sqlite3:execute mdb "DELETE FROM servers WHERE pid=?;" pid))
(else (sqlite3:execute mdb "UPDATE servers SET state='dead' WHERE pid=?;" pid)))
(if port (case action ((delete)(sqlite3:execute mdb "DELETE FROM servers WHERE (interface=? or hostname=?) AND port=?;" hostname hostname port))
(else (sqlite3:execute mdb "UPDATE servers SET state='dead' WHERE (interface=? or hostname=?) AND port=?;" hostname hostname port)))(debug:print 0 "ERROR: tasks:server-deregister called with neither pid nor port specified")))))
(define (tasks:server-set-state! mdb server-id state)
(sqlite3:execute mdb "UPDATE servers SET state=? WHERE id=?;" state server-id))
(define (tasks:server-delete-record! mdb server-id)
(sqlite3:execute mdb "DELETE FROM servers WHERE id=?;" server-id))
(define (tasks:server-delete-records-for-this-pid mdb)
(sqlite3:execute mdb "DELETE FROM servers WHERE hostname=? AND pid=?;" (get-host-name) (current-process-id)))
(define (tasks:server-deregister-self mdb hostname)
(define (tasks:server-set-interface-port mdb server-id interface port)
(tasks:server-deregister mdb hostname pid: (current-process-id))) (sqlite3:execute mdb "UPDATE servers SET interface=?,port=? WHERE id=?;" interface port server-id))
;; need a simple call for robustly removing records given host and port
(define (tasks:server-delete mdb hostname port)
(tasks:server-deregister mdb hostname port: port action: 'delete))
(define (tasks:server-get-server-id mdb hostname iface port pid)
(define (tasks:server-am-i-the-server? mdb run-id)
(let* ((all (tasks:server-get-servers-vying-for-run-id mdb run-id))
(first (if (null? all)
(begin (debug:print 0 "ERROR: no servers listed, should be at least one by now.")
(sqlite3:finalize! mdb)
(exit 1))
(car (db:get-rows all))))
(header (db:get-header all))
(id (db:get-value-by-header first header "id"))
(hostname (db:get-value-by-header first header "hostname"))
(pid (db:get-value-by-header first header "pid"))
(priority (db:get-value-by-header first header "priority")))
(debug:print 0 "INFO: am-i-the-server got record " first)
;; for now a basic check. add tiebreaking by priority later
(if (and (equal? hostname (get-host-name))
(equal? pid (current-process-id)))
id
#f)))
;; Use: (db:get-value-by-header (car (db:get-rows dat)) (db:get-header dat) "fieldname")
;; to extract info from the structure returned
;;
(define (tasks:server-get-servers-vying-for-run-id mdb run-id)
(debug:print-info 12 "tasks:server-get-server-id " mdb " " hostname " " iface " " port " " pid) (let ((res #f))
(let* ((header (list "id" "hostname" "pid" "interface" "port" "pubport" "state" "run_id" "priority" "start_time"))
(selstr (string-intersperse header ","))
(res '()))
(sqlite3:for-each-row
(lambda (id)
(set! res id))
(lambda (a . b)
(set! res (cons (apply vector a b) res)))
mdb
(cond ((and hostname pid) "SELECT id FROM servers WHERE hostname=? AND pid=?;")
(conc "SELECT " selstr " FROM servers WHERE run_id=? ORDER BY start_time DESC;")
((and iface port) "SELECT id FROM servers WHERE interface=? AND port=?;") ((and hostname port) "SELECT id FROM servers WHERE hostname=? AND port=?;") (else (begin run-id)
(debug:print 0 "ERROR: tasks:server-get-server-id needs (hostname and pid) OR (iface and port) OR (hostname and port)") "SELECT id FROM servers WHERE pid=-999;"))) (if hostname hostname iface)(if pid pid port))res))
(vector header res)))
(define (tasks:server-update-heartbeat mdb server-id)
(debug:print-info 1 "Heart beat update of server id=" server-id)
(handle-exceptions
exn
(begin
(debug:print 0 "WARNING: probable timeout on monitor.db access")
(begin
(debug:print-info 1 "Sending signal/term to " pid " on " hostname)
(process-signal pid signal/term) ;; local machine, send sig term
(thread-sleep! 5) ;; give it five seconds to die peacefully then do a brutal kill
(process-signal pid signal/kill))
(debug:print 0 "WARNING: Can't kill frozen server on remote host " hostname))))))
(define (tasks:get-all-servers mdb) (let ((res '())) (sqlite3:for-each-row (lambda (id pid hostname interface port pubport start-time priority state mt-version last-update transport) (set! res (cons (vector id pid hostname interface port pubport start-time priority state mt-version last-update transport) res))) mdb "SELECT id,pid,hostname,interface,port,pubport,start_time,priority,state,mt_version,strftime('%s','now')-heartbeat AS last_update,transport FROM servers ORDER BY start_time DESC;") res));;======================================================================
;; Tasks and Task monitors
;;======================================================================
;;======================================================================
;; Tasks
description This test will fail causing the dependent test "testxz"\
to never run. This triggers the code that must determine\
that a test will never be run and thus remove it from\
the queue of tests to be run.
tags first,single
reviewed 1/1/1965
jobgroup blockz
[setup]
runscript main.sh
[requirements]
priority 1
[test_meta]
jobgroup sqlite3
author matt
owner bob
description This test checks that a multi-lineitem test with mix of pass and non-fail rolls up a PASS
tags first,single
reviewed 09/10/2011, by Matt
[setup]
runscript main.sh
[requirements]
priority 2
# runtimelim 1d 1h 1m 10s
runtimelim 20s
[test_meta]
jobgroup sqlite3
author matt
owner bob
description This test checks that a multi-lineitem test with mix of pass and non-fail rolls up a PASS
tags first,single
reviewed 09/10/2011, by Matt
[setup]
runscript main.sh
[requirements]
priority 3
[test_meta]
jobgroup sqlite3
author matt
owner bob
description This test checks that a multi-lineitem test with mix of pass and non-fail rolls up a PASS
tags first,single
reviewed 09/10/2011, by Matt
[setup]
runscript main.sh
[requirements]
priority 4
[test_meta]
jobgroup sqlite3
author matt
owner bob
description This test checks that a multi-lineitem test with mix of pass and non-fail rolls up a PASS
tags first,single
reviewed 09/10/2011, by Matt
[setup]
runscript runscript.rb
tags non important,dumb junk
[requirements]
waiton runfirst
[items]
MANYITEMS [system (env > envfile.txt;echo aa ab ac ad ae af ag ah ai)]
# BORKED
[test_meta]
jobgroup sqlite3