Index: dashboard-tests.scm ================================================================== --- dashboard-tests.scm +++ dashboard-tests.scm @@ -275,10 +275,11 @@ "runname") #f)) ;; 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) + (testdat-path (conc rundir "/testdat.db")) ;; this gets recalculated until found (teststeps (if testdat (db:get-compressed-steps test-id work-area: rundir) '())) (testfullname (if testdat (db:test-get-fullname testdat) "Gathering data ...")) (testname (if testdat (db:test-get-testname testdat) "n/a")) (testmeta (if testdat (let ((tm (open-run-close db:testmeta-get-record #f testname))) @@ -310,14 +311,21 @@ (conc "-e " (get-environment-variable "SHELL")) ""))) (system (conc "cd " rundir ";xterm -T \"" (string-translate testfullname "()" " ") "\" " shell "&"))) (message-window (conc "Directory " rundir " not found"))))) + (widgets (make-hash-table)) (refreshdat (lambda () - (let* ((curr-mod-time (file-modification-time db-path)) + (let* ((curr-mod-time (max (file-modification-time db-path) + (if (file-exists? testdat-path) + (file-modification-time testdat-path) + (begin + (set! testdat-path (conc rundir "/testdat.db")) + 0)))) (need-update (or (and (> curr-mod-time db-mod-time) - (> (current-seconds) (+ last-update 2))) ;; every two seconds if db touched + (> (current-milliseconds)(+ last-update 250))) ;; every half seconds if db touched + (> (current-milliseconds)(+ last-update 10000)) ;; force update even 10 seconds request-update)) (newtestdat (if need-update (handle-exceptions exn (debug:print-info 2 "test db access issue: " ((condition-property-accessor 'exn 'message) exn)) @@ -328,14 +336,27 @@ (set! teststeps (db:get-compressed-steps test-id work-area: rundir)) (set! logfile (conc (db:test-get-rundir testdat) "/" (db:test-get-final_logf testdat))) (set! rundir (db:test-get-rundir testdat)) (set! testfullname (db:test-get-fullname testdat)) ;; (debug:print 0 "INFO: teststeps=" (intersperse teststeps "\n ")) + (set! db-mod-time curr-mod-time) + (set! last-update (current-milliseconds)) + (set! request-update #f) ;; met the need ... ) (need-update ;; if this was true and yet there is no data .... - (db:test-set-testname! testdat "DEAD OR DELETED TEST")))))) - (widgets (make-hash-table)) + (db:test-set-testname! testdat "DEAD OR DELETED TEST"))) + (if need-update + (begin + ;; update the gui elements here + (for-each + (lambda (key) + ;; (print "Updating " key) + ((hash-table-ref widgets key) testdat)) + (hash-table-keys widgets)) + (update-state-status-buttons testdat))) + ;; (iup:refresh self) + ))) (meta-widgets (make-hash-table)) (self #f) (store-label (lambda (name lbl cmd) (hash-table-set! widgets name (lambda (testdat) @@ -450,23 +471,45 @@ (iup:attribute-set! steps-matrix "ALIGNMENT1" "ALEFT") ;; (iup:attribute-set! steps-matrix "FIXTOTEXT" "C1") (iup:attribute-set! steps-matrix "RESIZEMATRIX" "YES") (let ((proc (lambda (testdat) + (let ((max-row 0)) (if (not (null? teststeps)) (let loop ((hed (car teststeps)) (tal (cdr teststeps)) (rownum 1) (colnum 1)) + (if (> rownum max-row)(set! max-row rownum)) (let ((val (vector-ref hed (- colnum 1))) (mtrx-rc (conc rownum ":" colnum))) (iup:attribute-set! steps-matrix mtrx-rc (if val (conc val) "")) (if (< colnum 6) (loop hed tal rownum (+ colnum 1)) (if (not (null? tal)) - (loop (car tal)(cdr tal)(+ rownum 1) 1)))) - (iup:attribute-set! steps-matrix "REDRAW" "ALL")))))) + (loop (car tal)(cdr tal)(+ rownum 1) 1)))))) + (if (> max-row 0) + (begin + ;; we are going to speculatively clear rows until we find a row that is already cleared + (let loop ((rownum (+ max-row 1)) + (colnum 0) + (deleted #f)) + ;; (debug:print-info 0 "cleaning " rownum ":" colnum) + (let* ((next-row (if (eq? colnum 6) (+ rownum 1) rownum)) + (next-col (if (eq? colnum 6) 1 (+ colnum 1))) + (mtrx-rc (conc rownum ":" colnum)) + (curr-val (iup:attribute steps-matrix mtrx-rc))) + ;; (debug:print-info 0 "cleaning " rownum ":" colnum " currval= " curr-val) + (if (and (string? curr-val) + (not (equal? curr-val ""))) + (begin + (iup:attribute-set! steps-matrix mtrx-rc "") + (loop next-row next-col #t)) + (if (eq? colnum 6) ;; not done, didn't get a full blank row + (if deleted (loop next-row next-col #f)) ;; exit on this not met + (loop next-row next-col deleted))))) + (iup:attribute-set! steps-matrix "REDRAW" "ALL"))))))) (hash-table-set! widgets "StepsMatrix" proc) (proc testdat)) steps-matrix) ;; populate the Test Data panel (iup:frame @@ -512,16 +555,8 @@ (iup:callback-set! *tim* "ACTION_CB" (lambda (x) ;; Now start keeping the gui updated from the db (refreshdat) ;; update from the db here ;(thread-suspend! other-thread) - ;; update the gui elements here - (for-each - (lambda (key) - ;; (print "Updating " key) - ((hash-table-ref widgets key) testdat)) - (hash-table-keys widgets)) - (update-state-status-buttons testdat) - ; (iup:refresh self) (if *exit-started* (set! *exit-started* 'ok)))))))))) Index: dashboard.scm ================================================================== --- dashboard.scm +++ dashboard.scm @@ -118,14 +118,19 @@ (define *alltestnamelst* '()) (define *searchpatts* (make-hash-table)) (define *num-runs* 8) (define *tot-run-count* (cdb:remote-run db:get-num-runs #f "%")) ;; (define *tot-run-count* (db:get-num-runs *db* "%")) + +;; Update management +;; (define *last-update* (current-seconds)) (define *last-db-update-time* 0) (define *please-update-buttons* #t) (define *delayed-update* 0) +(define *update-is-running* #f) +(define *update-mutex* (make-mutex)) (define *num-tests* 15) (define *start-run-offset* 0) (define *start-test-offset* 0) (define *examine-test-dat* (make-hash-table)) @@ -1275,20 +1280,22 @@ (iup:attribute-set! *tim* "RUN" "YES") ;; Move this stuff to db.scm? I'm not sure that is the right thing to do... ;; (define *last-db-update-time* (file-modification-time (conc *toppath* "/megatest.db"))) +(define *last-recalc-ended-time* 0) (define (dashboard:been-changed) (> (file-modification-time (conc *toppath* "/megatest.db")) *last-db-update-time*)) (define (dashboard:set-db-update-time) (set! *last-db-update-time* (file-modification-time (conc *toppath* "/megatest.db")))) (define (dashboard:recalc modtime please-update-buttons last-db-update-time) (or please-update-buttons - (and (> modtime last-db-update-time) + (and (> (current-milliseconds)(+ *last-recalc-ended-time* 150)) + (> modtime last-db-update-time) (> (current-seconds)(+ last-db-update-time 1))))) (define *monitor-db-path* (conc *toppath* "/monitor.db")) (define *last-monitor-update-time* 0) @@ -1328,18 +1335,19 @@ (else (let ((updater (hash-table-ref/default *updaters* *current-tab-number* #f))) (if updater (updater))))) (set! *please-update-buttons* #f) (set! *last-db-update-time* modtime) - (set! *last-update* run-update-time))))) + (set! *last-update* run-update-time) + (set! *last-recalc-ended-time* (current-milliseconds)))))) ;;====================================================================== ;; The heavy lifting starts here ;;====================================================================== -;; ease debugging by loading ~/.megatestrc -(let ((debugcontrolf (conc (get-environment-variable "HOME") "/.megatestrc"))) +;; ease debugging by loading ~/.dashboardrc +(let ((debugcontrolf (conc (get-environment-variable "HOME") "/.dashboardrc"))) (if (file-exists? debugcontrolf) (load debugcontrolf))) (cond ((args:get-arg "-run") @@ -1365,9 +1373,20 @@ (else (set! uidat (make-dashboard-buttons *num-runs* *num-tests* *dbkeys*)) (iup:callback-set! *tim* "ACTION_CB" (lambda (x) + (let ((update-is-running #f)) + (mutex-lock! *update-mutex*) + (set! update-is-running *update-is-running*) + (if (not update-is-running) + (set! *update-is-running* #t)) + (mutex-unlock! *update-mutex*) + (if (not update-is-running) + (begin (dashboard:run-update x) + (mutex-lock! *update-mutex*) + (set! *update-is-running* #f) + (mutex-unlock! *update-mutex*)))) 1)))) (iup:main-loop) Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -1509,10 +1509,12 @@ (define (cdb:num-clients serverdat) (cdb:client-call serverdat 'numclients #t *default-numtries*)) (define (cdb:test-set-status-state serverdat test-id status state msg) + (if (member state '("LAUNCHED" "REMOTEHOSTSTART")) + (cdb:client-call serverdat 'set-test-start-time #t *default-numtries* test-id)) (if msg (cdb:client-call serverdat 'state-status-msg #t *default-numtries* state status msg test-id) (cdb:client-call serverdat 'state-status #t *default-numtries* state status test-id))) ;; run-id test-name item-path minutes cpuload diskfree tmpfree) (define (cdb:test-rollup-test_data-pass-fail serverdat test-id) @@ -1562,10 +1564,11 @@ ;;====================================================================== (define db:queries (list '(register-test "INSERT OR IGNORE INTO tests (run_id,testname,event_time,item_path,state,status) VALUES (?,?,strftime('%s','now'),?,'NOT_STARTED','n/a');") '(state-status "UPDATE tests SET state=?,status=? WHERE id=?;") + '(set-test-start-time "UPDATE tests SET event_time=strftime('%s','now') WHERE id=?;") '(state-status-msg "UPDATE tests SET state=?,status=?,comment=? WHERE id=?;") '(pass-fail-counts "UPDATE tests SET fail_count=?,pass_count=? WHERE id=?;") ;; test_data-pf-rollup is used to set a tests PASS/FAIL based on the pass/fail info from the steps '(test_data-pf-rollup "UPDATE tests SET status=CASE WHEN (SELECT fail_count FROM tests WHERE id=?) > 0 @@ -2179,11 +2182,11 @@ ;; if prereq test with itempath='' is COMPLETED and PASS, WARN, CHECK, or WAIVED then prereq is met ;; if prereq test with itempath=ref-item-path and COMPLETED with PASS, WARN, CHECK, or WAIVED then prereq is met ;; ;; Note: mode 'normal means that tests must be COMPLETED and ok (i.e. PASS, WARN, CHECK, SKIP or WAIVED) ;; mode 'toplevel means that tests must be COMPLETED only -;; mode 'itemmatch means that tests items must be COMPLETED and (PASS|WARN|WAIVED|CHECK) [[ NB// NOT IMPLEMENTED YET ]] +;; mode 'itemmatch or 'itemwait means that tests items must be COMPLETED and (PASS|WARN|WAIVED|CHECK) [[ NB// NOT IMPLEMENTED YET ]] ;; (define (db:get-prereqs-not-met run-id waitons ref-item-path #!key (mode 'normal)) (if (or (not waitons) (null? waitons)) '() @@ -2202,33 +2205,40 @@ ;; (if (equal? waitontest-name (db:test-get-testname test)) ;; by defintion this had better be true ... (let* ((state (db:test-get-state test)) (status (db:test-get-status test)) (item-path (db:test-get-item-path test)) (is-completed (equal? state "COMPLETED")) + (is-running (equal? state "RUNNING")) (is-killed (equal? state "KILLED")) (is-ok (member status '("PASS" "WARN" "CHECK" "WAIVED" "SKIP"))) (same-itempath (equal? ref-item-path item-path))) (set! ever-seen #t) (cond ;; case 1, non-item (parent test) is ((and (equal? item-path "") ;; this is the parent test is-completed - (or is-ok (member mode '(toplevel itemmatch)))) + (or is-ok (member mode '(toplevel itemmatch itemwait)))) (set! parent-waiton-met #t)) ;; Special case for toplevel and KILLED ((and (equal? item-path "") ;; this is the parent test is-killed (eq? mode 'toplevel)) (set! parent-waiton-met #t)) - ((or (and (not same-itempath) - (eq? mode 'itemmatch)) ;; in itemmatch mode we look only at the same itempath - (and same-itempath - is-completed - (or is-ok - (eq? mode 'toplevel) ;; toplevel does not block on FAIL - (and is-ok (eq? mode 'itemmatch)) ;; itemmatch blocks on not ok - ))) + ;; For itemwait mode IFF the previous matching item is good the set parent-waiton-met + ((and (member mode '(itemmatch itemwait)) + ;; (not (equal? item-path "")) ;; this applies to both top level (to allow launching of next batch) and items + same-itempath) + (if (and is-completed is-ok) + (set! item-waiton-met #t)) + (if (and (equal? item-path "") + (or is-completed is-running));; this is the parent, set it to run if completed or running + (set! parent-waiton-met #t))) + ;; normal checking of parent items, any parent or parent item not ok blocks running + ((and is-completed + (or is-ok + (eq? mode 'toplevel)) ;; toplevel does not block on FAIL + (and is-ok (eq? mode 'itemmatch))) ;; itemmatch blocks on not ok (set! item-waiton-met #t))))) tests) ;; both requirements, parent and item-waiton must be met to NOT add item to ;; prereq's not met list (if (not (or parent-waiton-met item-waiton-met)) Index: docs/manual/Makefile ================================================================== --- docs/manual/Makefile +++ docs/manual/Makefile @@ -1,5 +1,7 @@ -megatest_manual.html : megatest_manual.txt getting_started.txt writing_tests.txt reference.txt +megatest_manual.html : megatest_manual.txt getting_started.txt writing_tests.txt reference.txt ../plan.txt asciidoc megatest_manual.txt dos2unix megatest_manual.html +clean: + rm -f megatest_manual.html Index: docs/manual/megatest_manual.html ================================================================== --- docs/manual/megatest_manual.html +++ docs/manual/megatest_manual.html @@ -750,21 +750,22 @@

This book is organised as three sub-books; getting started, writing tests and reference.

Why Megatest?

The Megatest project was started for two reasons, the first was an immediate and pressing need for a generalized tool to manage a suite -of regression tests and the second was the fact that I had written or -maintained several such tools at different companies over the years -and it seemed a good thing to have a single open source tool, flexible -enough to meet the needs of any team doing continuous integrating and -or running a complex suite of tests for release qualification.

+of regression tests and the second was the fact that the author had +written or maintained several such tools at different companies over +the years and it seemed a good thing to have a single open source +tool, flexible enough to meet the needs of any team doing continuous +integrating and or running a complex suite of tests for release +qualification.

Megatest Design Philosophy

Megatest is intended to provide the minimum needed resources to make -writing a suite of tests and implementing continuous build for -software, design engineering or process control (via owlfs for +writing a suite of tests and tasks for implementing continuous build +for software, design engineering or process control (via owlfs for example) without being specialized for any specific problem space. Megatest in of itself does not know what constitutes a PASS or FAIL of a test. In most cases megatest is best used in conjunction with logpro or a similar tool to parse, analyze and decide on the test outcome.

@@ -778,10 +779,324 @@ which can launch jobs on local and remote Linux hosts. Currently megatest uses the network filesystem to call home to your master sqlite3 database.

+ +

Road Map

+

Note: This road-map is tentative and subject to change without notice.

+
+

ww32

+
    +
  1. +

    +Rerun step and or subsequent steps from gui +

    +
  2. +
  3. +

    +Refresh test area files from gui +

    +
  4. +
  5. +

    +Clean and re-run button +

    +
  6. +
  7. +

    +Clean up STATE and STATUS handling. +

    +
      +
    1. +

      +Dashboard and Test control panel are reverse order - choose and fix +

      +
    2. +
    3. +

      +Move seldom used states and status to drop down selector +

      +
    4. +
    +
  8. +
  9. +

    +Access test control panel when clicking on Run Summary tests +

    +
  10. +
  11. +

    +Feature: -generate-index-tree +

    +
  12. +
  13. +

    +Change specifing of state and status to use STATE1/STATUS1,STATE2/STATUS2 +

    +
  14. +
+
+
+

ww33

+
    +
  1. +

    +http api available for use with Perl, Ruby etc. scripts +

    +
  2. +
  3. +

    +megatest.config setup entries for: +

    +
      +
    1. +

      +run launching (e.g. /bin/sh %CMD% > /dev/null) +

      +
    2. +
    3. +

      +browser "konqueror %FNAME% +

      +
    4. +
    +
  4. +
+
+
+

ww34

+
    +
  1. +

    +Mark dependent tests for clean/rerun -rerun-downstream +

    +
  2. +
  3. +

    +On run start check for defunct tests in RUNNING, LAUNCHED or REMOTEHOSTSTART and correct or notify +

    +
  4. +
  5. +

    +Fix: refresh of gui sometimes fails on last item (race condition?) +

    +
  6. +
+
+
+

ww35

+
    +
  1. +

    +refdb: Add export of csv, json and sexp +

    +
  2. +
  3. +

    +Convert to using call-with-environment-variables where possible. Should allow handling of parallel runs in same process. +

    +
  4. +
  5. +

    +Re-work text interface wizards. Several bugs on record. Possibly convert to gui based. +

    +
  6. +
  7. +

    +Add to testconfig requirements section; launchlimiter scriptname, calls scriptname to check if ok to launch test +

    +
  8. +
  9. +

    +Refactor Run Summary view, currently very clumsy +

    +
  10. +
  11. +

    +Add option to show steps in Run Summary view +

    +
  12. +
+
+
+

ww36

+
    +
  1. +

    +Refactor guis for resizeablity +

    +
  2. +
  3. +

    +Add filters to Run Summary view and Run Control view +

    +
  4. +
  5. +

    +Add to megatest.config or testconfig; rerunok STATE/STATUS,STATE/STATUS… +

    +
  6. +
  7. +

    +Launch gates for diskspace; /path/one>1G,/path/two>200M,/tmp>5G,#{scheme toppath}>1G +

    +
  8. +
+
+
+

Bin List

+
    +
  1. +

    +Quality improvements +

    +
      +
    1. +

      +Server stutters occasionally +

      +
    2. +
    3. +

      +Large number of items or tests still has some issues. +

      +
    4. +
    5. +

      +Code refactoring +

      +
    6. +
    7. +

      +Replace remote process with true API using json (supports Web app also) +

      +
    8. +
    +
  2. +
  3. +

    +Streamline the gui +

    +
      +
    1. +

      +Everything resizable +

      +
    2. +
    3. +

      +Less clutter +

      +
    4. +
    5. +

      +Tool tips +

      +
    6. +
    7. +

      +Filters on Run Summary, Summary and Run Control panel +

      +
    8. +
    9. +

      +Built in log viewer (partially implemented) +

      +
    10. +
    11. +

      +Refactor the test control panel +

      +
    12. +
    +
  4. +
  5. +

    +Help and documentation +

    +
      +
    1. +

      +Complete the user manual (I’ve been working on this lately). +

      +
    2. +
    3. +

      +Online help in the gui +

      +
    4. +
    +
  6. +
  7. +

    +Streamlined install +

    +
      +
    1. +

      +Deployed version (download a location independent ready to run binary bundle) +

      +
    2. +
    3. +

      +Install Makefile (in progress, needed for Mike to install on VMs) +

      +
    4. +
    5. +

      +Added option to compile IUP (needed for VMs) +

      +
    6. +
    +
  8. +
  9. +

    +Server side run launching +

    +
  10. +
  11. +

    +Support for re-running, cleaning etc. of individual steps (ezsteps makes this very easy to implement). +

    +
  12. +
  13. +

    +Launch process needs built in daemonizing (easy to do, just need to test it thoroughly). +

    +
  14. +
  15. +

    +Wizards for creating tests, regression areas (current ones are text only and limited). +

    +
  16. +
  17. +

    +Fully functional built in web service (currently you can browse runs but it is very simplistic). +

    +
  18. +
  19. +

    +Wildcards in runconfigs: e.g. [p1271/9/%/%] +

    +
  20. +
  21. +

    +Gui panels for editing megatest.config and runconfigs.config +

    +
  22. +
  23. +

    +Fully isolated tests (no use of NFS to see regression area files) +

    +
  24. +
  25. +

    +Windows version +

    +
  26. +

Getting Started

Getting started with Megatest
@@ -869,17 +1184,25 @@

An example link to anchor at start of the first sub-section.

An example link to a bibliography entry [taoup].

-

Reference

+

Writing Tests

The First Chapter of the Second Part

Chapters grouped into book parts are at level 1 and can contain sub-sections.

+
+

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

@@ -1084,10 +1407,10 @@

Index: docs/manual/megatest_manual.txt ================================================================== --- docs/manual/megatest_manual.txt +++ docs/manual/megatest_manual.txt @@ -13,22 +13,23 @@ Why Megatest? ~~~~~~~~~~~~~ The Megatest project was started for two reasons, the first was an immediate and pressing need for a generalized tool to manage a suite -of regression tests and the second was the fact that I had written or -maintained several such tools at different companies over the years -and it seemed a good thing to have a single open source tool, flexible -enough to meet the needs of any team doing continuous integrating and -or running a complex suite of tests for release qualification. +of regression tests and the second was the fact that the author had +written or maintained several such tools at different companies over +the years and it seemed a good thing to have a single open source +tool, flexible enough to meet the needs of any team doing continuous +integrating and or running a complex suite of tests for release +qualification. Megatest Design Philosophy ~~~~~~~~~~~~~~~~~~~~~~~~~~ Megatest is intended to provide the minimum needed resources to make -writing a suite of tests and implementing continuous build for -software, design engineering or process control (via owlfs for +writing a suite of tests and tasks for implementing continuous build +for software, design engineering or process control (via owlfs for example) without being specialized for any specific problem space. Megatest in of itself does not know what constitutes a PASS or FAIL of a test. In most cases megatest is best used in conjunction with logpro or a similar tool to parse, analyze and decide on the test outcome. @@ -42,11 +43,13 @@ the distributed compute platform in use. A template script is provided which can launch jobs on local and remote Linux hosts. Currently megatest uses the network filesystem to call home to your master sqlite3 database. -include::getting_started.txt[] include::writing_tests.txt[] +include::../plan.txt[] +include::getting_started.txt[] +include::writing_tests.txt[] include::reference.txt[] [appendix] Example Appendix ================ Index: docs/plan.txt ================================================================== --- docs/plan.txt +++ docs/plan.txt @@ -1,7 +1,58 @@ Road Map ======== + +Note: This road-map is tentative and subject to change without notice. + +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 @@ -28,17 +79,5 @@ . 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 -Move test specific db to test dir -================================= - -. Create teststats.db -. Redirect test run stats to teststats.db -. Redirect test steps data to teststats.db -. Redirect test_data to teststats.db -. Direct dboard to get stats from teststats.db -. Redirect kill requests to teststats.db -. Kill requests need to kill all processes in the tree -. Roll up overall stats to megatest.db every five minutes or when test done -. Add any necessary tests Index: http-transport.scm ================================================================== --- http-transport.scm +++ http-transport.scm @@ -11,11 +11,11 @@ (require-extension (srfi 18) extras tcp s11n) (use sqlite3 srfi-1 posix regex regex-case srfi-69 hostinfo md5 message-digest) (import (prefix sqlite3 sqlite3:)) -(use spiffy uri-common intarweb http-client spiffy-request-vars uri-common intarweb spiffy-directory-listing) +(use spiffy uri-common intarweb http-client spiffy-request-vars intarweb spiffy-directory-listing) ;; Configurations for server (tcp-buffer-size 2048) (max-connections 2048) Index: megatest-version.scm ================================================================== --- megatest-version.scm +++ megatest-version.scm @@ -1,7 +1,7 @@ ;; Always use two digit decimal ;; 1.01, 1.02...1.10,1.11 ... 1.99,2.00.. (declare (unit megatest-version)) -(define megatest-version 1.5508) +(define megatest-version 1.6) Index: mt.scm ================================================================== --- mt.scm +++ mt.scm @@ -43,16 +43,16 @@ (define (mt:get-runs-by-patt keys runnamepatt targpatt) (let loop ((runsdat (cdb:remote-run db:get-runs-by-patt #f keys runnamepatt targpatt 0 500)) (res '()) (offset 0) (limit 500)) - (print "runsdat: " runsdat) + ;; (print "runsdat: " runsdat) (let* ((header (vector-ref runsdat 0)) (runslst (vector-ref runsdat 1)) (full-list (append res runslst)) (have-more (eq? (length runslst) limit))) - (debug:print 0 "header: " header " runslst: " runslst " have-more: " have-more) + ;; (debug:print 0 "header: " header " runslst: " runslst " have-more: " have-more) (if have-more (let ((new-offset (+ offset limit)) (next-batch (cdb:remote-run db:get-runs-by-patt #f keys runnamepatt targpatt offset limit))) (debug:print-info 4 "More than " limit " runs, have " (length full-list) " runs so far.") (debug:print-info 0 "next-batch: " next-batch) Index: runs.scm ================================================================== --- runs.scm +++ runs.scm @@ -518,14 +518,12 @@ ;; If one or more of the prereqs-not-met are FAIL then we can issue ;; a message and drop hed from the items to be processed. (if (null? fails) (begin ;; couldn't run, take a breather - (debug:print-info 0 "Shouldn't really get here, race condition? Unable to launch more tests at this moment, killing time ...") - (debug:print-info 0 " test is " hed ", prereqs-not-met is " prereqs-not-met) - ;; (thread-sleep! (+ 0.01 *global-delta*)) ;; long sleep here - no resources, may as well be patient - ;; we made new tal by sticking hed at the back of the list + (debug:print-info 0 "Waiting for more work to do...") + (thread-sleep! 1) (list (car newtal)(cdr newtal) reg reruns)) ;; the waiton is FAIL so no point in trying to run hed ever again (if (or (not (null? reg))(not (null? tal))) (if (vector? hed) (begin @@ -908,10 +906,34 @@ (let ((dparts (string-split dir "/")) (count (if (null? params) 1 (car params)))) (conc "/" (string-intersperse (take dparts (- (length dparts) count)) "/")))) + +(define (runs:recursive-delete-with-error-msg real-dir) + (if (> (system (conc "rm -rf " real-dir)) 0) + (debug:print 0 "ERROR: There was a problem removing " real-dir " with rm -f"))) + +(define (runs:safe-delete-test-dir real-dir) + ;; first delete all sub-directories + (directory-fold + (lambda (f x) + (let ((fullname (conc real-dir "/" f))) + (if (directory? fullname)(runs:recursive-delete-with-error-msg fullname))) + (+ 1 x)) + 0 real-dir) + ;; then files other than *testdat.db* + (directory-fold + (lambda (f x) + (let ((fullname (conc real-dir "/" f))) + (if (not (string-search (regexp "testdat.db") f)) + (runs:recursive-delete-with-error-msg fullname))) + (+ 1 x)) + 0 real-dir) + ;; then the entire directory + (runs:recursive-delete-with-error-msg real-dir)) + ;; Remove runs ;; fields are passing in through ;; action: ;; 'remove-runs ;; 'set-state-status @@ -989,11 +1011,13 @@ ((remove-runs) (debug:print-info 0 "test: " test-name " itest-state: " test-state) (if (member test-state (list "RUNNING" "LAUNCHED" "REMOTEHOSTSTART" "KILLREQ")) (begin (if (not (hash-table-ref/default test-retry-time test-fulln #f)) - (hash-table-set! test-retry-time test-fulln (current-seconds))) + (begin + ;; want to set to REMOVING BUT CANNOT do it here? + (hash-table-set! test-retry-time test-fulln (current-seconds)))) (if (> (- (current-seconds)(hash-table-ref test-retry-time test-fulln)) allow-run-time) ;; This test is not in a correct state for cleaning up. Let's try some graceful shutdown steps first ;; Set the test to "KILLREQ" and wait five seconds then try again. Repeat up to five times then give ;; up and blow it away. (begin @@ -1006,20 +1030,19 @@ ;; NOTE: This is suboptimal as the testdata will be used later and the state/status may have changed ... (if (null? tal) (loop new-test-dat tal) (loop (car tal)(append tal (list new-test-dat))))) (begin - (cdb:remote-run db:delete-test-records db #f (db:test-get-id test)) + (cdb:remote-run db:test-set-state-status-by-id db (db:test-get-id test) "REMOVING" "LOCKED" #f) (debug:print-info 1 "Attempting to remove " (if real-dir (conc " dir " real-dir " and ") "") " link " run-dir) (if (and real-dir (> (string-length real-dir) 5) (file-exists? real-dir)) ;; bad heuristic but should prevent /tmp /home etc. (begin ;; let* ((realpath (resolve-pathname run-dir))) (debug:print-info 1 "Recursively removing " real-dir) (if (file-exists? real-dir) - (if (> (system (conc "rm -rf " real-dir)) 0) - (debug:print 0 "ERROR: There was a problem removing " real-dir " with rm -f")) + (runs:safe-delete-test-dir real-dir) (debug:print 0 "WARNING: test dir " real-dir " appears to not exist or is not readable"))) (if real-dir (debug:print 0 "WARNING: directory " real-dir " does not exist") (debug:print 0 "WARNING: no real directory corrosponding to link " run-dir ", nothing done"))) (if (symbolic-link? run-dir) @@ -1038,10 +1061,12 @@ (delete-directory run-dir))) (if run-dir (debug:print 0 "WARNING: not removing " run-dir " as it either doesn't exist or is not a symlink") (debug:print 0 "NOTE: the run dir for this test is undefined. Test may have already been deleted.")) )) + ;; Only delete the records *after* removing the directory. If things fail we have a record + (cdb:remote-run db:delete-test-records db #f (db:test-get-id test)) (if (not (null? tal)) (loop (car tal)(cdr tal)))))) ((set-state-status) (debug:print-info 2 "new state " (car state-status) ", new status " (cadr state-status)) (cdb:remote-run db:test-set-state-status-by-id db (db:test-get-id test) (car state-status)(cadr state-status) #f) Index: tests.scm ================================================================== --- tests.scm +++ tests.scm @@ -218,11 +218,12 @@ (loop (car tal)(cdr tal)))))))))) ;; Check for waiver eligibility ;; (define (tests:check-waiver-eligibility testdat prev-testdat) - (let* ((testconfig (tests:get-testconfig (db:test-get-testname testdat) #f)) + (let* ((test-registry (make-hash-table)) + (testconfig (tests:get-testconfig (db:test-get-testname testdat) test-registry #f)) (test-rundir (db:test-get-rundir testdat)) (prev-rundir (db:test-get-rundir prev-testdat)) (waivers (configf:section-vars testconfig "waivers")) (waiver-rx (regexp "^(\\S+)\\s+(.*)$")) (diff-rule "diff %file1% %file2%") ADDED tests/fdktestqa/testqa/README Index: tests/fdktestqa/testqa/README ================================================================== --- /dev/null +++ tests/fdktestqa/testqa/README @@ -0,0 +1,1 @@ +set NUMTESTS to set the number of tests that will be run. A small number (say 20) illustrates itemwait well. Index: tests/fdktestqa/testqa/tests/bigrun/step1.sh ================================================================== --- tests/fdktestqa/testqa/tests/bigrun/step1.sh +++ tests/fdktestqa/testqa/tests/bigrun/step1.sh @@ -1,9 +1,9 @@ #!/bin/sh -if [ $NUMBER -lt 200 ];then - sleep 20 - sleep $NUMBER +if [ $NUMBER -lt 15 ];then + sleep 2 + sleep `echo 2 * $NUMBER | bc` else - sleep 200 + sleep 100 fi exit 0 Index: tests/fdktestqa/testqa/tests/bigrun2/testconfig ================================================================== --- tests/fdktestqa/testqa/tests/bigrun2/testconfig +++ tests/fdktestqa/testqa/tests/bigrun2/testconfig @@ -4,11 +4,11 @@ # Test requirements are specified here [requirements] waiton bigrun priority 0 -mode itemmatch +mode itemwait # Iteration for your tests are controlled by the items section [items] NUMBER #{scheme (string-intersperse (map number->string (sort (let loop ((a 0)(res '()))(if (<= a (or (any->number (get-environment-variable "NUMTESTS")) 2500))(loop (+ a 1)(cons a res)) res)) <)) " ")} ADDED tests/fdktestqa/testqa/tests/bigrun3/step1.sh Index: tests/fdktestqa/testqa/tests/bigrun3/step1.sh ================================================================== --- /dev/null +++ tests/fdktestqa/testqa/tests/bigrun3/step1.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# prev_test=`$MT_MEGATEST -test-paths -target $MT_TARGET :runname $MT_RUNNAME -testpatt bigrun/$NUMBER` +# if [ -e $prev_test/testconfig ]; then +# exit 0 +# else +# exit 1 +# fi + +exit 0 ADDED tests/fdktestqa/testqa/tests/bigrun3/testconfig Index: tests/fdktestqa/testqa/tests/bigrun3/testconfig ================================================================== --- /dev/null +++ tests/fdktestqa/testqa/tests/bigrun3/testconfig @@ -0,0 +1,22 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +step1 step1.sh + +# Test requirements are specified here +[requirements] +waiton bigrun2 +priority 0 +mode itemwait + + +# Iteration for your tests are controlled by the items section +[items] +NUMBER #{scheme (string-intersperse (map number->string (sort (let loop ((a 0)(res '()))(if (<= a (or (any->number (get-environment-variable "NUMTESTS")) 2500))(loop (+ a 1)(cons a res)) res)) <)) " ")} + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description An example test +tags tagone,tagtwo +reviewed never