Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -14,10 +14,11 @@ example/linktree example/runs *.backup mkdeploy/linktree mkdeploy/site.config +deploytarg/* mtest newdboard *.log fslsync/fslsynclinks/* fslsync/fslsyncruns/* @@ -27,5 +28,16 @@ *.bak simplerun/*.scm simplerun/simpleruns tests/mintest/runs/* tests/mintest/linktree/* +tests/installall/stdrel/* +tests/installall/runs/* +tests/installall/links/* +tests/fdktestqa/simpleruns/* +tests/installall/megatest.db +tests/installall/monitor.db +tests/megatest.db +tests/fdktestqa/simplelinks/* +tests/fdktestqa/testqa/megatest.db +tests/fdktestqa/testqa/monitor.db +megatest-fossil-hash.scm Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -6,11 +6,11 @@ ods.scm runconfig.scm server.scm configf.scm \ db.scm keys.scm margs.scm megatest-version.scm \ process.scm runs.scm tasks.scm tests.scm genexample.scm \ fs-transport.scm http-transport.scm \ client.scm gutils.scm synchash.scm daemon.scm mt.scm dcommon.scm \ - tree.scm + tree.scm ezsteps.scm lock-queue.scm GUISRCF = dashboard-tests.scm dashboard-guimonitor.scm OFILES = $(SRCFILES:%.scm=%.o) GOFILES = $(GUISRCF:%.scm=%.o) @@ -21,11 +21,14 @@ MTESTHASH=$(shell fossil info|grep checkout:| awk '{print $$2}') CSIPATH=$(shell which csi) CKPATH=$(shell dirname $(shell dirname $(CSIPATH))) -all : mtest dboard newdboard +all : mtest dboard newdboard txtdb + +refdb : txtdb/txtdb.scm + csc -I txtdb txtdb/txtdb.scm -o refdb mtest: $(OFILES) megatest.o csc $(CSCOPTS) $(OFILES) megatest.o -o mtest dboard : $(OFILES) $(GOFILES) dashboard.scm @@ -32,10 +35,13 @@ csc $(OFILES) dashboard.scm $(GOFILES) -o dboard newdboard : newdashboard.scm $(OFILES) $(GOFILES) csc $(OFILES) $(GOFILES) newdashboard.scm -o newdboard +$(PREFIX)/bin/revtagfsl : utils/revtagfsl.scm + csc utils/revtagfsl.scm -o $(PREFIX)/bin/revtagfsl + deploytarg/libiupcd.so : $(CKPATH)/lib/libiupcd.so for i in iup im cd av call sqlite; do \ cp $(CKPATH)/lib/lib$$i* deploytarg/ ; \ done cp $(CKPATH)/include/*.h deploytarg @@ -86,18 +92,26 @@ chmod a+x $@ $(DEPLOYHELPERS) : utils/mt_* $(INSTALL) $< $@ chmod a+X $@ + +$(PREFIX)/bin/mt_xterm : utils/mt_xterm + $(INSTALL) $< $@ + chmod a+x $@ $(PREFIX)/bin/nbfake : utils/nbfake $(INSTALL) $< $@ chmod a+x $@ $(PREFIX)/bin/nbfind : utils/nbfind $(INSTALL) $< $@ chmod a+x $@ + +$(PREFIX)/bin/refdb : refdb + $(INSTALL) $< $@ + chmod a+x $@ deploytarg/nbfake : utils/nbfake $(INSTALL) $< $@ chmod a+x $@ @@ -110,11 +124,12 @@ $(PREFIX)/bin/dboard : dboard $(FILES) $(INSTALL) dboard $(PREFIX)/bin/dboard utils/mk_wrapper $(PREFIX) dboard > $(PREFIX)/bin/dashboard chmod a+x $(PREFIX)/bin/dashboard -install : bin $(PREFIX)/bin/mtest $(PREFIX)/bin/megatest $(PREFIX)/bin/dboard $(PREFIX)/bin/dashboard $(HELPERS) $(PREFIX)/bin/nbfake $(PREFIX)/bin/nbfind $(PREFIX)/bin/newdboard +install : bin $(PREFIX)/bin/mtest $(PREFIX)/bin/megatest $(PREFIX)/bin/dboard $(PREFIX)/bin/dashboard $(HELPERS) $(PREFIX)/bin/nbfake \ + $(PREFIX)/bin/nbfind $(PREFIX)/bin/newdboard $(PREFIX)/bin/refdb $(PREFIX)/bin/mt_xterm $(PREFIX)/bin/revtagfsl deploytarg/apropos.so : Makefile for i in apropos base64 canvas-draw csv-xml directory-utils dot-locking extras fmt format hostinfo http-client intarweb json md5 message-digest posix posix-extras readline regex regex-case s11n spiffy spiffy-request-vars sqlite3 srfi-1 srfi-18 srfi-69 tcp test uri-common check-errors synch matchable sql-null tcp-server rpc blob-utils string-utils variable-item defstruct uri-generic sendfile opensll openssl lookup-table list-utils stack; do \ chicken-install -prefix deploytarg -deploy $$i;done @@ -131,6 +146,6 @@ test: tests/tests.scm cd tests;csi -I .. -b -n tests.scm clean : - rm -f $(OFILES) $(GOFILES) megatest dboard dboard.o megatest.o + rm -f $(OFILES) $(GOFILES) megatest dboard dboard.o megatest.o dashboard.o Index: NOTES ================================================================== --- NOTES +++ NOTES @@ -1,5 +1,17 @@ +# FROM andyjpg on #chicken + +(let ((original-exit (exit-handler))) + (exit-handler (lambda (#!optional (exit-code 0)) + (printf "Preparing to exit...\n" exit-code) + (for-each (lambda (pid) + (printf "Sending signal/term to ~A\n" pid) + (process-signal pid signal/term)) (children)) + (original-exit exit-code)))) + + + 1. All run control access to db is direct. 2. All test machines must have megatest available 3. Tests may or may not have file system access to the originating run area. rsync is used to pull the test area to the home host if and only if the originating area can not be seen via file Index: client.scm ================================================================== --- client.scm +++ client.scm @@ -17,11 +17,11 @@ (use sqlite3 srfi-1 posix regex regex-case srfi-69 hostinfo md5 message-digest) ;; (use zmq) (import (prefix sqlite3 sqlite3:)) -(use spiffy uri-common intarweb http-client spiffy-request-vars uri-common intarweb) +(use spiffy uri-common intarweb http-client spiffy-request-vars uri-common intarweb directory-utils) (declare (unit client)) (declare (uses common)) (declare (uses db)) @@ -50,45 +50,30 @@ ;; Do all the connection work, look up the transport type and set up the ;; connection if required. ;; ;; 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 mush figure out +;; 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 50)) +(define (client:setup #!key (numtries 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 (debug:print-info 11 "*transport-type* is " *transport-type* ", *runremote* is " *runremote*) - (let* ((hostinfo (if (not *transport-type*) ;; If we dont' already have transport type set then figure it out - (open-run-close tasks:get-best-server tasks:open-db) - #f))) - ;; if have hostinfo then extract the transport type - ;; else fall back to fs + (let* ((hostinfo (open-run-close tasks:get-best-server tasks:open-db))) (debug:print-info 11 "CLIENT SETUP, hostinfo=" hostinfo) (set! *transport-type* (if hostinfo (string->symbol (tasks:hostinfo-get-transport hostinfo)) 'fs)) - ;; ;; DEBUG STUFF - ;; (if (eq? *transport-type* 'fs)(begin (print "ERROR!!!!!!! refusing to run with transport " *transport-type*)(exit 99))) - (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)))) - ;; we are not doing fs any longer. let's cheat and start up a server - ;; if we are falling back on fs (not 100% supported) do an about face and start a server - (if (not (equal? (args:get-arg "-transport") "fs")) - (begin - (set! *transport-type* #f) - (system (conc "megatest -list-servers | grep " megatest-version " | grep alive || megatest -server - -daemonize && sleep 3")) - (thread-sleep! 1) - (if (> numtries 0) - (client:setup numtries: (- numtries 1)))))) + ((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) @@ -95,11 +80,12 @@ (tasks:hostinfo-get-port hostinfo) (tasks:hostinfo-get-pubport hostinfo))) (else ;; default to fs (debug:print 0 "ERROR: unrecognised transport type " *transport-type* " attempting to continue with fs") (set! *transport-type* 'fs) - (set! *megatest-db* (open-db)))))) + (set! *megatest-db* (open-db)))) + (pop-directory))) ;; client:signal-handler (define (client:signal-handler signum) (handle-exceptions exn Index: common.scm ================================================================== --- common.scm +++ common.scm @@ -40,11 +40,11 @@ (define *globalexitstatus* 0) ;; attempt to work around possible thread issues (define *passnum* 0) ;; when running track calls to run-tests or similar ;; SERVER (define *my-client-signature* #f) -(define *transport-type* #f) +(define *transport-type* 'fs) (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 (define *last-db-access* (current-seconds)) ;; update when db is accessed via server (define *max-cache-size* 0) @@ -71,10 +71,14 @@ ;; Awful. Please FIXME (define *env-vars-by-run-id* (make-hash-table)) (define *current-run-name* #f) +;; Testconfig and runconfig caches. +(define *testconfigs* (make-hash-table)) ;; test-name => testconfig +(define *runconfigs* (make-hash-table)) ;; target => runconfig + (define (common:clear-caches) (set! *target* (make-hash-table)) (set! *keys* (make-hash-table)) (set! *keyvals* (make-hash-table)) (set! *toptest-paths* (make-hash-table)) @@ -83,11 +87,28 @@ (set! *test-info* (make-hash-table)) (set! *run-info-cache* (make-hash-table)) (set! *env-vars-by-run-id* (make-hash-table)) (set! *test-id-cache* (make-hash-table))) -;; Debugging stuff +;;====================================================================== +;; S T A T E S A N D S T A T U S E S +;;====================================================================== + +(define *common:std-states* + (list "COMPLETED" "NOT_STARTED" "RUNNING" "REMOTEHOSTSTART" "LAUNCHED" "KILLED" "KILLREQ" "STUCK")) + +(define *common:std-statuses* + (list "PASS" "WARN" "FAIL" "CHECK" "n/a" "WAIVED" "SKIP" "DELETED" "STUCK/DEAD")) + +;; These are stopping conditions that prevent a test from being run +(define *common:cant-run-states-sym* + '(COMPLETED KILLED WAIVED UNKNOWN INCOMPLETE)) + +;;====================================================================== +;; D E B U G G I N G S T U F F +;;====================================================================== + (define *verbosity* 1) (define *logging* #f) (define (get-with-default val default) (let ((val (args:get-arg val))) @@ -296,26 +317,28 @@ (uname #f)) (if (null? (car uname-res)) "unknown" (caar uname-res)))) -(define (save-environment-as-files fname) +(define (save-environment-as-files fname #!key (ignorevars (list "DISPLAY" "LS_COLORS" "XKEYSYMDB" "EDITOR"))) (let ((envvars (get-environment-variables)) (whitesp (regexp "[^a-zA-Z0-9_\\-:;,.\\/%$]"))) (with-output-to-file (conc fname ".csh") (lambda () (for-each (lambda (key) - (let* ((val (cdr key)) - (sval (if (string-search whitesp val)(conc "\"" val "\"") val))) - (print "setenv " (car key) " " sval))) - envvars))) + (if (not (member key ignorevars)) + (let* ((val (cdr key)) + (sval (if (string-search whitesp val)(conc "\"" val "\"") val))) + (print "setenv " (car key) " " sval)))) + envvars))) (with-output-to-file (conc fname ".sh") (lambda () (for-each (lambda (key) - (let* ((val (cdr key)) - (sval (if (string-search whitesp val)(conc "\"" val "\"") val))) - (print "export " (car key) "=" sval))) + (if (not (member key ignorevars)) + (let* ((val (cdr key)) + (sval (if (string-search whitesp val)(conc "\"" val "\"") val))) + (print "export " (car key) "=" sval)))) envvars))))) ;; set some env vars from an alist, return an alist with original values ;; (("VAR" "value") ...) (define (alist->env-vars lst) Index: common_records.scm ================================================================== --- common_records.scm +++ common_records.scm @@ -49,20 +49,24 @@ (define (debug:print n . params) (if (debug:debug-mode n) (with-output-to-port (current-error-port) (lambda () - (apply print params) - (if *logging* (apply db:log-event params)))))) + (if *logging* + (db:log-event (apply conc params)) + (apply print params) + ))))) (define (debug:print-info n . params) (if (debug:debug-mode n) (with-output-to-port (current-error-port) (lambda () - (let ((res #f));; (format#format #f "INFO:~2d ~a" n (apply conc params)))) - (apply print "INFO: (" n ") " params) ;; res) - (if *logging* (db:log-event res))))))) + (let ((res (format#format #f "INFO: (~2d) ~a" n (apply conc params)))) + (if *logging* + (db:log-event res) + (apply print "INFO: (" n ") " params) ;; res) + )))))) ;; if a value is printable (i.e. string or number) return the value ;; else return an empty string (define-inline (printable val) (if (or (number? val)(string? val)) val "")) Index: configf.scm ================================================================== --- configf.scm +++ configf.scm @@ -54,10 +54,11 @@ (define configf:include-rx (regexp "^\\[include\\s+(.*)\\]\\s*$")) (define configf:section-rx (regexp "^\\[(.*)\\]\\s*$")) (define configf:blank-l-rx (regexp "^\\s*$")) (define configf:key-sys-pr (regexp "^(\\S+)\\s+\\[system\\s+(\\S+.*)\\]\\s*$")) (define configf:key-val-pr (regexp "^(\\S+)(\\s+(.*)|())$")) +(define configf:key-no-val (regexp "^(\\S+)(\\s*)$")) (define configf:comment-rx (regexp "^\\s*#.*")) (define configf:cont-ln-rx (regexp "^(\\s+)(\\S+.*)$")) ;; read a line and process any #{ ... } constructs @@ -140,11 +141,12 @@ (define (read-config path ht allow-system #!key (environ-patt #f)(curr-section #f)(sections #f)) (debug:print-info 5 "read-config " path " allow-system " allow-system " environ-patt " environ-patt " curr-section: " curr-section " sections: " sections " pwd: " (current-directory)) (if (not (file-exists? path)) (begin (debug:print-info 1 "read-config - file not found " path " current path: " (current-directory)) - (if (not ht)(make-hash-table) ht)) + ;; WARNING: This is a risky change but really, we should not return an empty hash table if no file read? + #f) ;; (if (not ht)(make-hash-table) ht)) (let ((inp (open-input-file path)) (res (if (not ht)(make-hash-table) ht))) (let loop ((inl (configf:read-line inp res allow-system)) ;; (read-line inp)) (curr-section-name (if curr-section curr-section "default")) (var-flag #f);; turn on for key-var-pr and cont-ln-rx, turn off elsewhere @@ -206,22 +208,26 @@ ((return-string) cmd) (else (val-proc))))) (loop (configf:read-line inp res allow-system) curr-section-name #f #f)) (loop (configf:read-line inp res allow-system) curr-section-name #f #f))) (configf:key-val-pr ( x key unk1 val unk2 ) (let* ((alist (hash-table-ref/default res curr-section-name '())) - (envar (and environ-patt (string-search (regexp environ-patt) curr-section-name))) - (realval (if envar - (config:eval-string-in-environment val) - val))) - (debug:print-info 6 "read-config env setting, envar: " envar " realval: " realval " val: " val " key: " key " curr-section-name: " curr-section-name) - (if envar - (begin - ;; (debug:print-info 4 "read-config key=" key ", val=" val ", realval=" realval) - (setenv key realval))) - (hash-table-set! res curr-section-name - (config:assoc-safe-add alist key realval)) - (loop (configf:read-line inp res allow-system) curr-section-name key #f))) + (envar (and environ-patt (string-search (regexp environ-patt) curr-section-name))) + (realval (if envar + (config:eval-string-in-environment val) + val))) + (debug:print-info 6 "read-config env setting, envar: " envar " realval: " realval " val: " val " key: " key " curr-section-name: " curr-section-name) + (if envar + (begin + ;; (debug:print-info 4 "read-config key=" key ", val=" val ", realval=" realval) + (setenv key realval))) + (hash-table-set! res curr-section-name + (config:assoc-safe-add alist key realval)) + (loop (configf:read-line inp res allow-system) curr-section-name key #f))) + (configf:key-no-val ( x key val) (let* ((alist (hash-table-ref/default res curr-section-name '()))) + (hash-table-set! res curr-section-name + (config:assoc-safe-add alist key #t)) + (loop (configf:read-line inp res allow-system) curr-section-name key #f))) ;; if a continued line (configf:cont-ln-rx ( x whsp val ) (let ((alist (hash-table-ref/default res curr-section-name '()))) (if var-flag ;; if set to a string then we have a continued var (let ((newval (conc (config-lookup res curr-section-name var-flag) "\n" Index: dashboard-tests.scm ================================================================== --- dashboard-tests.scm +++ dashboard-tests.scm @@ -24,10 +24,11 @@ (declare (unit dashboard-tests)) (declare (uses common)) (declare (uses db)) (declare (uses gutils)) +(declare (uses ezsteps)) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") @@ -192,37 +193,39 @@ (let* ((state (db:test-get-state testdat)) (status (db:test-get-status testdat)) (color (car (gutils:get-color-for-state-status state status)))) ((vector-ref *state-status* 0) state color) ((vector-ref *state-status* 1) status color))) + +(define *dashboard-test-db* #t) ;;====================================================================== ;; Set fields ;;====================================================================== -(define (set-fields-panel test-id testdat) +(define (set-fields-panel test-id testdat #!key (db #f)) (let ((newcomment #f) (newstatus #f) (newstate #f)) (iup:frame #:title "Set fields" (iup:vbox (iup:hbox (iup:label "Comment:") (iup:textbox #:action (lambda (val a b) - (open-run-close db:test-set-state-status-by-id #f test-id #f #f b) + (open-run-close db:test-set-state-status-by-id db test-id #f #f b) (set! newcomment b)) #:value (db:test-get-comment testdat) #:expand "HORIZONTAL")) (apply iup:hbox (iup:label "STATE:" #:size "30x") (let* ((btns (map (lambda (state) (let ((btn (iup:button state #:expand "HORIZONTAL" #:size "50x" #:font "Courier New, -10" #:action (lambda (x) - (open-run-close db:test-set-state-status-by-id #f test-id state #f #f) + (open-run-close db:test-set-state-status-by-id db test-id state #f #f) (db:test-set-state! testdat state))))) btn)) - (list "COMPLETED" "NOT_STARTED" "RUNNING" "REMOTEHOSTSTART" "KILLED" "KILLREQ")))) + *common:std-states*))) ;; (list "COMPLETED" "NOT_STARTED" "RUNNING" "REMOTEHOSTSTART" "LAUNCHED" "KILLED" "KILLREQ")))) (vector-set! *state-status* 0 (lambda (state color) (for-each (lambda (btn) (let* ((name (iup:attribute btn "TITLE")) @@ -235,14 +238,14 @@ (iup:label "STATUS:" #:size "30x") (let* ((btns (map (lambda (status) (let ((btn (iup:button status #:expand "HORIZONTAL" #:size "50x" #:font "Courier New, -10" #:action (lambda (x) - (open-run-close db:test-set-state-status-by-id #f test-id #f status #f) + (open-run-close db:test-set-state-status-by-id db test-id #f status #f) (db:test-set-status! testdat status))))) btn)) - (list "PASS" "WARN" "FAIL" "CHECK" "n/a" "WAIVED" "SKIP")))) + *common:std-statuses*))) ;; (list "PASS" "WARN" "FAIL" "CHECK" "n/a" "WAIVED" "SKIP")))) (vector-set! *state-status* 1 (lambda (status color) (for-each (lambda (btn) (let* ((name (iup:attribute btn "TITLE")) @@ -250,40 +253,74 @@ (if (not (colors-similar? newcolor (iup:attribute btn "BGCOLOR"))) (iup:attribute-set! btn "BGCOLOR" newcolor)))) btns))) btns)))))) +(define (dashboard-tests:run-html-viewer lfilename) + (let ((htmlviewercmd (configf:lookup *configdat* "setup" "htmlviewercmd"))) + (if htmlviewercmd + (system (conc "(" htmlviewercmd " " lfilename " ) &")) + (iup:send-url lfilename)))) + +(define (dashboard-tests:run-a-step info) + #t) + +(define (dashboard-tests:step-run-control testdat stepname testconfig) + (iup:dialog ;; #:close_cb (lambda (a)(exit)) ; #:expand "YES" + #:title stepname + (iup:vbox ; #:expand "YES" + (iup:label (conc "Step: " stepname "\nNB// These buttons only run the test step\nfor the purpose of debugging.\nNot all database updates are done.")) + (iup:button "Re-run" + #:expand "HORIZONTAL" + #:action (lambda (obj) + (thread-start! + (make-thread (lambda () + (ezsteps:run-from testdat stepname #t)) + (conc "ezstep run single step " stepname))))) + (iup:button "Re-run and continue" + #:expand "HORIZONTAL" + #:action (lambda (obj) + (thread-start! + (make-thread (lambda () + (ezsteps:run-from testdat stepname #f)) + (conc "ezstep run from step " stepname))))) + ;; (iup:button "Refresh test data" + ;; #:expand "HORIZONTAL" + ;; #:action (lambda (obj) + ;; (print "Refresh test data " stepname)) + ))) ;;====================================================================== ;; ;;====================================================================== (define (examine-test test-id) ;; run-id run-key origtest) - (let* ((testdat (open-run-close db:get-test-info-by-id #f test-id)) - (db-path (conc *toppath* "/megatest.db")) + (let* ((db-path (conc *toppath* "/megatest.db")) + (db (open-db)) + (testdat (open-run-close db:get-test-info-by-id db test-id)) (db-mod-time 0) ;; (file-modification-time db-path)) (last-update 0) ;; (current-seconds)) - (request-update #t) - (db #f)) + (request-update #t)) (if (not testdat) (begin - (debug:print 0 "ERROR: No test data found for test " test-id ", exiting") + (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 (open-run-close db:get-key-val-pairs #f run-id) #f)) - (rundat (if testdat (open-run-close db:get-run-info #f run-id) #f)) + (keydat (if testdat (open-run-close db:get-key-val-pairs db run-id) #f)) + (rundat (if testdat (open-run-close db:get-run-info db run-id) #f)) (runname (if testdat (db:get-value-by-header (db:get-row rundat) (db:get-header rundat) "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))) + (let ((tm (open-run-close db:testmeta-get-record db testname))) (if tm tm (make-db:testmeta))) (make-db:testmeta))) (keystring (string-intersperse (map (lambda (keyval) @@ -293,49 +330,71 @@ "/")) (item-path (db:test-get-item-path testdat)) (viewlog (lambda (x) (if (file-exists? logfile) ;(system (conc "firefox " logfile "&")) - (iup:send-url logfile) + (dashboard-tests:run-html-viewer logfile) (message-window (conc "File " logfile " not found"))))) - (view-a-log (lambda (lfile) + (view-a-log (lambda (lfile) (let ((lfilename (conc rundir "/" lfile))) ;; (print "lfilename: " lfilename) (if (file-exists? lfilename) ;(system (conc "firefox " logfile "&")) - (iup:send-url lfilename) + (dashboard-tests:run-html-viewer lfilename) (message-window (conc "File " lfilename " not found")))))) (xterm (lambda (x) (if (directory-exists? rundir) (let ((shell (if (get-environment-variable "SHELL") (conc "-e " (get-environment-variable "SHELL")) ""))) (system (conc "cd " rundir - ";xterm -T \"" (string-translate testfullname "()" " ") "\" " shell "&"))) + ";mt_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)) - (need-update (or (and (> curr-mod-time db-mod-time) - (> (current-seconds) (+ last-update 2))) ;; every two seconds if db touched + (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-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)) - (open-run-close db:get-test-info-by-id #f test-id ))))) + (open-run-close db:get-test-info-by-id db test-id ))))) (cond ((and need-update newtestdat) (set! testdat newtestdat) (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 ")) + (if (eq? curr-mod-time db-mod-time) ;; do only once if same + (set! db-mod-time (+ curr-mod-time 1)) + (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) @@ -385,11 +444,32 @@ command-text-box "VALUE" (conc "xterm -geometry 180x20 -e \"megatest -remove-runs -target " keystring " :runname " runname " -testpatt " (conc testname "/" (if (equal? item-path "") "%" item-path)) - " -v ;echo Press any key to continue;bash -c 'read -n 1 -s'\""))))) + " -v ;echo Press any key to continue;bash -c 'read -n 1 -s'\"")))) + (clean-run-execute (lambda (x) + (let ((cmd (conc "xterm -geometry 180x20 -e \"" + "megatest -remove-runs -target " keystring " :runname " runname + " -testpatt " (conc testname "/" (if (equal? item-path "") + "%" + item-path)) + ";megatest -target " keystring " :runname " runname + " -runtests " (conc testname "/" (if (equal? item-path "") + "%" + item-path)) + " ;echo Press any key to continue;bash -c 'read -n 1 -s'\""))) + (system (conc cmd " &"))))) + (remove-test (lambda (x) + (iup:attribute-set! + command-text-box "VALUE" + (conc "xterm -geometry 180x20 -e \"megatest -remove-runs -target " keystring " :runname " runname + " -testpatt " (conc testname "/" (if (equal? item-path "") + "%" + item-path)) + " -v ;echo Press any key to continue;bash -c 'read -n 1 -s'\"")) + ))) (cond ((not testdat)(begin (print "ERROR: bad test info for " test-id)(exit 1))) ((not rundat)(begin (print "ERROR: found test info but there is a problem with the run info for " run-id)(exit 1))) (else ;; (test-set-status! db run-id test-name state status itemdat) @@ -409,10 +489,11 @@ (iup:hbox (iup:button "View Log" #:action viewlog #:size "80x") (iup:button "Start Xterm" #:action xterm #:size "80x") (iup:button "Run Test" #:action run-test #:size "80x") (iup:button "Clean Test" #:action remove-test #:size "80x") + (iup:button "CleanRunExecute!" #:action clean-run-execute #:size "80x") (iup:button "Kill All Jobs" #:action kill-jobs #:size "80x") (iup:button "Close" #:action (lambda (x)(exit)) #:size "80x")) (apply iup:hbox (list command-text-box command-launch-button)))) @@ -430,13 +511,17 @@ #:numlin-visible 5 #:click-cb (lambda (obj lin col status) ;; (if (equal? col 6) (let* ((mtrx-rc (conc lin ":" 6)) (fname (iup:attribute obj mtrx-rc))) ;; col)))) - (view-a-log fname))) - ;; (print "obj: " obj " mtrx-rc: " mtrx-rc " fname: " fname " lin: " lin " col: " col " status: " status))) - ))) + (if (eq? col 6) + (view-a-log fname) + (iup:show + (dashboard-tests:step-run-control + testdat + (iup:attribute obj (conc lin ":" 1)) + teststeps)))))))) ;; (let loop ((count 0)) ;; (iup:attribute-set! steps-matrix "FITTOTEXT" (conc "L" count)) ;; (if (< count 30) ;; (loop (+ count 1)))) (iup:attribute-set! steps-matrix "0:1" "Step Name") @@ -450,23 +535,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 @@ -496,11 +603,11 @@ (db:test-data-get-tol x) (db:test-data-get-status x) (db:test-data-get-units x) (db:test-data-get-type x) (db:test-data-get-comment x))) - (open-run-close db:read-test-data #f test-id "%"))) + (open-run-close db:read-test-data db test-id "%"))) "\n"))) (if (not (equal? currval newval)) (iup:attribute-set! test-data "VALUE" newval ))))) ;; "TITLE" newval))))) test-data)) ;;(dashboard:run-controls) @@ -512,16 +619,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,15 +118,21 @@ (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 *all-item-test-names* '()) (define *num-tests* 15) (define *start-run-offset* 0) (define *start-test-offset* 0) (define *examine-test-dat* (make-hash-table)) (define *exit-started* #f) @@ -133,12 +139,32 @@ (define *status-ignore-hash* (make-hash-table)) (define *state-ignore-hash* (make-hash-table)) (define *db-file-path* (conc *toppath* "/megatest.db")) -(define *tests-sort-reverse* #f) +(define *tests-sort-options* (vector (vector "Sort +a" 'testname "ASC") + (vector "Sort -a" 'testname "DESC") + (vector "Sort +t" 'event_time "ASC") + (vector "Sort -t" 'event_time "DESC") + (vector "Sort +s" 'statestatus "ASC") + (vector "Sort -s" 'statestatus "DESC"))) + +;; Don't forget to adjust the >= below if you add to the sort-options above +(define (next-sort-option) + (if (>= *tests-sort-reverse* 5) + (set! *tests-sort-reverse* 0) + (set! *tests-sort-reverse* (+ *tests-sort-reverse* 1))) + *tests-sort-reverse*) + +(define (get-curr-sort) + (vector-ref *tests-sort-options* *tests-sort-reverse*)) + +(define *tests-sort-reverse* 3) (define *hide-empty-runs* #f) +(define *hide-not-hide* #t) ;; toggle for hide/not hide +(define *hide-not-hide-button* #f) +(define *hide-not-hide-tabs* #f) (define *current-tab-number* 0) (define *updaters* (make-hash-table)) (debug:setup) @@ -147,11 +173,10 @@ (define-inline (dboard:uidat-get-keycol vec)(vector-ref vec 0)) (define-inline (dboard:uidat-get-lftcol vec)(vector-ref vec 1)) (define-inline (dboard:uidat-get-header vec)(vector-ref vec 2)) (define-inline (dboard:uidat-get-runsvec vec)(vector-ref vec 3)) - (define (message-window msg) (iup:show (iup:dialog (iup:vbox @@ -170,12 +195,12 @@ i)) (define (pad-list l n)(append l (make-list (- n (length l))))) (define (colors-similar? color1 color2) - (let* ((c1 (map string->number (string-split color1))) - (c2 (map string->number (string-split color2))) + (let* ((c1 (map string->number (string-split color1))) + (c2 (map string->number (string-split color2))) (delta (map (lambda (a b)(abs (- a b))) c1 c2))) (null? (filter (lambda (x)(> x 3)) delta)))) ;; keypatts: ( (KEY1 "abc%def")(KEY2 "%") ) (define (update-rundat runnamepatt numruns testnamepatt keypatts) @@ -185,19 +210,29 @@ (header (db:get-header allruns)) (runs (db:get-rows allruns)) (result '()) (maxtests 0) (states (hash-table-keys *state-ignore-hash*)) - (statuses (hash-table-keys *status-ignore-hash*))) + (statuses (hash-table-keys *status-ignore-hash*)) + (sort-info (get-curr-sort)) + (sort-by (vector-ref sort-info 1)) + (sort-order (vector-ref sort-info 2)) + (bubble-type (if (member sort-order '(testname)) + 'testname + 'itempath))) ;; ;; trim runs to only those that are changing often here ;; (for-each (lambda (run) - (let* ((run-id (db:get-value-by-header run header "id")) - (tests (let ((tsts (mt:get-tests-for-run run-id testnamepatt states statuses))) - (if *tests-sort-reverse* (reverse tsts) tsts))) - (key-vals (cdb:remote-run db:get-key-vals #f run-id))) + (let* ((run-id (db:get-value-by-header run header "id")) + (tests (mt:get-tests-for-run run-id testnamepatt states statuses + not-in: *hide-not-hide* + sort-by: sort-by + sort-order: sort-order)) + ;; NOTE: bubble-up also sets the global *all-item-test-names* + ;; (tests (bubble-up tmptests priority: bubble-type)) + (key-vals (cdb:remote-run db:get-key-vals #f run-id))) ;; Not sure this is needed? (set! referenced-run-ids (cons run-id referenced-run-ids)) (if (> (length tests) maxtests) (set! maxtests (length tests))) (if (or (not *hide-empty-runs*) ;; this reduces the data burden when set @@ -244,36 +279,35 @@ (vector-set! res 1 (car (string-split (cadr splst) ")")))) res)) lst)) (define (collapse-rows inlst) - (let* ((newlst (filter (lambda (x) - (let* ((tparts (string-split x "(")) - (basetname (if (null? tparts) x (car tparts)))) + (let* ((sort-info (get-curr-sort)) + (sort-by (vector-ref sort-info 1)) + (sort-order (vector-ref sort-info 2)) + (bubble-type (if (member sort-order '(testname)) + 'testname + 'itempath)) + (newlst (filter (lambda (x) + (let* ((tparts (string-split x "(")) + (basetname (if (null? tparts) x (car tparts)))) ;(print "x " x " tparts: " tparts " basetname: " basetname) - (cond - ((string-match blank-line-rx x) #f) - ((equal? x basetname) #t) - ((hash-table-ref/default *collapsed* basetname #f) + (cond + ((string-match blank-line-rx x) #f) + ((equal? x basetname) #t) + ((hash-table-ref/default *collapsed* basetname #f) ;(print "Removing " basetname " from items") - #f) - (else #t)))) - inlst)) - (vlst (run-item-name->vectors newlst)) - ;; sort by second field - (vlst-s1 (sort vlst (lambda (a b) - (let ((astr (vector-ref a 1)) - (bstr (vector-ref b 1))) - (if (string=? astr "") #f #t))))) - ;; (>= (string-length (vector-ref a 1))(string-length (vector-ref b 1)))))) - (vlst-s2 (sort vlst-s1 (lambda (a b) - (string>= (vector-ref a 0)(vector-ref b 0)))))) + #f) + (else #t)))) + inlst)) + (vlst (run-item-name->vectors newlst)) + (vlst2 (bubble-up vlst priority: bubble-type))) (map (lambda (x) (if (equal? (vector-ref x 1) "") (vector-ref x 0) (conc (vector-ref x 0) "(" (vector-ref x 1) ")"))) - vlst-s2))) + vlst2))) (define (update-labels uidat) (let* ((rown 0) (keycol (dboard:uidat-get-keycol uidat)) (lftcol (dboard:uidat-get-lftcol uidat)) @@ -297,10 +331,66 @@ (iup:attribute-set! lbl "TITLE" munged-val))) (iup:attribute-set! lbl "FGCOLOR" (if (hash-table-ref/default *collapsed* newval #f) "0 112 112" "0 0 0")) (if (< i maxn) (loop (+ i 1))))))) +;; +(define (get-itemized-tests test-dats) + (let ((tnames '())) + (for-each (lambda (tdat) + (let ((tname (vector-ref tdat 0)) ;; (db:test-get-testname tdat)) + (ipath (vector-ref tdat 1))) ;; (db:test-get-item-path tdat))) + (if (not (equal? ipath "")) + (if (not (member tname tnames)) + (set! tnames (append tnames (list tname))))))) + test-dats))) + +;; Bubble up the top tests to above the items, collect the items underneath +;; all while preserving the sort order from the SQL query as best as possible. +;; +(define (bubble-up test-dats #!key (priority 'itempath)) + (if (null? test-dats) + test-dats + (begin + (let* ((tnames '()) ;; list of names used to reserve order + (tests (make-hash-table)) ;; hash of lists, used to build as we go + (itemized (get-itemized-tests test-dats))) + (for-each + (lambda (testdat) + (let* ((tname (vector-ref testdat 0)) ;; db:test-get-testname testdat)) + (ipath (vector-ref testdat 1))) ;; db:test-get-item-path testdat))) + ;; (seen (hash-table-ref/default tests tname #f))) + (if (not (member tname tnames)) + (if (or (and (eq? priority 'itempath) + (not (equal? ipath ""))) + (and (eq? priority 'testname) + (equal? ipath "")) + (not (member tname itemized))) + (set! tnames (append tnames (list tname))))) + (if (equal? ipath "") + ;; This a top level, prepend it + (hash-table-set! tests tname (cons testdat (hash-table-ref/default tests tname '()))) + ;; This is item, append it + (hash-table-set! tests tname (append (hash-table-ref/default tests tname '())(list testdat)))))) + test-dats) + ;; Set all tests with items + (set! *all-item-test-names* (append (if (null? tnames) + '() + (filter (lambda (tname) + (let ((tlst (hash-table-ref tests tname))) + (and (list tlst) + (> (length tlst) 1)))) + tnames)) + *all-item-test-names*)) + (let loop ((hed (car tnames)) + (tal (cdr tnames)) + (res '())) + (let ((newres (append res (hash-table-ref tests hed)))) + (if (null? tal) + newres + (loop (car tal)(cdr tal) newres)))))))) + (define (update-buttons uidat numruns numtests) (let* ((runs (if (> (length *allruns*) numruns) (take-right *allruns* numruns) (pad-list *allruns* numruns))) (lftcol (dboard:uidat-get-lftcol uidat)) @@ -392,14 +482,28 @@ (set! coln (+ coln 1)))) runs))) (define (mkstr . x) (string-intersperse (map conc x) ",")) + +(define (set-bg-on-filter) + (let ((search-changed (not (null? (filter (lambda (key) + (not (equal? (hash-table-ref *searchpatts* key) "%"))) + (hash-table-keys *searchpatts*))))) + (state-changed (not (null? (hash-table-keys *state-ignore-hash*)))) + (status-changed (not (null? (hash-table-keys *status-ignore-hash*))))) + (iup:attribute-set! *hide-not-hide-tabs* "BGCOLOR" + (if (or search-changed + state-changed + status-changed) + "190 180 190" + "190 190 190" + )))) (define (update-search x val) - ;; (print "Setting search for " x " to " val) - (hash-table-set! *searchpatts* x val)) + (hash-table-set! *searchpatts* x val) + (set-bg-on-filter)) (define (mark-for-update) (set! *last-db-update-time* 0) (set! *delayed-update* 1)) @@ -469,11 +573,11 @@ (lbs '())) (let* ((lb (let ((lb (list-ref key-listboxes indx))) (if lb lb (iup:listbox - ;; #:size "x10" + #:size "45x50" #:fontsize "10" #:expand "YES" ;; "VERTICAL" ;; #:dropdown "YES" #:editbox "YES" #:action (lambda (obj a b c) @@ -623,11 +727,12 @@ ;; A gui for launching tests ;; (define (dashboard:run-controls) (let* ((targets (make-hash-table)) (test-records (make-hash-table)) - (test-names (tests:get-valid-tests *toppath* '())) + (all-tests-registry (tests:get-all)) ;; (tests:get-valid-tests *toppath* '())) + (test-names (hash-table-keys all-tests-registry)) (sorted-testnames #f) (action "-runtests") (cmdln "") (runlogs (make-hash-table)) (key-listboxes #f) @@ -641,11 +746,11 @@ (dashboard:update-run-command)))) (tests-draw-state (make-hash-table)) ;; use for keeping state of the test canvas (test-patterns-textbox #f)) (hash-table-set! tests-draw-state 'first-time #t) (hash-table-set! tests-draw-state 'scalef 8) - (tests:get-full-data test-names test-records '()) + (tests:get-full-data test-names test-records '() all-tests-registry) (set! sorted-testnames (tests:sort-by-priority-and-waiton test-records)) ;; refer to *keys*, *dbkeys* for keys (iup:vbox ;; The command line display/exectution control @@ -743,10 +848,11 @@ (dboard:lines->test-patt b)) (dashboard:update-run-command)) #:value (dboard:test-patt->lines (dboard:data-get-test-patts *data*)) #:expand "YES" + #:size "x50" #:multiline "YES"))) (set! test-patterns-textbox tb) tb)) (iup:frame #:title "Target" @@ -761,19 +867,19 @@ ;; Text box for STATES (iup:frame #:title "States" (dashboard:text-list-toggle-box ;; Move these definitions to common and find the other useages and replace! - '("COMPLETED" "RUNNING" "STUCK" "INCOMPLETE" "LAUNCHED" "REMOTEHOSTSTART" "KILLED") + *common:std-states* ;; '("COMPLETED" "RUNNING" "STUCK" "INCOMPLETE" "LAUNCHED" "REMOTEHOSTSTART" "KILLED") (lambda (all) (dboard:data-set-states! *data* all) (dashboard:update-run-command)))) ;; Text box for STATES (iup:frame #:title "Statuses" (dashboard:text-list-toggle-box - '("PASS" "FAIL" "n/a" "CHECK" "WAIVED" "SKIP" "DELETED" "STUCK/DEAD") + *common:std-statuses* ;; '("PASS" "FAIL" "n/a" "CHECK" "WAIVED" "SKIP" "DELETED" "STUCK/DEAD") (lambda (all) (dboard:data-set-statuses! *data* all) (dashboard:update-run-command)))))))) (iup:frame @@ -794,11 +900,11 @@ ;; Following doesn't work ;; #:wheel-cb (make-canvas-action ;; (lambda (cnv xadj yadj) ;; ;; (print "cnv: " cnv " x: " x " y: " y) ;; (dashboard:draw-tests cnv xadj yadj tests-draw-state sorted-testnames))) - #:size "150x150" + ;; #:size "50x50" #:expand "YES" #:scrollbar "YES" #:posx "0.5" #:posy "0.5" #:button-cb (lambda (obj btn pressed x y status) @@ -936,11 +1042,15 @@ #:expand "YES")) (updater (lambda () (let* ((runs-dat (mt:get-runs-by-patt *keys* "%" #f)) (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records (run-id (dboard:data-get-curr-run-id *data*)) - (tests-dat (let ((tdat (mt:get-tests-for-run run-id "%" '() '() + (tests-dat (let ((tdat (mt:get-tests-for-run run-id + (hash-table-ref/default *searchpatts* "test-name" "%/%") + (hash-table-keys *state-ignore-hash*) ;; '() + (hash-table-keys *status-ignore-hash*) ;; '() + not-in: *hide-not-hide* qryvals: "id,testname,item_path,state,status"))) ;; get 'em all (sort tdat (lambda (a b) (let* ((aval (vector-ref a 2)) (bval (vector-ref b 2)) (anum (string->number aval)) @@ -978,23 +1088,24 @@ (let* ((run-record (hash-table-ref/default runs-hash run-id #f)) (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key)) *keys*)) (run-name (db:get-value-by-header run-record runs-header "runname")) (col-name (conc (string-intersperse key-vals "\n") "\n" run-name)) - (run-path (append key-vals (list run-name)))) - (hash-table-set! (dboard:data-get-run-keys *data*) run-id run-path) - ;; (iup:attribute-set! (dboard:data-get-runs-matrix *data*) - ;; (conc rownum ":" colnum) col-name) - ;; (hash-table-set! runid-to-col run-id (list colnum run-record)) - ;; Here we update the tests treebox and tree keys - (tree:add-node tb "Runs" (append key-vals (list run-name)) - userdata: (conc "run-id: " run-id)) - (let ((path ;;(string-intersperse "/" - (append key-vals (list run-name)))) - (hash-table-set! (dboard:data-get-path-run-ids *data*) path run-id)) - ;; (set! colnum (+ colnum 1)) - )) + (run-path (append key-vals (list run-name))) + (existing (tree:find-node tb run-path))) + (if (not (hash-table-ref/default (dboard:data-get-path-run-ids *data*) run-path #f)) + (begin + (hash-table-set! (dboard:data-get-run-keys *data*) run-id run-path) + ;; (iup:attribute-set! (dboard:data-get-runs-matrix *data*) + ;; (conc rownum ":" colnum) col-name) + ;; (hash-table-set! runid-to-col run-id (list colnum run-record)) + ;; Here we update the tests treebox and tree keys + (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name)) + userdata: (conc "run-id: " run-id)) + (hash-table-set! (dboard:data-get-path-run-ids *data*) run-path run-id) + ;; (set! colnum (+ colnum 1)) + )))) run-ids) (iup:attribute-set! run-matrix "CLEARVALUE" "CONTENTS") (iup:attribute-set! run-matrix "CLEARATTRIB" "CONTENTS") (iup:attribute-set! run-matrix "NUMCOL" max-col ) (iup:attribute-set! run-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20 @@ -1083,59 +1194,77 @@ ;; (mark-for-update) ;; (update-search "item-name" val)) )) (iup:vbox (iup:hbox - (iup:button "Sort" #:action (lambda (obj) - (set! *tests-sort-reverse* (not *tests-sort-reverse*)) - (iup:attribute-set! obj "TITLE" (if *tests-sort-reverse* "+Sort" "-Sort")) - (mark-for-update))) + (iup:button "Sort -t" #:action (lambda (obj) + (next-sort-option) + (iup:attribute-set! obj "TITLE" (vector-ref (vector-ref *tests-sort-options* *tests-sort-reverse*) 0)) + (mark-for-update))) (iup:button "HideEmpty" #:action (lambda (obj) (set! *hide-empty-runs* (not *hide-empty-runs*)) - (iup:attribute-set! obj "TITLE" (if *hide-empty-runs* "+Hide" "-Hide")) + (iup:attribute-set! obj "TITLE" (if *hide-empty-runs* "+HideE" "-HideE")) (mark-for-update))) - (iup:button "Refresh" #:action (lambda (obj) - (mark-for-update)))) + (let ((hideit (iup:button "HideTests" #:action (lambda (obj) + (set! *hide-not-hide* (not *hide-not-hide*)) + (iup:attribute-set! obj "TITLE" (if *hide-not-hide* "HideTests" "NotHide")) + (mark-for-update))))) + (set! *hide-not-hide-button* hideit) + hideit)) (iup:hbox - (iup:button "Quit" #:action (lambda (obj)(if *db* (sqlite3:finalize! *db*))(exit))) - (iup:button "Monitor" #:action (lambda (obj)(system (conc (car (argv))" -guimonitor &"))))) - )) - ;; (iup:button "<- Left" #:action (lambda (obj)(set! *start-run-offset* (+ *start-run-offset* 1)))) - ;; (iup:button "Up ^" #:action (lambda (obj)(set! *start-test-offset* (if (> *start-test-offset* 0)(- *start-test-offset* 1) 0)))) - ;; (iup:button "Down v" #:action (lambda (obj)(set! *start-test-offset* (if (>= *start-test-offset* (length *alltestnamelst*))(length *alltestnamelst*)(+ *start-test-offset* 1))))) - ;; (iup:button "Right ->" #:action (lambda (obj)(set! *start-run-offset* (if (> *start-run-offset* 0)(- *start-run-offset* 1) 0)))) + (iup:button "Quit" #:action (lambda (obj)(if *db* (sqlite3:finalize! *db*))(exit))) + (iup:button "Refresh" #:action (lambda (obj) + (mark-for-update))) + (iup:button "Collapse" #:action (lambda (obj) + (let ((myname (iup:attribute obj "TITLE"))) + (if (equal? myname "Collapse") + (begin + (for-each (lambda (tname) + (hash-table-set! *collapsed* tname #t)) + *all-item-test-names*) + (iup:attribute-set! obj "TITLE" "Expand")) + (begin + (for-each (lambda (tname) + (hash-table-delete! *collapsed* tname)) + (hash-table-keys *collapsed*)) + (iup:attribute-set! obj "TITLE" "Collapse")))) + (mark-for-update)))))) (iup:frame - #:title "hide" + #:title "state/status filter" (iup:vbox (apply iup:hbox (map (lambda (status) (iup:toggle status #:action (lambda (obj val) (mark-for-update) (if (eq? val 1) (hash-table-set! *status-ignore-hash* status #t) - (hash-table-delete! *status-ignore-hash* status))))) - '("PASS" "FAIL" "WARN" "CHECK" "WAIVED" "STUCK/DEAD" "n/a" "SKIP"))) + (hash-table-delete! *status-ignore-hash* status)) + (set-bg-on-filter)))) + *common:std-statuses*)) ;; '("PASS" "FAIL" "WARN" "CHECK" "WAIVED" "STUCK/DEAD" "n/a" "SKIP"))) (apply iup:hbox (map (lambda (state) (iup:toggle state #:action (lambda (obj val) (mark-for-update) (if (eq? val 1) (hash-table-set! *state-ignore-hash* state #t) - (hash-table-delete! *state-ignore-hash* state))))) - '("RUNNING" "COMPLETED" "INCOMPLETE" "LAUNCHED" "NOT_STARTED" "KILLED" "DELETED"))) + (hash-table-delete! *state-ignore-hash* state)) + (set-bg-on-filter)))) + *common:std-states*)) ;; '("RUNNING" "COMPLETED" "INCOMPLETE" "LAUNCHED" "NOT_STARTED" "KILLED" "DELETED"))) (iup:valuator #:valuechanged_cb (lambda (obj) (let ((val (inexact->exact (round (/ (string->number (iup:attribute obj "VALUE")) 10)))) (oldmax (string->number (iup:attribute obj "MAX"))) (maxruns *tot-run-count*)) (set! *start-run-offset* val) (mark-for-update) (debug:print 6 "*start-run-offset* " *start-run-offset* " maxruns: " maxruns ", val: " val " oldmax: " oldmax) (iup:attribute-set! obj "MAX" (* maxruns 10)))) - #:expand "YES" - #:max (* 10 (length *allruns*))))) + #:expand "HORIZONTAL" + #:max (* 10 (length *allruns*)) + #:min 0 + #:step 0.01))) ;(iup:button "inc rows" #:action (lambda (obj)(set! *num-tests* (+ *num-tests* 1)))) ;(iup:button "dec rows" #:action (lambda (obj)(set! *num-tests* (if (> *num-tests* 0)(- *num-tests* 1) 0)))) ) ) @@ -1168,11 +1297,13 @@ (debug:print 6 "*start-test-offset* " *start-test-offset* " val: " val " newmax: " newmax " oldmax: " oldmax) (if (< val 10) (iup:attribute-set! obj "MAX" newmax)) )) #:expand "VERTICAL" - #:orientation "VERTICAL") + #:orientation "VERTICAL" + #:min 0 + #:step 0.01) (apply iup:vbox (reverse res))))))) (else (let ((labl (iup:button "" #:flat "YES" #:alignment "ALEFT" @@ -1254,10 +1385,12 @@ ;; (set! (iup:callback tabs tabchange-cb:) (lambda (a b c)(print "SWITCHED TO TAB: " a " " b " " c))) (iup:attribute-set! tabs "TABTITLE0" "Summary") (iup:attribute-set! tabs "TABTITLE1" "Runs") (iup:attribute-set! tabs "TABTITLE2" "Run Summary") (iup:attribute-set! tabs "TABTITLE3" "Run Control") + (iup:attribute-set! tabs "BGCOLOR" "190 190 190") + (set! *hide-not-hide-tabs* tabs) tabs))) (vector keycol lftcol header runsvec))) (if (or (args:get-arg "-rows") (get-environment-variable "DASHBOARDROWS" )) @@ -1273,24 +1406,30 @@ (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) + +;; Force creation of the db in case it isn't already there. +(let ((db (tasks:open-db))) + (sqlite3:finalize! db)) (define (dashboard:run-update x) (let* ((modtime (file-modification-time *db-file-path*)) (monitor-modtime (file-modification-time *monitor-db-path*)) (run-update-time (current-seconds)) @@ -1322,18 +1461,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") @@ -1347,21 +1487,33 @@ (begin (print "ERROR: runid is not a number " (args:get-arg "-run")) (exit 1))))) ((args:get-arg "-test") (let ((testid (string->number (args:get-arg "-test")))) - (if testid + (if (and (number? testid) + (>= testid 0)) (examine-test testid) (begin - (print "ERROR: testid is not a number " (args:get-arg "-test")) + (debug:print 3 "INFO: tried to open test with invalid test-id. " (args:get-arg "-test")) (exit 1))))) ((args:get-arg "-guimonitor") (gui-monitor *db*)) (else (set! uidat (make-dashboard-buttons *num-runs* *num-tests* *dbkeys*)) (iup:callback-set! *tim* "ACTION_CB" (lambda (x) - (dashboard:run-update 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 @@ -259,13 +259,13 @@ (string->number (args:get-arg "-override-timeout")) 136000)))) (handle-exceptions exn (begin - (debug:print 0 "ERROR: problem accessing test db " work-area ", you probably should clean and re-run this test" + (debug:print 2 "ERROR: problem accessing test db " work-area ", you probably should clean and re-run this test" ((condition-property-accessor 'exn 'message) exn)) - #f) + (set! db (sqlite3:open-database ":memory:"))) ;; open an in-memory db to allow readonly access (set! db (sqlite3:open-database dbpath))) (sqlite3:set-busy-handler! db handler) (if (not dbexists) (begin (sqlite3:execute db "PRAGMA synchronous = FULL;") @@ -359,19 +359,23 @@ (sqlite3:execute db "CREATE TABLE IF NOT EXISTS log (id INTEGER PRIMARY KEY,event_time TIMESTAMP DEFAULT (strftime('%s','now')),logline TEXT,pwd TEXT,cmdline TEXT,pid INTEGER);") (sqlite3:execute db (conc "PRAGMA synchronous = 0;")))) db)) (define (db:log-local-event . loglst) - (let ((logline (apply conc loglst)) - (pwd (current-directory)) - (cmdline (string-intersperse (argv) " ")) - (pid (current-process-id))) - (db:log-event logline pwd cmdline pid))) + (let ((logline (apply conc loglst))) + ;; (pwd (current-directory)) + ;; (cmdline (string-intersperse (argv) " ")) + ;; (pid (current-process-id))) + (db:log-event logline))) -(define (db:log-event logline pwd cmdline pid) +(define (db:log-event logline) (let ((db (open-logging-db))) - (sqlite3:execute db "INSERT INTO log (logline,pwd,cmdline,pid) VALUES (?,?,?,?);" logline (current-directory)(string-intersperse (argv) " ")(current-process-id)) + (sqlite3:execute db "INSERT INTO log (logline,pwd,cmdline,pid) VALUES (?,?,?,?);" + logline + (current-directory) + (string-intersperse (argv) " ") + (current-process-id)) (sqlite3:finalize! db) logline)) ;;====================================================================== ;; TODO: @@ -455,10 +459,55 @@ ((< mver 1.37) (db:set-var db "MEGATEST_VERSION" 1.37) (sqlite3:execute db "ALTER TABLE tests ADD COLUMN archived INTEGER DEFAULT 0;")) ((< mver megatest-version) (db:set-var db "MEGATEST_VERSION" megatest-version)))))) + +;; Clean out old junk and vacuum the database +;; +;; Ultimately do something like this: +;; +;; 1. Look at test records either deleted or part of deleted run: +;; a. If test dir exists, set the the test to state='UNKNOWN', Set the run to 'unknown' +;; b. If test dir gone, delete the test record +;; 2. Look at run records +;; a. If have tests that are not deleted, set state='unknown' +;; b. .... +;; +(define (db:clean-up db) + (let ((count-stmt (sqlite3:prepare db "SELECT (SELECT count(id) FROM tests)+(SELECT count(id) FROM runs);")) + (statements + (map (lambda (stmt) + (sqlite3:prepare db stmt)) + (list + ;; delete all tests that belong to runs that are 'deleted' + "DELETE FROM tests WHERE run_id in (SELECT id FROM runs WHERE state='deleted');" + ;; delete all tests that are 'DELETED' + "DELETE FROM tests WHERE state='DELETED';" + ;; delete all tests that have no run + "DELETE FROM tests WHERE run_id NOT IN (SELECT DISTINCT id FROM runs);" + ;; delete all runs that are state='deleted' + "DELETE FROM runs WHERE state='deleted';" + ;; delete empty runs + "DELETE FROM runs WHERE id NOT IN (SELECT DISTINCT r.id FROM runs AS r INNER JOIN tests AS t ON t.run_id=r.id);" + )))) + (sqlite3:with-transaction + db + (lambda () + (sqlite3:for-each-row (lambda (tot) + (debug:print-info 0 "Records count before clean: " tot)) + count-stmt) + (map sqlite3:execute statements) + (sqlite3:for-each-row (lambda (tot) + (debug:print-info 0 "Records count after clean: " tot)) + count-stmt))) + (map sqlite3:finalize! statements) + (sqlite3:finalize! count-stmt) + (sqlite3:execute db "VACUUM;"))) + +;; (define (db:report-junk-records db) + ;;====================================================================== ;; meta get and set vars ;;====================================================================== @@ -589,18 +638,18 @@ (if (and runname (null? (filter (lambda (x)(not x)) keyvals))) ;; 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=?,event_time=strftime('%s','now') WHERE id=?;" state status res) + (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=?,event_time=strftime('%s','now') WHERE id=? AND state='deleted';" state status res) res) (begin (debug:print 0 "ERROR: Called without all necessary keys") #f)))) @@ -691,11 +740,11 @@ (let* ((stateparts (string-split state "|")) (newstate (conc (car stateparts) "\n" (cadr stateparts)))) (hash-table-set! totals newstate (+ (hash-table-ref/default totals newstate 0) count)) (set! res (cons (list runname newstate count) res)))) db - "SELECT runname,t.state||'|'||t.status AS s,count(t.id) FROM runs AS r INNER JOIN tests AS t ON r.id=t.run_id GROUP BY s,runname ORDER BY r.event_time,s DESC;" ) + "SELECT runname,t.state||'|'||t.status AS s,count(t.id) FROM runs AS r INNER JOIN tests AS t ON r.id=t.run_id GROUP BY s,runname ORDER BY r.event_time,s DESC;" ) ;; (set! res (reverse res)) (for-each (lambda (state) (set! res (cons (list "Totals" state (hash-table-ref totals state)) res))) (sort (hash-table-keys totals) string>=)) res)) @@ -705,11 +754,11 @@ ;; register a test run with the db ;; ;; Use: (db-get-value-by-header (db:get-header runinfo)(db:get-row runinfo)) ;; to extract info from the structure returned ;; -(define (db:get-runs-by-patt db keys runnamepatt targpatt) ;; test-name) +(define (db:get-runs-by-patt db 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 '()) (key-patt "") @@ -725,11 +774,14 @@ (set! key-patt (conc key-patt " AND " key " " wildtype " '" patt "'")) (begin (debug:print 0 "ERROR: searching for runs with no pattern set for " fulkey) (exit 6))))) keyvals) - (set! qry-str (conc "SELECT " keystr " FROM runs WHERE state != 'deleted' AND runname " runwildtype " ? " key-patt " ORDER BY event_time;")) + (set! qry-str (conc "SELECT " keystr " FROM runs WHERE state != 'deleted' AND runname " runwildtype " ? " key-patt " ORDER BY event_time" + (if limit (conc " LIMIT " limit) "") + (if offset (conc " OFFSET " offset) "") + ";")) (debug:print-info 4 "runs:get-runs-by-patt qry=" qry-str " " runnamepatt) (sqlite3:for-each-row (lambda (a . r) (set! res (cons (list->vector (cons a r)) res))) db @@ -739,40 +791,46 @@ ;; use (get-value-by-header (db:get-header runinfo)(db:get-row runinfo)) (define (db:get-run-info db run-id) ;;(if (hash-table-ref/default *run-info-cache* run-id #f) ;; (hash-table-ref *run-info-cache* run-id) - (let* ((res #f) - (keys (db:get-keys db)) - (remfields (list "id" "runname" "state" "status" "owner" "event_time")) - (header (append keys remfields)) - (keystr (conc (keys->keystr keys) "," - (string-intersperse remfields ",")))) - (debug:print-info 11 "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr) - (sqlite3:for-each-row - (lambda (a . x) - (set! res (apply vector a x))) - db - (conc "SELECT " keystr " FROM runs WHERE id=? AND state != 'deleted';") - run-id) - (debug:print-info 11 "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr) - (let ((finalres (vector header res))) - ;; (hash-table-set! *run-info-cache* run-id finalres) - finalres))) + (let* ((res #f) + (keys (db:get-keys db)) + (remfields (list "id" "runname" "state" "status" "owner" "event_time")) + (header (append keys remfields)) + (keystr (conc (keys->keystr keys) "," + (string-intersperse remfields ",")))) + (debug:print-info 11 "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr) + (sqlite3:for-each-row + (lambda (a . x) + (set! res (apply vector a x))) + db + (conc "SELECT " keystr " FROM runs WHERE id=? AND state != 'deleted';") + run-id) + (debug:print-info 11 "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr) + (let ((finalres (vector header res))) + ;; (hash-table-set! *run-info-cache* run-id finalres) + finalres))) (define (db:set-comment-for-run db run-id comment) (debug:print-info 11 "db:set-comment-for-run START run-id: " run-id " comment: " comment) (sqlite3:execute db "UPDATE runs SET comment=? WHERE id=?;" comment run-id) (debug:print-info 11 "db:set-comment-for-run END run-id: " run-id " comment: " comment)) ;; does not (obviously!) removed dependent data. But why not!!? (define (db:delete-run db run-id) (common:clear-caches) ;; don't trust caches after doing any deletion - (sqlite3:execute db "UPDATE runs SET state='deleted' WHERE id=?;" run-id)) + ;; First set any related tests to DELETED + (let ((stmt1 (sqlite3:prepare db "UPDATE tests SET state='DELETED',comment='' WHERE run_id=?;")) + (stmt2 (sqlite3:prepare db "UPDATE runs SET state='deleted',comment='' WHERE id=?;"))) + (sqlite3:with-transaction + db (lambda () + (sqlite3:execute stmt1 run-id) + (sqlite3:execute stmt2 run-id))) + (sqlite3:finalize! stmt1) + (sqlite3:finalize! stmt2))) ;; (sqlite3:execute db "DELETE FROM runs WHERE id=?;" run-id)) - - (define (db:update-run-event_time db run-id) (debug:print-info 11 "db:update-run-event_time START run-id: " run-id) (sqlite3:execute db "UPDATE runs SET event_time=strftime('%s','now') WHERE id=?;" run-id) (debug:print-info 11 "db:update-run-event_time END run-id: " run-id)) @@ -809,37 +867,37 @@ (debug:print-info 11 "db:get-key-val-pairs END keys: " keys " run-id: " run-id) (reverse res))) ;; get key vals for a given run-id (define (db:get-key-vals db run-id) - (let ((mykeyvals (hash-table-ref/default *keyvals* run-id #f))) + (let ((mykeyvals (hash-table-ref/default *keyvals* run-id #f))) (if mykeyvals mykeyvals - (let* ((keys (db:get-keys db)) - (res '())) - (debug:print-info 11 "db:get-key-vals START keys: " keys " run-id: " run-id) - (for-each - (lambda (key) - (let ((qry (conc "SELECT " key " FROM runs WHERE id=?;"))) - ;; (debug:print 0 "qry: " qry) - (sqlite3:for-each-row - (lambda (key-val) - (set! res (cons key-val res))) - db qry run-id))) - keys) - (debug:print-info 11 "db:get-key-vals END keys: " keys " run-id: " run-id) + (let* ((keys (db:get-keys db)) + (res '())) + (debug:print-info 11 "db:get-key-vals START keys: " keys " run-id: " run-id) + (for-each + (lambda (key) + (let ((qry (conc "SELECT " key " FROM runs WHERE id=?;"))) + ;; (debug:print 0 "qry: " qry) + (sqlite3:for-each-row + (lambda (key-val) + (set! res (cons key-val res))) + db qry run-id))) + keys) + (debug:print-info 11 "db:get-key-vals END keys: " keys " run-id: " run-id) (let ((final-res (reverse res))) (hash-table-set! *keyvals* run-id final-res) final-res))))) ;; The target is keyval1/keyval2..., cached in *target* as it is used often (define (db:get-target db run-id) (let ((mytarg (hash-table-ref/default *target* run-id #f))) (if mytarg mytarg - (let* ((keyvals (db:get-key-vals db run-id)) - (thekey (string-intersperse (map (lambda (x)(if x x "-na-")) keyvals) "/"))) + (let* ((keyvals (db:get-key-vals db run-id)) + (thekey (string-intersperse (map (lambda (x)(if x x "-na-")) keyvals) "/"))) (hash-table-set! *target* run-id thekey) thekey)))) ;;====================================================================== ;; T E S T S @@ -847,15 +905,14 @@ ;; states and statuses are lists, turn them into ("PASS","FAIL"...) and use NOT IN ;; i.e. these lists define what to NOT show. ;; states and statuses are required to be lists, empty is ok ;; not-in #t = above behaviour, #f = must match -(define (db:get-tests-for-run db run-id testpatt states statuses offset limit not-in sort-by +(define (db:get-tests-for-run db run-id testpatt states statuses offset limit not-in sort-by sort-order #!key (qryvals #f) ) - (debug:print-info 11 "db:get-tests-for-run START run-id=" run-id ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) (let* ((qryvals (if qryvals qryvals "id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment")) (res '()) ;; if states or statuses are null then assume match all when not-in is false (states-qry (if (null? states) #f @@ -872,42 +929,44 @@ " NOT IN ('" " IN ('") (string-intersperse statuses "','") "')"))) (states-statuses-qry - (cond - ((and states-qry statuses-qry) - (conc " AND ( " states-qry " AND " statuses-qry " ) ")) - (states-qry - (conc " AND " states-qry)) - (statuses-qry - (conc " AND " statuses-qry)) - (else ""))) + (cond + ((and states-qry statuses-qry) + (conc " AND ( " states-qry " AND " statuses-qry " ) ")) + (states-qry + (conc " AND " states-qry)) + (statuses-qry + (conc " AND " statuses-qry)) + (else ""))) (tests-match-qry (tests:match->sqlqry testpatt)) (qry (conc "SELECT " qryvals " FROM tests WHERE run_id=? AND state != 'DELETED' " states-statuses-qry (if tests-match-qry (conc " AND (" tests-match-qry ") ") "") (case sort-by - ((rundir) " ORDER BY length(rundir) DESC ") - ((event_time) " ORDER BY event_time ASC ") - (else (if (string? sort-by) - (conc " ORDER BY " sort-by) - ""))) + ((rundir) " ORDER BY length(rundir) ") + ((testname) (conc " ORDER BY testname " (if sort-order (conc sort-order ",") "") " item_path ")) + ((statestatus) (conc " ORDER BY state " (if sort-order (conc sort-order ",") "") " status ")) + ((event_time) " ORDER BY event_time ") + (else (if (string? sort-by) + (conc " ORDER BY " sort-by) + ""))) + (if sort-order sort-order "") (if limit (conc " LIMIT " limit) "") (if offset (conc " OFFSET " offset) "") ";" - ))) + ))) (debug:print-info 8 "db:get-tests-for-run qry=" qry) (sqlite3:for-each-row (lambda (a . b) ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration final-logf comment) (set! res (cons (apply vector a b) res))) ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration final-logf comment) res))) db qry run-id ) - (debug:print-info 11 "db:get-tests-for-run START run-id=" run-id ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) res)) ;; get a useful subset of the tests data (used in dashboard ;; use db:mintests-get-{id ,run_id,testname ...} (define (db:get-tests-for-runs-mindata db run-ids testpatt states status not-in) @@ -919,14 +978,13 @@ ;; i.e. these lists define what to NOT show. ;; states and statuses are required to be lists, empty is ok ;; not-in #t = above behaviour, #f = must match ;; run-ids is a list of run-ids or a single number or #f for all runs (define (db:get-tests-for-runs db run-ids testpatt states statuses - #!key (not-in #t) - (sort-by #f) - (qryvals "id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment")) ;; 'rundir 'event_time - (debug:print-info 11 "db:get-tests-for-run START run-ids=" run-ids ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) + #!key (not-in #t) + (sort-by #f) + (qryvals "id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment")) ;; 'rundir 'event_time (let* ((res '()) ;; if states or statuses are null then assume match all when not-in is false (states-qry (if (null? states) #f (conc " state " @@ -954,19 +1012,18 @@ (if tests-match-qry (conc " AND (" tests-match-qry ") ") "") (case sort-by ((rundir) " ORDER BY length(rundir) DESC;") ((event_time) " ORDER BY event_time ASC;") (else ";")) - ))) - (debug:print-info 8 "db:get-tests-for-run qry=" qry) + ))) + (debug:print-info 8 "db:get-tests-for-runs qry=" qry) (sqlite3:for-each-row (lambda (a . b) ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration final-logf comment) (set! res (cons (apply vector a b) res))) ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration final-logf comment) res))) db qry ) - (debug:print-info 11 "db:get-tests-for-run START run-ids=" run-ids ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) res)) ;; this one is a bit broken BUG FIXME (define (db:delete-test-step-records db test-id #!key (work-area #f)) ;; Breaking it into two queries for better file access interleaving @@ -990,11 +1047,11 @@ (begin (sqlite3:execute db "DELETE FROM test_steps WHERE test_id=?;" test-id) (sqlite3:execute db "DELETE FROM test_data WHERE test_id=?;" test-id) (if force (sqlite3:execute db "DELETE FROM tests WHERE id=?;" test-id) - (sqlite3:execute db "UPDATE tests SET state='DELETED',status='n/a' WHERE id=?;" test-id))))) + (sqlite3:execute db "UPDATE tests SET state='DELETED',status='n/a',comment='' WHERE id=?;" test-id))))) (define (db:delete-tests-for-run db run-id) (common:clear-caches) (sqlite3:execute db "DELETE FROM tests WHERE run_id=?;" run-id)) @@ -1047,27 +1104,31 @@ (define (cdb:tests-update-run-duration serverdat test-id minutes) (cdb:client-call serverdat 'update-run-duration #t *default-numtries* minutes test-id)) (define (cdb:tests-update-uname-host serverdat test-id uname hostname) - (cdb:client-call serverdat 'update-uname-host #t *default-numtries* test-id uname hostname)) + (cdb:client-call serverdat 'update-uname-host #t *default-numtries* uname hostname test-id)) ;; speed up for common cases with a little logic +;; NB// Ultimately this will be deprecated in deference to mt:test-set-state-status-by-id +;; (define (db:test-set-state-status-by-id db test-id newstate newstatus newcomment) (cond ((and newstate newstatus newcomment) (sqlite3:execute db "UPDATE tests SET state=?,status=?,comment=? WHERE id=?;" newstate newstatus newcomment test-id)) ((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 test-id))))) + (if newcomment (sqlite3:execute db "UPDATE tests SET comment=? WHERE id=?;" newcomment test-id)))) + (mt:process-triggers test-id newstate newstatus)) -(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)) +;; Never used +;; (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)) (define (db:get-count-tests-running db) (let ((res 0)) (sqlite3:for-each-row (lambda (count) @@ -1092,11 +1153,11 @@ (sqlite3:for-each-row (lambda (count) (set! res count)) db "SELECT count(id) FROM tests WHERE state = 'RUNNING' OR state = 'LAUNCHED' OR state = 'REMOTEHOSTSTART' - AND testname in (SELECT testname FROM test_meta WHERE jobgroup=?;" + AND testname in (SELECT testname FROM test_meta WHERE jobgroup=?);" jobgroup) res))) ;; done with run when: ;; 0 tests in LAUNCHED, NOT_STARTED, REMOTEHOSTSTART, RUNNING @@ -1221,11 +1282,11 @@ (define (db:get-test-info db run-id testname item-path) (db:get-test-info-by-id db (db:get-test-id db run-id testname item-path))) (define (db:test-set-comment db test-id comment) (sqlite3:execute - db + db "UPDATE tests SET comment=? WHERE id=?;" comment test-id)) (define (cdb:test-set-rundir! serverdat run-id test-name item-path rundir) (cdb:client-call serverdat 'test-set-rundir #t *default-numtries* rundir run-id test-name item-path)) @@ -1259,11 +1320,11 @@ ;; BUG: Move the values derived from args to parameters and push to megatest.scm (let* ((testpatt (if (args:get-arg "-testpatt")(args:get-arg "-testpatt") "%")) (statepatt (if (args:get-arg ":state") (args:get-arg ":state") "%")) (statuspatt (if (args:get-arg ":status") (args:get-arg ":status") "%")) (runname (if (args:get-arg ":runname") (args:get-arg ":runname") "%")) - (paths-from-db (cdb:remote-run db:test-get-paths-matching-keynames-target db keynames target res + (paths-from-db (cdb:remote-run db:test-get-paths-matching-keynames-target-new db keynames target res testpatt: testpatt statepatt: statepatt statuspatt: statuspatt runname: runname))) (if fnamepatt @@ -1290,17 +1351,46 @@ (testqry (tests:match->sqlqry testpatt)) (qrystr (conc "SELECT t.rundir FROM tests AS t INNER JOIN runs AS r ON t.run_id=r.id WHERE " keystr " AND r.runname LIKE '" runname "' AND " testqry " AND t.state LIKE '" statepatt "' AND t.status LIKE '" statuspatt "' ORDER BY t.event_time ASC;"))) - (debug:print 3 "qrystr: " qrystr) (sqlite3:for-each-row (lambda (p) (set! res (cons p res))) db qrystr) res)) + +(define (db:test-get-paths-matching-keynames-target-new db keynames target res + #!key + (testpatt "%") + (statepatt "%") + (statuspatt "%") + (runname "%")) + (let* ((row-ids '()) + (keystr (string-intersperse + (map (lambda (key val) + (conc key " like '" val "'")) + keynames + (string-split target "/")) + " AND ")) + (testqry (tests:match->sqlqry testpatt)) + (runsqry (sqlite3:prepare db (conc "SELECT id FROM runs WHERE " keystr " AND runname LIKE '" runname "';"))) + (tstsqry (sqlite3:prepare db (conc "SELECT rundir FROM tests WHERE run_id=? AND " testqry " AND state LIKE '" statepatt "' AND status LIKE '" statuspatt "' ORDER BY event_time ASC;")))) + (sqlite3:for-each-row + (lambda (rid) + (set! row-ids (cons rid row-ids))) + runsqry) + (for-each (lambda (rid) + (sqlite3:for-each-row + (lambda (p) + (set! res (cons p res))) + tstsqry rid)) + row-ids) + (sqlite3:finalize! tstsqry) + (sqlite3:finalize! runsqry) + res)) ;; look through tests from matching runs for a file (define (db:test-get-first-path-matching db keynames target fname) ;; [refpaths] is the section where references to other megatest databases are stored (let ((mt-paths (configf:get-section "refpaths")) @@ -1336,26 +1426,28 @@ ((zmq)(with-output-to-string (lambda ()(serialize obj)))) (else obj))) (define (db:string->obj msg) (case *transport-type* - ((fs) msg) - ((http) - (with-input-from-string - (base64:base64-decode - (string-substitute - (regexp "_") "=" msg #t)) - (lambda ()(deserialize)))) - ((zmq)(with-input-from-string msg (lambda ()(deserialize)))) - (else msg))) + ((fs) msg) + ((http) + (if (string? msg) + (with-input-from-string + (base64:base64-decode + (string-substitute + (regexp "_") "=" msg #t)) + (lambda ()(deserialize))) + (vector #f #f #f))) ;; crude reply for when things go awry + ((zmq)(with-input-from-string msg (lambda ()(deserialize)))) + (else msg))) (define (cdb:use-non-blocking-mode proc) (set! *client-non-blocking-mode* #t) (let ((res (proc))) (set! *client-non-blocking-mode* #f) res)) - + ;; params = 'target cached remparams ;; ;; make-vector-record cdb packet client-sig qtype immediate query-sig params qtime ;; ;; cdb:client-call is the unified interface to all the transports. It dispatches the @@ -1411,35 +1503,35 @@ ;; now get the actual message (let ((myres (db:string->obj (receive-message* sub-socket)))) (if (equal? query-sig (vector-ref myres 1)) (set! res (vector-ref myres 2)) (loop))))))) - ;; (timeout (lambda () - ;; (let loop ((n numretries)) - ;; (thread-sleep! 15) - ;; (if (not res) - ;; (if (> numretries 0) - ;; (begin - ;; (debug:print 2 "WARNING: no reply to query " params ", trying resend") - ;; (debug:print-info 11 "re-sending message") - ;; (send-message push-socket zdat) - ;; (debug:print-info 11 "message re-sent") - ;; (loop (- n 1))) - ;; ;; (apply cdb:client-call *runremote* qtype immediate (- numretries 1) params)) - ;; (begin - ;; (debug:print 0 "ERROR: cdb:client-call timed out " params ", exiting.") - ;; (exit 5)))))))) + ;; (timeout (lambda () + ;; (let loop ((n numretries)) + ;; (thread-sleep! 15) + ;; (if (not res) + ;; (if (> numretries 0) + ;; (begin + ;; (debug:print 2 "WARNING: no reply to query " params ", trying resend") + ;; (debug:print-info 11 "re-sending message") + ;; (send-message push-socket zdat) + ;; (debug:print-info 11 "message re-sent") + ;; (loop (- n 1))) + ;; ;; (apply cdb:client-call *runremote* qtype immediate (- numretries 1) params)) + ;; (begin + ;; (debug:print 0 "ERROR: cdb:client-call timed out " params ", exiting.") + ;; (exit 5)))))))) (debug:print-info 11 "Starting threads") (let ((th1 (make-thread send-receive "send receive")) ;; (th2 (make-thread timeout "timeout")) ) (thread-start! th1) ;; (thread-start! th2) (thread-join! th1) (debug:print-info 11 "cdb:client-call returning res=" res) res)))))) - + (define (cdb:set-verbosity serverdat val) (cdb:client-call serverdat 'set-verbosity #f *default-numtries* val)) (define (cdb:login serverdat keyval signature) (cdb:client-call serverdat 'login #t *default-numtries* keyval megatest-version signature)) @@ -1448,11 +1540,14 @@ (cdb:client-call serverdat 'logout #t *default-numtries* keyval signature)) (define (cdb:num-clients serverdat) (cdb:client-call serverdat 'numclients #t *default-numtries*)) +;; I think this would be more efficient if executed on client side FIXME??? (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) @@ -1461,10 +1556,22 @@ (define (cdb:pass-fail-counts serverdat test-id fail-count pass-count) (cdb:client-call serverdat 'pass-fail-counts #t *default-numtries* fail-count pass-count test-id)) (define (cdb:tests-register-test serverdat run-id test-name item-path) (cdb:client-call serverdat 'register-test #t *default-numtries* run-id test-name item-path)) + +;; more transactioned calls, these for roll-up-pass-fail stuff +(define (cdb:update-pass-fail-counts serverdat run-id test-name) + (cdb:client-call serverdat 'update-fail-pass-counts #t *default-numtries* run-id test-name run-id test-name run-id test-name)) + +(define (cdb:top-test-set-running serverdat run-id test-name) + (cdb:client-call serverdat 'top-test-set-running #t *default-numtries* run-id test-name)) + +(define (cdb:top-test-set-per-pf-counts serverdat run-id test-name) + (cdb:client-call serverdat 'top-test-set-per-pf-counts #t *default-numtries* run-id test-name run-id test-name run-id test-name)) + +;;= (define (cdb:flush-queue serverdat) (cdb:client-call serverdat 'flush #f *default-numtries*)) (define (cdb:kill-server serverdat pid) @@ -1475,11 +1582,13 @@ (define (cdb:get-test-info serverdat run-id test-name item-path) (cdb:client-call serverdat 'immediate #f *default-numtries* open-run-close db:get-test-info #f run-id test-name item-path)) (define (cdb:get-test-info-by-id serverdat test-id) - (cdb:client-call serverdat 'immediate #f *default-numtries* open-run-close db:get-test-info-by-id #f test-id)) + (let ((test-dat (cdb:client-call serverdat 'immediate #f *default-numtries* open-run-close db:get-test-info-by-id #f test-id))) + (hash-table-set! *test-info* test-id (vector (current-seconds) test-dat)) ;; cached for use where up-to-date info is not needed + test-dat)) ;; db should be db open proc or #f (define (cdb:remote-run proc db . params) (apply cdb:client-call *runremote* 'immediate #f *default-numtries* open-run-close proc #f params)) @@ -1501,12 +1610,18 @@ ;; A G R E G A T E D T R A N S A C T I O N D B W R I T E S ;;====================================================================== (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');") + ;; Test state and status + '(set-test-state "UPDATE tests SET state=? WHERE id=?;") + '(set-test-status "UPDATE tests SET state=? WHERE id=?;") '(state-status "UPDATE tests SET state=?,status=? WHERE id=?;") '(state-status-msg "UPDATE tests SET state=?,status=?,comment=? WHERE id=?;") + ;; Test comment + '(set-test-comment "UPDATE tests SET comment=? WHERE id=?;") + '(set-test-start-time "UPDATE tests SET event_time=strftime('%s','now') 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 THEN 'FAIL' @@ -1523,17 +1638,39 @@ '(update-cpuload-diskfree "UPDATE tests SET cpuload=?,diskfree=? WHERE id=?;") '(update-run-duration "UPDATE tests SET run_duration=? WHERE id=?;") '(update-uname-host "UPDATE tests SET uname=?,host=? WHERE id=?;") '(update-test-state "UPDATE tests SET state=? WHERE state=? AND run_id=? AND testname=? AND NOT (item_path='' AND testname IN (SELECT DISTINCT testname FROM tests WHERE testname=? AND item_path != ''));") '(update-test-status "UPDATE tests SET status=? WHERE status like ? AND run_id=? AND testname=? AND NOT (item_path='' AND testname IN (SELECT DISTINCT testname FROM tests WHERE testname=? AND item_path != ''));") - )) + ;; stuff for roll-up-pass-fail-counts + '(update-fail-pass-counts "UPDATE tests + SET fail_count=(SELECT count(id) FROM tests WHERE run_id=? AND testname=? AND item_path != '' AND status IN ('FAIL','CHECK')), + pass_count=(SELECT count(id) FROM tests WHERE run_id=? AND testname=? AND item_path != '' AND status IN ('PASS','WARN','WAIVED')) + WHERE run_id=? AND testname=? AND item_path='';") + '(top-test-set-running "UPDATE tests SET state='RUNNING' WHERE run_id=? AND testname=? AND item_path='';") + '(top-test-set-per-pf-counts "UPDATE tests + SET state=CASE + WHEN (SELECT count(id) FROM tests + WHERE run_id=? AND testname=? + AND item_path != '' + AND state in ('RUNNING','NOT_STARTED','LAUNCHED','REMOTEHOSTSTART')) > 0 THEN 'RUNNING' + ELSE 'COMPLETED' END, + status=CASE + WHEN fail_count > 0 THEN 'FAIL' + WHEN pass_count > 0 AND fail_count=0 THEN 'PASS' + WHEN (SELECT count(id) FROM tests + WHERE run_id=? AND testname=? + AND item_path != '' + AND status = 'SKIP') > 0 THEN 'SKIP' + ELSE 'UNKNOWN' END + WHERE run_id=? AND testname=? AND item_path='';") + )) ;; do not run these as part of the transaction (define db:special-queries '(rollup-tests-pass-fail - db:roll-up-pass-fail-counts - login - immediate + ;; db:roll-up-pass-fail-counts ;; WHY NOT!? + login + immediate flush sync set-verbosity killserver )) @@ -1552,11 +1689,11 @@ (mutex-unlock! *incoming-mutex*) (if (> (length data) 0) ;; Process if we have data (begin (debug:print-info 7 "Writing cached data " data) - + ;; Prepare the needed sql statements ;; (for-each (lambda (request-item) (let ((stmt-key (vector-ref request-item 0)) (query (vector-ref request-item 1))) @@ -1644,11 +1781,11 @@ (thread-sleep! 0.01) (loop)))) (set! *number-of-writes* (+ *number-of-writes* 1)) (set! *writes-total-delay* (+ *writes-total-delay* (- (current-milliseconds) start-time))) got-it)) - + (define (db:process-queue-item db item) (let* ((stmt-key (cdb:packet-get-qtype item)) (qry-sig (cdb:packet-get-query-sig item)) (return-address (cdb:packet-get-client-sig item)) (params (cdb:packet-get-params item)) @@ -1734,49 +1871,10 @@ db "SELECT id,item_path,state,status,run_duration,final_logf,comment FROM tests WHERE run_id=? AND testname=? AND item_path != '';" run-id test-name) res)) -;; Rollup the pass/fail counts from itemized tests into fail_count and pass_count -;; NOTE: Is this duplicating (db:test-data-rollup db test-id status) ???? -(define (db:roll-up-pass-fail-counts db run-id test-name item-path status) - ;; (cdb:flush-queue *runremote*) - (if (and (not (equal? item-path "")) - (member status '("PASS" "WARN" "FAIL" "WAIVED" "RUNNING" "CHECK" "SKIP"))) - (begin - (sqlite3:execute - db - "UPDATE tests - SET fail_count=(SELECT count(id) FROM tests WHERE run_id=? AND testname=? AND item_path != '' AND status IN ('FAIL','CHECK')), - pass_count=(SELECT count(id) FROM tests WHERE run_id=? AND testname=? AND item_path != '' AND status IN ('PASS','WARN','WAIVED')) - WHERE run_id=? AND testname=? AND item_path='';" - run-id test-name run-id test-name run-id test-name) - ;; (thread-sleep! 0.1) ;; give other processes a chance here, no, better to be done ASAP? - (if (equal? status "RUNNING") ;; running takes priority over all other states, force the test state to RUNNING - (sqlite3:execute db "UPDATE tests SET state=? WHERE run_id=? AND testname=? AND item_path='';" "RUNNING" run-id test-name) - (sqlite3:execute - db - "UPDATE tests - SET state=CASE - WHEN (SELECT count(id) FROM tests - WHERE run_id=? AND testname=? - AND item_path != '' - AND state in ('RUNNING','NOT_STARTED')) > 0 THEN 'RUNNING' - ELSE 'COMPLETED' END, - status=CASE - WHEN fail_count > 0 THEN 'FAIL' - WHEN pass_count > 0 AND fail_count=0 THEN 'PASS' - WHEN (SELECT count(id) FROM tests - WHERE run_id=? AND testname=? - AND item_path != '' - AND status = 'SKIP') > 0 THEN 'SKIP' - ELSE 'UNKNOWN' END - WHERE run_id=? AND testname=? AND item_path='';" - run-id test-name run-id test-name run-id test-name)) - #f) - #f)) - ;;====================================================================== ;; Tests meta data ;;====================================================================== ;; read the record given a testname @@ -1922,17 +2020,17 @@ ;; if the test is not FAIL then set status based on the fail and pass counts. (cdb:test-rollup-test_data-pass-fail *runremote* test-id) ;; (sqlite3:execute ;; db ;;; NOTE: Should this be WARN,FAIL? A WARN is not a FAIL????? BUG FIXME ;; "UPDATE tests - ;; SET status=CASE WHEN (SELECT fail_count FROM tests WHERE id=?) > 0 - ;; THEN 'FAIL' - ;; WHEN (SELECT pass_count FROM tests WHERE id=?) > 0 AND - ;; (SELECT status FROM tests WHERE id=?) NOT IN ('WARN','FAIL') - ;; THEN 'PASS' - ;; ELSE status - ;; END WHERE id=?;" + ;; SET status=CASE WHEN (SELECT fail_count FROM tests WHERE id=?) > 0 + ;; THEN 'FAIL' + ;; WHEN (SELECT pass_count FROM tests WHERE id=?) > 0 AND + ;; (SELECT status FROM tests WHERE id=?) NOT IN ('WARN','FAIL') + ;; THEN 'PASS' + ;; ELSE status + ;; END WHERE id=?;" ;; test-id test-id test-id test-id) )))) (define (db:get-prev-tol-for-test db test-id category variable) ;; Finish me? @@ -2079,14 +2177,14 @@ ((eq? (db:step-get-event_time a)(db:step-get-event_time b)) (< (db:step-get-id a) (db:step-get-id b))) (else #f))))) res))) -(define (db:get-compressed-steps test-id #!key (work-area #f)) +(define (db:get-compressed-steps test-id #!key (work-area #f)(tdb #f)) (if (or (not work-area) (file-exists? (conc work-area "/testdat.db"))) - (let* ((comprsteps (open-run-close db:get-steps-table #f test-id work-area: work-area))) + (let* ((comprsteps (open-run-close db:get-steps-table tdb test-id work-area: work-area))) (map (lambda (x) ;; take advantage of the \n on time->string (vector (vector-ref x 0) (let ((s (vector-ref x 1))) @@ -2119,11 +2217,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)) '() @@ -2142,37 +2240,44 @@ ;; (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 + ;; 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)) (set! result (append (if (null? tests) (list waitontest-name) tests) result))) ;; if the test is not found then clearly the waiton is not met... ;; (if (not ever-seen)(set! result (cons waitontest-name result))))) (if (not ever-seen) Index: dcommon.scm ================================================================== --- dcommon.scm +++ dcommon.scm @@ -346,13 +346,13 @@ (iup:attribute-set! section-matrix (conc curr-row-num ":1") (configf:lookup rawconfig sectionname var)) (set! curr-row-num (+ 1 curr-row-num))) ;; (config-lookup *configdat* "fields" var))) key-vals) (iup:vbox (iup:label (if title title (conc "Settings from [" sectionname "]")) - #:size "5x" - #:expand "HORIZONTAL" - ) + ;; #:size "5x" + #:expand "HORIZONTAL" + ) section-matrix))) ;; General data ;; (define (dcommon:general-info) @@ -384,18 +384,20 @@ (let* ((run-stats (mt:get-run-stats)) (indices (common:sparse-list-generate-index run-stats)) ;; proc: set-cell)) (row-indices (car indices)) (col-indices (cadr indices)) (max-row (if (null? row-indices) 1 (apply max (map cadr row-indices)))) - (max-col (if (null? col-indices) 1 (apply max (map cadr col-indices)))) + (max-col (if (null? col-indices) 1 + (apply max (map cadr col-indices)))) (max-visible (max (- *num-tests* 15) 3)) + (max-col-vis (if (> max-col 10) 10 max-col)) (numrows 1) (numcols 1)) (iup:attribute-set! stats-matrix "CLEARVALUE" "CONTENTS") (iup:attribute-set! stats-matrix "NUMCOL" max-col ) (iup:attribute-set! stats-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20 - (iup:attribute-set! stats-matrix "NUMCOL_VISIBLE" max-col) + (iup:attribute-set! stats-matrix "NUMCOL_VISIBLE" max-col-vis) (iup:attribute-set! stats-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row)) ;; Row labels (for-each (lambda (ind) (let* ((name (car ind)) @@ -434,11 +436,11 @@ (if changed (iup:attribute-set! stats-matrix "REDRAW" "ALL")))))) (updater) (set! dashboard:update-summary-tab updater) (iup:attribute-set! stats-matrix "WIDTHDEF" "40") (iup:vbox - (iup:label "Run statistics" #:expand "HORIZONTAL") + ;; (iup:label "Run statistics" #:expand "HORIZONTAL") stats-matrix))) (define (dcommon:servers-table) (let* ((colnum 0) (rownum 0) 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 ADDED docs/manual/howto.txt Index: docs/manual/howto.txt ================================================================== --- /dev/null +++ docs/manual/howto.txt @@ -0,0 +1,48 @@ + +How To Do Things +================ + +Tricks +------ + +This section is a compendium of a various useful tricks for debugging, +configuring and generally getting the most out of Megatest. + +Debugging Tricks +---------------- + +Examining The Environment +~~~~~~~~~~~~~~~~~~~~~~~~~ + +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.2 +cellname/LVS/cellname.LAYOUT_ERRORS + +Error: text open + +ww31.3 +cellname/LVS/cellname.LAYOUT_ERRORS + +Error: text open Index: docs/manual/megatest_manual.html ================================================================== --- docs/manual/megatest_manual.html +++ docs/manual/megatest_manual.html @@ -742,46 +742,30 @@ <matt@kiatoa.com>
version 1.0, April 2012
-
-

Dedication

-
-

Dedicated to my wife Joanna who has kindly supported my working on various projects over the years.

-
-

Thanks

-
-

Thank you the many people I’ve worked over the years who have -shared their knowledge and insights with me.

-

Thanks also to the creators of the various open source projects that -Megatest is built on. These include Linux, xemacs, chicken scheme, -fossil and asciidoc. Without these projects something like Megatest -would be difficult or impossible to do.

-
-
-
-

Preface

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.

@@ -795,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
@@ -886,41 +1184,158 @@

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

+
+

Setup section

+
+

Header

+
+
+
[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
+
+
+
+
+

Requirements section

+
+

Header

+
+
+
[requirements]
+
+
+
+

Wait on Other Tests

-
# testconfig
-[requirements]
-
-# A normal waiton waits for the prior tests to be COMPLETED
+
# A normal waiton waits for the prior tests to be COMPLETED
 # and PASS, CHECK or WAIVED
-waiton test1 test2
-
-# A item based waiton will start items in a test when the
-# same-named item is COMPLETED and PASS, CHECK or WAIVED
-# in the prior test
-#
-mode   normal | toplevel
-
-# With a toplevel test you may wish to generate your list
+waiton test1 test2
+
+
+
+

Mode

+

The default (i.e. if mode is not specified) is normal. All pre-dependent tests +must be COMPLETED and PASS, CHECK or WAIVED before the test will start

+
+
+
mode   normal
+
+

The toplevel mode requires only that the prior tests are COMPLETED.

+
+
+
mode toplevel
+
+

A item based waiton will start items in a test when the +same-named item is COMPLETED and PASS, CHECK or WAIVED +in the prior test

+
+
+
mode itemmatch
+
+
+
+
# With a toplevel test you may wish to generate your list
 # of tests to run dynamically
 #
 # waiton #{shell get-valid-tests-to-run.sh}
+
+
+

Run time limit

+
+
+
runtimelim 1h 2m 3s  # this will automatically kill the test if it runs for more than 1h 2m and 3s
+
+
+
+

Skip

+
+
+

Header

+
+
+
[skip]
+
+
+
+

Skip on Still-running Tests

+
+
+
# NB// If the prevrunning line exists with *any* value the test will
+# automatically SKIP if the same-named test is currently RUNNING
+
+prevrunning x
+
+
+
+

Skip if a File Exists

+
+
+
fileexists /path/to/a/file # skip if /path/to/a/file exists
+
+
+
+

Controlled waiver propagation

+

If test is FAIL and previous test in run with same MT_TARGET is WAIVED then apply the following rules from the testconfig: +If a waiver check is specified in the testconfig apply the check and if it passes then set this FAIL to WAIVED

+

Waiver check has two parts, 1) a list of waiver, rulename, filepatterns and 2) the rulename script spec (note that "diff" and "logpro" are predefined)

+
+
+
###### EXAMPLE FROM testconfig #########
+# matching file(s) will be diff'd with previous run and logpro applied
+# if PASS or WARN result from logpro then WAIVER state is set
+#
+[waivers]
+# logpro_file    rulename      input_glob
+waiver_1         logpro        lookittmp.log
+
+[waiver_rules]
+
+# This builtin rule is the default if there is no <waivername>.logpro file
+# diff   diff %file1% %file2%
+
+# This builtin rule is applied if a <waivername>.logpro file exists
+# logpro diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html
+
+
+
+
+

Ezsteps

+

To transfer the environment to the next step you can do the following:

+
+
+
$MT_MEGATEST -env2file .ezsteps/${stepname}
+
+

Appendix A: Example Appendix

@@ -1000,10 +1415,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,40 +43,15 @@ 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::howto.txt[] include::reference.txt[] - - -Controlled waiver propagation -============================= -If test is FAIL and previous test in run with same MT_TARGET is WAIVED then apply the following rules from the testconfig: -If a waiver check is specified in the testconfig apply the check and if it passes then set this FAIL to WAIVED - -Waiver check has two parts, 1) a list of waiver, rulename, filepatterns and 2) the rulename script spec (note that "diff" and "logpro" are predefined) - -========================================================= -###### EXAMPLE FROM testconfig ######### -# matching file(s) will be diff'd with previous run and logpro applied -# if PASS or WARN result from logpro then WAIVER state is set -# -[waivers] -# logpro_file rulename input_glob -waiver_1 logpro lookittmp.log - -[waiver_rules] - -# This builtin rule is the default if there is no .logpro file -# diff diff %file1% %file2% - -# This builtin rule is applied if a .logpro file exists -# logpro diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html -========================================================= - - [appendix] Example Appendix ================ One or more optional appendixes go here at section level zero. Index: docs/manual/reference.txt ================================================================== --- docs/manual/reference.txt +++ docs/manual/reference.txt @@ -8,27 +8,146 @@ sub-sections. The testconfig File ------------------- +Setup section +~~~~~~~~~~~~~ + +Header +^^^^^^ + +------------------- +[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 ------------------- -# testconfig + +Requirements section +~~~~~~~~~~~~~~~~~~~~ + +Header +^^^^^^ + +------------------- [requirements] +------------------- + +Wait on Other Tests +^^^^^^^^^^^^^^^^^^^ +------------------- # A normal waiton waits for the prior tests to be COMPLETED # and PASS, CHECK or WAIVED waiton test1 test2 +------------------- + +Mode +^^^^ + +The default (i.e. if mode is not specified) is normal. All pre-dependent tests +must be COMPLETED and PASS, CHECK or WAIVED before the test will start + +------------------- +mode normal +------------------- + +The toplevel mode requires only that the prior tests are COMPLETED. + +------------------- +mode toplevel +------------------- + +A item based waiton will start items in a test when the +same-named item is COMPLETED and PASS, CHECK or WAIVED +in the prior test + +------------------- +mode itemmatch +------------------- -# A item based waiton will start items in a test when the -# same-named item is COMPLETED and PASS, CHECK or WAIVED -# in the prior test -# -mode normal | toplevel +------------------- # With a toplevel test you may wish to generate your list # of tests to run dynamically # # waiton #{shell get-valid-tests-to-run.sh} ------------------ + + +Run time limit +^^^^^^^^^^^^^^ + +----------------- +runtimelim 1h 2m 3s # this will automatically kill the test if it runs for more than 1h 2m and 3s +----------------- + +Skip +^^^^ + +Header +^^^^^^ + +----------------- +[skip] +----------------- + +Skip on Still-running Tests +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +----------------- +# NB// If the prevrunning line exists with *any* value the test will +# automatically SKIP if the same-named test is currently RUNNING + +prevrunning x +----------------- + +Skip if a File Exists +^^^^^^^^^^^^^^^^^^^^^ + +----------------- +fileexists /path/to/a/file # skip if /path/to/a/file exists +----------------- + +Controlled waiver propagation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If test is FAIL and previous test in run with same MT_TARGET is WAIVED then apply the following rules from the testconfig: +If a waiver check is specified in the testconfig apply the check and if it passes then set this FAIL to WAIVED + +Waiver check has two parts, 1) a list of waiver, rulename, filepatterns and 2) the rulename script spec (note that "diff" and "logpro" are predefined) + +----------------- +###### EXAMPLE FROM testconfig ######### +# matching file(s) will be diff'd with previous run and logpro applied +# if PASS or WARN result from logpro then WAIVER state is set +# +[waivers] +# logpro_file rulename input_glob +waiver_1 logpro lookittmp.log + +[waiver_rules] + +# This builtin rule is the default if there is no .logpro file +# diff diff %file1% %file2% + +# This builtin rule is applied if a .logpro file exists +# logpro diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html +----------------- + +Ezsteps +~~~~~~~ + +To transfer the environment to the next step you can do the following: + +---------------------------- +$MT_MEGATEST -env2file .ezsteps/${stepname} +---------------------------- + :numbered!: ADDED docs/manual_running_of_tests.png Index: docs/manual_running_of_tests.png ================================================================== --- /dev/null +++ docs/manual_running_of_tests.png cannot compute difference between binary files ADDED docs/megatest-about.svg Index: docs/megatest-about.svg ================================================================== --- /dev/null +++ docs/megatest-about.svg @@ -0,0 +1,492 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Megatest + Simple - but not TOO simple! + + Automation + Quality Assurance + Regression Testing + System Administration + + + + + + Write one task or test and iterateDistribute tasks over one or many hostsOrganize runs by any variables you wish - release - architecture - unit or partitionTasks or tests may depend on othersEach task or test runs in clean areaAdd disk space or partitions as neededRigorous results; error, pass, warn etc.Crontab friendly runs (skip if running)Easy debugging - easy to recreate environment for task - annotated HTML logs help find issuesSimplify scripts - eliminate for-each or while loops - parallel running handled by tool + + FAIL + + PASS + + WARN + + Index: docs/megatest-training.odp ================================================================== --- docs/megatest-training.odp +++ docs/megatest-training.odp cannot compute difference between binary files Index: docs/megatest-training.pdf ================================================================== --- docs/megatest-training.pdf +++ docs/megatest-training.pdf cannot compute difference between binary files Index: docs/plan.txt ================================================================== --- docs/plan.txt +++ docs/plan.txt @@ -1,13 +1,83 @@ - -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 +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 +.. 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 + Index: ezsteps.scm ================================================================== --- ezsteps.scm +++ ezsteps.scm @@ -8,19 +8,166 @@ ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. ;; strftime('%m/%d/%Y %H:%M:%S','now','localtime') -(use sqlite3 srfi-1 posix regex regex-case srfi-69 dot-locking) +(use sqlite3 srfi-1 posix regex regex-case srfi-69 dot-locking directory-utils) (import (prefix sqlite3 sqlite3:)) (declare (unit ezsteps)) (declare (uses db)) (declare (uses common)) (declare (uses items)) (declare (uses runconfig)) (include "common_records.scm") -; (include "key_records.scm") -; (include "db_records.scm") -; (include "run_records.scm") +(include "key_records.scm") +(include "db_records.scm") +(include "run_records.scm") + +(define (ezsteps:run-from testdat start-step-name run-one) + (let* ((test-run-dir (db:test-get-rundir testdat)) + (testconfig (read-config (conc test-run-dir "/testconfig") #f #t environ-patt: "pre-launch-env-vars")) + (ezstepslst (hash-table-ref/default testconfig "ezsteps" '())) + (run-mutex (make-mutex)) + (rollup-status 0) + (exit-info (vector #t #t #t)) + (test-id (db:test-get-id testdat)) + (test-name (db:test-get-testname testdat)) + (kill-job #f)) ;; for future use (on re-factoring with launch.scm code + (let loop ((count 5)) + (if (file-exists? test-run-dir) + (push-directory test-run-dir) + (if (> count 0) + (begin + (debug:print 0 "WARNING: ezsteps attempting to run but test run directory " test-run-dir " is not there. Waiting and trying again " count " more times") + (sleep 3) + (loop (- count 1)))))) + (debug:print-info 0 "Running in directory " test-run-dir) + (if (not (file-exists? ".ezsteps"))(create-directory ".ezsteps")) + ;; if ezsteps was defined then we are sure to have at least one step but check anyway + (if (not (> (length ezstepslst) 0)) + (message-window "ERROR: You can only re-run steps defined via ezsteps") + (begin + (let loop ((ezstep (car ezstepslst)) + (tal (cdr ezstepslst)) + (prevstep #f) + (runflag #f)) ;; flag used to skip steps when not starting at the beginning + (if (vector-ref exit-info 1) + (let* ((stepname (car ezstep)) ;; do stuff to run the step + (stepinfo (cadr ezstep)) + (stepparts (string-match (regexp "^(\\{([^\\}]*)\\}\\s*|)(.*)$") stepinfo)) + (stepparms (list-ref stepparts 2)) ;; for future use, {VAR=1,2,3}, run step for each + (stepcmd (list-ref stepparts 3)) + (script "") ; "#!/bin/bash\n") ;; yep, we depend on bin/bash FIXME!!! + (logpro-used #f)) + + ;; Skip steps until hit start-step-name + ;; + (if (and start-step-name + (not runflag)) + (if (equal? stepname start-step-name) + (set! runflag #t) ;; and continue + (if (not (null? tal)) + (loop (car tal)(cdr tal) stepname #f)))) + (debug:print 4 "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts + " stepparms: " stepparms " stepcmd: " stepcmd) + + (if (file-exists? (conc stepname ".logpro"))(set! logpro-used #t)) + + ;; call the command using mt_ezstep + (set! script (conc "mt_ezstep " stepname " " (if prevstep prevstep "-") " " stepcmd)) + + (debug:print 4 "script: " script) + ;; DO NOT remote + (db:teststep-set-status! #f test-id stepname "start" "-" #f #f work-area: test-run-dir) + ;; now launch + (let ((pid (process-run script))) + (let processloop ((i 0)) + (let-values (((pid-val exit-status exit-code)(process-wait pid #t))) + (mutex-lock! run-mutex) + (vector-set! exit-info 0 pid) + (vector-set! exit-info 1 exit-status) + (vector-set! exit-info 2 exit-code) + (mutex-unlock! run-mutex) + (if (eq? pid-val 0) + (begin + (thread-sleep! 1) + (processloop (+ i 1)))) + )) + (let ((exinfo (vector-ref exit-info 2)) + (logfna (if logpro-used (conc stepname ".html") ""))) + ;; testing if procedures called in a remote call cause problems (ans: no or so I suspect) + (db:teststep-set-status! #f test-id stepname "end" exinfo #f logfna work-area: test-run-dir)) + (if logpro-used + (cdb:test-set-log! *runremote* test-id (conc stepname ".html"))) + ;; set the test final status + (let* ((this-step-status (cond + ((and (eq? (vector-ref exit-info 2) 2) logpro-used) 'warn) + ((eq? (vector-ref exit-info 2) 0) 'pass) + (else 'fail))) + (overall-status (cond + ((eq? rollup-status 2) 'warn) + ((eq? rollup-status 0) 'pass) + (else 'fail))) + (next-status (cond + ((eq? overall-status 'pass) this-step-status) + ((eq? overall-status 'warn) + (if (eq? this-step-status 'fail) 'fail 'warn)) + (else 'fail)))) + (debug:print 4 "Exit value received: " (vector-ref exit-info 2) " logpro-used: " logpro-used + " this-step-status: " this-step-status " overall-status: " overall-status + " next-status: " next-status " rollup-status: " rollup-status) + (case next-status + ((warn) + (set! rollup-status 2) + ;; NB// test-set-status! does rdb calls under the hood + (tests:test-set-status! test-id "RUNNING" "WARN" + (if (eq? this-step-status 'warn) "Logpro warning found" #f) + #f)) + ((pass) + (tests:test-set-status! test-id "RUNNING" "PASS" #f #f)) + (else ;; 'fail + (set! rollup-status 1) ;; force fail + (tests:test-set-status! test-id "RUNNING" "FAIL" (conc "Failed at step " stepname) #f) + )))) + (if (and (steprun-good? logpro-used (vector-ref exit-info 2)) + (not (null? tal))) + (if (not run-one) ;; if we got here we completed the step, if run-one is true, stop + (loop (car tal) (cdr tal) stepname runflag)))) + (debug:print 4 "WARNING: a prior step failed, stopping at " ezstep))) + + ;; Once done with step/steps update the test record + ;; + (let* ((item-path (db:test-get-item-path testdat)) ;; (item-list->path itemdat)) + (testinfo (cdb:get-test-info-by-id *runremote* test-id))) ;; refresh the testdat, call it iteminfo in case need prev/curr + ;; Am I completed? + (if (equal? (db:test-get-state testinfo) "RUNNING") ;; (not (equal? (db:test-get-state testinfo) "COMPLETED")) + (let ((new-state (if kill-job "KILLED" "COMPLETED") ;; (if (eq? (vector-ref exit-info 2) 0) ;; exited with "good" status + ;; "COMPLETED" + ;; (db:test-get-state testinfo))) ;; else preseve the state as set within the test + ) + (new-status (cond + ((not (vector-ref exit-info 1)) "FAIL") ;; job failed to run + ((eq? rollup-status 0) + ;; if the current status is AUTO the defer to the calculated value (i.e. leave this AUTO) + (if (equal? (db:test-get-status testinfo) "AUTO") "AUTO" "PASS")) + ((eq? rollup-status 1) "FAIL") + ((eq? rollup-status 2) + ;; if the current status is AUTO the defer to the calculated value but qualify (i.e. make this AUTO-WARN) + (if (equal? (db:test-get-status testinfo) "AUTO") "AUTO-WARN" "WARN")) + (else "FAIL")))) ;; (db:test-get-status testinfo))) + (debug:print-info 2 "Test NOT logged as COMPLETED, (state=" (db:test-get-state testinfo) "), updating result, rollup-status is " rollup-status) + (tests:test-set-status! test-id + new-state + new-status + (args:get-arg "-m") #f) + ;; need to update the top test record if PASS or FAIL and this is a subtest + (if (not (equal? item-path "")) + (cdb:roll-up-pass-fail-counts *runremote* run-id test-name item-path new-status)))) + ;; for automated creation of the rollup html file this is a good place... + (if (not (equal? item-path "")) + (tests:summarize-items #f run-id test-id test-name #f)) ;; don't force - just update if no + ))) + (pop-directory) + rollup-status)) 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) @@ -183,11 +183,15 @@ ;; ;; 1 Hello, world! Goodbye Dolly ;; Send msg to serverdat and receive result (define (http-transport:client-send-receive serverdat msg #!key (numretries 30)) (let* (;; (url (http-transport:make-server-url serverdat)) - (fullurl (caddr serverdat)) ;; (conc url "/ctrl")) ;; (conc url "/?dat=" msg))) + (fullurl (if (list? serverdat) + (caddr serverdat) + (begin + (debug:print 0 "FATAL ERROR: http-transport:client-send-receive called with no server info") + (exit 1)))) ;; (conc url "/ctrl")) ;; (conc url "/?dat=" msg))) (res #f)) (handle-exceptions exn (begin (print "ERROR IN http-transport:client-send-receive " ((condition-property-accessor 'exn 'message) exn)) ADDED index-tree.scm Index: index-tree.scm ================================================================== --- /dev/null +++ index-tree.scm @@ -0,0 +1,50 @@ +;;====================================================================== +;; Copyright 2006-2013, 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. +;;====================================================================== + +;;====================================================================== +;; Tests +;;====================================================================== + +(use sqlite3 srfi-1 posix regex regex-case srfi-69 dot-locking tcp directory-utils) +(import (prefix sqlite3 sqlite3:)) + +(declare (unit tests)) +(declare (uses lock-queue)) +(declare (uses db)) +(declare (uses common)) +(declare (uses items)) +(declare (uses runconfig)) + +(include "common_records.scm") +(include "key_records.scm") +(include "db_records.scm") +(include "run_records.scm") +(include "test_records.scm") + +;; Populate the links tree with index.html files +;; +;; - start from most recent tests and work towards oldest -OR- +;; start from deepest hierarchy and work way up +;; - look up tests in megatest.db +;; - cross-reference the tests to stats.db +;; - if newer than event_time in stats.db or not registered in stats.db regenerate +;; - run du and store in stats.db +;; - when all tests at that level done generate next level up index.html +;; +;; include in rollup html index.html: +;; sum of du +;; counts of PASS, FAIL, RUNNING, REMOTEHOSTSTART, LAUNCHED, CHECK etc. +;; overall status +;; +;; include in test specific index.html: +;; host, uname, cpu graph, disk avail graph, steps, data +;; meta data, state, status, du +;; Index: launch.scm ================================================================== --- launch.scm +++ launch.scm @@ -1,7 +1,7 @@ -;; Copyright 2006-2012, Matthew Welland. +;; Copyright 2006-2013, 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 @@ -90,11 +90,11 @@ (change-directory top-path) (debug:print 2 "Exectuing " test-name " (id: " test-id ") on " (get-host-name)) ;; Setup the *runremote* global var (if *runremote* (debug:print 2 "ERROR: I'm not expecting *runremote* to be set at this time")) ;; (set! *runremote* runremote) - (set! *transport-type* (string->symbol transport)) + ;; (set! *transport-type* (string->symbol transport)) (set! keys (cdb:remote-run db:get-keys #f)) (set! keyvals (keys:target->keyval keys target)) ;; apply pre-overrides before other variables. The pre-override vars must not ;; clobbers things from the official sources such as megatest.config and runconfigs.config (if (string? set-vars) @@ -112,10 +112,11 @@ (setenv "MT_TEST_NAME" test-name) (setenv "MT_ITEM_INFO" (conc itemdat)) (setenv "MT_RUNNAME" runname) (setenv "MT_MEGATEST" megatest) (setenv "MT_TARGET" target) + (setenv "MT_LINKTREE" (configf:lookup *configdat* "setup" "linktree")) (if mt-bindir-path (setenv "PATH" (conc (getenv "PATH") ":" mt-bindir-path))) ;; (change-directory top-path) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") @@ -134,12 +135,16 @@ (alist->env-vars env-ovrd) (set-megatest-env-vars run-id) (set-item-env-vars itemdat) (save-environment-as-files "megatest") ;; open-run-close not needed for test-set-meta-info - (tests:set-meta-info #f test-id run-id test-name itemdat 0 work-area) - (tests:test-set-status! test-id "REMOTEHOSTSTART" "n/a" (args:get-arg "-m") #f) + (tests:set-full-meta-info #f test-id run-id 0 work-area) + + ;; (tests:test-set-status! test-id "REMOTEHOSTSTART" "n/a" (args:get-arg "-m") #f) + (tests:test-force-state-status! test-id "REMOTEHOSTSTART" "n/a") + (thread-sleep! 0.3) ;; NFS slowness has caused grief here + (if (args:get-arg "-xterm") (set! fullrunscript "xterm") (if (and fullrunscript (not (file-execute-access? fullrunscript))) (system (conc "chmod ug+x " fullrunscript)))) ;; We are about to actually kick off the test @@ -149,15 +154,25 @@ (let* ((m (make-mutex)) (kill-job? #f) (exit-info (vector #t #t #t)) (job-thread #f) + (keep-going #t) (runit (lambda () ;; (let-values ;; (((pid exit-status exit-code) ;; (run-n-wait fullrunscript))) - (tests:test-set-status! test-id "RUNNING" "n/a" #f #f) + ;; (tests:test-set-status! test-id "RUNNING" "n/a" #f #f) + ;; Since we should have a clean slate at this time there is no need to do + ;; any of the other stuff that tests:test-set-status! does. Let's just + ;; force RUNNING/n/a + + + (thread-sleep! 0.3) + (tests:test-force-state-status! test-id "RUNNING" "n/a") + (thread-sleep! 0.3) ;; NFS slowness has caused grief here + ;; if there is a runscript do it first (if fullrunscript (let ((pid (process-run fullrunscript))) (let loop ((i 0)) (let-values @@ -176,10 +191,11 @@ ;; then, if runscript ran ok (or did not get called) ;; do all the ezsteps (if any) (if ezsteps (let* ((testconfig (read-config (conc work-area "/testconfig") #f #t environ-patt: "pre-launch-env-vars")) ;; FIXME??? is allow-system ok here? (ezstepslst (hash-table-ref/default testconfig "ezsteps" '()))) + (hash-table-set! *testconfigs* test-name testconfig) ;; cached for lazy reads later ... (if (not (file-exists? ".ezsteps"))(create-directory ".ezsteps")) ;; if ezsteps was defined then we are sure to have at least one step but check anyway (if (not (> (length ezstepslst) 0)) (debug:print 0 "ERROR: ezsteps defined but ezstepslst is zero length") (let loop ((ezstep (car ezstepslst)) @@ -243,26 +259,32 @@ (else 'fail))) (next-status (cond ((eq? overall-status 'pass) this-step-status) ((eq? overall-status 'warn) (if (eq? this-step-status 'fail) 'fail 'warn)) - (else 'fail)))) + (else 'fail))) + (next-state "RUNNING") + ;; (cond + ;; ((null? tal) ;; more to run? + ;; "COMPLETED") + ;; (else "RUNNING")) + ) (debug:print 4 "Exit value received: " (vector-ref exit-info 2) " logpro-used: " logpro-used " this-step-status: " this-step-status " overall-status: " overall-status " next-status: " next-status " rollup-status: " rollup-status) (case next-status ((warn) (set! rollup-status 2) ;; NB// test-set-status! does rdb calls under the hood - (tests:test-set-status! test-id "RUNNING" "WARN" + (tests:test-set-status! test-id next-state "WARN" (if (eq? this-step-status 'warn) "Logpro warning found" #f) #f)) ((pass) - (tests:test-set-status! test-id "RUNNING" "PASS" #f #f)) + (tests:test-set-status! test-id next-state "PASS" #f #f)) (else ;; 'fail (set! rollup-status 1) ;; force fail - (tests:test-set-status! test-id "RUNNING" "FAIL" (conc "Failed at step " stepname) #f) + (tests:test-set-status! test-id next-state "FAIL" (conc "Failed at step " stepname) #f) )))) (if (and (steprun-good? logpro-used (vector-ref exit-info 2)) (not (null? tal))) (loop (car tal) (cdr tal) stepname))) (debug:print 4 "WARNING: a prior step failed, stopping at " ezstep)))))))) @@ -273,10 +295,11 @@ (round (- (current-seconds) start-seconds))))) (kill-tries 0)) + (tests:set-full-meta-info #f test-id run-id (calc-minutes) work-area) (let loop ((minutes (calc-minutes))) (begin (set! kill-job? (or (test-get-kill-request test-id) ;; run-id test-name itemdat)) (and runtlim (let* ((run-seconds (- (current-seconds) start-seconds)) (time-exceeded (> run-seconds runtlim))) @@ -284,14 +307,17 @@ (begin (debug:print-info 0 "KILLING TEST DUE TO TIME LIMIT EXCEEDED! Runtime=" run-seconds " seconds, limit=" runtlim) #t) #f))))) ;; open-run-close not needed for test-set-meta-info - (tests:set-meta-info #f test-id run-id test-name itemdat minutes work-area) + (tests:set-partial-meta-info #f test-id run-id minutes work-area) (if kill-job? (begin (mutex-lock! m) + ;; NOTE: The pid can change as different steps are run. Do we need handshaking between this + ;; section and the runit section? Or add a loop that tries three times with a 1/4 second + ;; between tries? (let* ((pid (vector-ref exit-info 0))) (if (number? pid) (process-signal pid signal/kill) ;; (begin ;; (debug:print 0 "WARNING: Request received to kill job (attempt # " kill-tries ")") @@ -315,68 +341,84 @@ (sqlite3:finalize! tdb) (exit 1)))) (set! kill-tries (+ 1 kill-tries)) (mutex-unlock! m))) ;; (sqlite3:finalize! db) - (thread-sleep! (+ 10 (random 10))) ;; add some jitter to the call home time to spread out the db accesses - (loop (calc-minutes))))))) - (th1 (make-thread monitorjob)) - (th2 (make-thread runit))) + (if keep-going + (begin + (thread-sleep! 3) ;; (+ 3 (random 6))) ;; add some jitter to the call home time to spread out the db accesses + (if keep-going + (loop (calc-minutes)))))))))) ;; NOTE: Checking twice for keep-going is intentional + (th1 (make-thread monitorjob "monitor job")) + (th2 (make-thread runit "run job"))) (set! job-thread th2) (thread-start! th1) (thread-start! th2) (thread-join! th2) + (set! keep-going #f) + (thread-join! th1) + ;; (thread-sleep! 1) + ;; (thread-terminate! th1) ;; Not sure if this is a good idea + (thread-sleep! 1) ;; give thread th1 a chance to be done TODO: Verify this is needed. At 0.1 I was getting fail to stop, increased to total of 1.1 sec. (mutex-lock! m) (let* ((item-path (item-list->path itemdat)) (testinfo (cdb:get-test-info-by-id *runremote* test-id))) ;; )) ;; run-id test-name item-path))) ;; Am I completed? - (if (not (equal? (db:test-get-state testinfo) "COMPLETED")) - (begin - (debug:print 2 "Test NOT logged as COMPLETED, (state=" (db:test-get-state testinfo) "), updating result, rollup-status is " rollup-status) - (tests:test-set-status! test-id - (if kill-job? "KILLED" "COMPLETED") - (cond + (if (member (db:test-get-state testinfo) '("REMOTEHOSTSTART" "RUNNING")) ;; NOTE: It should *not* be REMOTEHOSTSTART but for reasons I don't yet understand it sometimes gets stuck in that state ;; (not (equal? (db:test-get-state testinfo) "COMPLETED")) + (let ((new-state (if kill-job? "KILLED" "COMPLETED") ;; (if (eq? (vector-ref exit-info 2) 0) ;; exited with "good" status + ;; "COMPLETED" + ;; (db:test-get-state testinfo))) ;; else preseve the state as set within the test + ) + (new-status (cond ((not (vector-ref exit-info 1)) "FAIL") ;; job failed to run ((eq? rollup-status 0) - ;; if the current status is AUTO the defer to the calculated value (i.e. leave this AUTO) + ;; if the current status is AUTO then defer to the calculated value (i.e. leave this AUTO) (if (equal? (db:test-get-status testinfo) "AUTO") "AUTO" "PASS")) ((eq? rollup-status 1) "FAIL") ((eq? rollup-status 2) ;; if the current status is AUTO the defer to the calculated value but qualify (i.e. make this AUTO-WARN) (if (equal? (db:test-get-status testinfo) "AUTO") "AUTO-WARN" "WARN")) - (else "FAIL")) - (args:get-arg "-m") #f))) + (else "FAIL")))) ;; (db:test-get-status testinfo))) + (debug:print-info 1 "Test exited in state=" (db:test-get-state testinfo) ", setting state/status based on exit code of " (vector-ref exit-info 1) " and rollup-status of " rollup-status) + (tests:test-set-status! test-id + new-state + new-status + (args:get-arg "-m") #f) + ;; need to update the top test record if PASS or FAIL and this is a subtest + ;; NO NEED TO CALL roll-up-pass-fail-counts HERE, THIS IS DONE IN roll-up-pass-fail-counts called by tests:test-set-status! + ;; (if (not (equal? item-path "")) + ;; (begin + ;; (thread-sleep! 0.1) ;; give other processes an opportunity to access the db as rollup is lower priority + ;; (cdb:roll-up-pass-fail-counts *runremote* run-id test-name item-path new-status))) + )) ;; for automated creation of the rollup html file this is a good place... (if (not (equal? item-path "")) - (tests:summarize-items #f run-id test-name #f)) ;; don't force - just update if no - ) + (tests:summarize-items #f run-id test-id test-name #f))) ;; don't force - just update if no (mutex-unlock! m) - ;; (exec-results (cmd-run->list fullrunscript)) ;; (list ">" (conc test-name "-run.log")))) - ;; (success exec-results)) ;; (eq? (cadr exec-results) 0))) (debug:print 2 "Output from running " fullrunscript ", pid " (vector-ref exit-info 0) " in work area " work-area ":\n====\n exit code " (vector-ref exit-info 2) "\n" "====\n") - ;; (sqlite3:finalize! db) - ;; (sqlite3:finalize! tdb) (if (not (vector-ref exit-info 1)) (exit 4))))))) ;; set up the very basics needed for doing anything here. (define (setup-for-run) ;; would set values for KEYS in the environment here for better support of env-override but ;; have chicken/egg scenario. need to read megatest.config then read it again. Going to ;; pass on that idea for now ;; special case - (set! *configinfo* (find-and-read-config - (if (args:get-arg "-config")(args:get-arg "-config") "megatest.config") - environ-patt: "env-override" - given-toppath: (get-environment-variable "MT_RUN_AREA_HOME") - pathenvvar: "MT_RUN_AREA_HOME")) - (set! *configdat* (if (car *configinfo*)(car *configinfo*) #f)) - (set! *toppath* (if (car *configinfo*)(cadr *configinfo*) #f)) - (if *toppath* - (setenv "MT_RUN_AREA_HOME" *toppath*) ;; to be deprecated - (debug:print 0 "ERROR: failed to find the top path to your run setup.")) + (if (not (hash-table? *configdat*)) ;; no need to re-open on every call + (begin + (set! *configinfo* (find-and-read-config + (if (args:get-arg "-config")(args:get-arg "-config") "megatest.config") + environ-patt: "env-override" + given-toppath: (get-environment-variable "MT_RUN_AREA_HOME") + pathenvvar: "MT_RUN_AREA_HOME")) + (set! *configdat* (if (car *configinfo*)(car *configinfo*) #f)) + (set! *toppath* (if (car *configinfo*)(cadr *configinfo*) #f)) + (if *toppath* + (setenv "MT_RUN_AREA_HOME" *toppath*) ;; to be deprecated + (debug:print 0 "ERROR: failed to find the top path to your Megatest area.")))) *toppath*) (define (get-best-disk confdat) (let* ((disks (hash-table-ref/default confdat "disks" #f)) (best #f) @@ -450,11 +492,12 @@ (if (not (file-exists? linktree)) (begin (debug:print 0 "WARNING: linktree did not exist! Creating it now at " linktree) (create-directory linktree #t))) ;; (system (conc "mkdir -p " linktree)))) ;; create the directory for the tests dir links, this is needed no matter what... - (if (not (directory-exists? lnkbase)) + (if (and (not (directory-exists? lnkbase)) + (not (file-exists? lnkbase))) (create-directory lnkbase #t)) ;; update the toptest record with its location rundir, cache the path ;; This wass highly inefficient, one db write for every subtest, potentially ;; thousands of unnecessary updates, cache the fact it was set and don't set it @@ -573,11 +616,16 @@ (list "MT_TEST_NAME" test-name) ;; (list "MT_ITEM_INFO" (conc itemdat)) (list "MT_RUNNAME" runname) ;; (list "MT_TARGET" mt_target) )) - (let* ((useshell (config-lookup *configdat* "jobtools" "useshell")) + (let* ((useshell (let ((ush (config-lookup *configdat* "jobtools" "useshell"))) + (if ush + (if (equal? ush "no") ;; must use "no" to NOT use shell + #f + ush) + #t))) ;; default is yes (launcher (config-lookup *configdat* "jobtools" "launcher")) (runscript (config-lookup test-conf "setup" "runscript")) (ezsteps (> (length (hash-table-ref/default test-conf "ezsteps" '())) 0)) ;; don't send all the steps, could be big (diskspace (config-lookup test-conf "requirements" "diskspace")) (memory (config-lookup test-conf "requirements" "memory")) @@ -608,10 +656,11 @@ ;; (test-id (cdb:remote-run db:get-test-id #f run-id test-name item-path)) (testinfo (cdb:get-test-info-by-id *runremote* test-id)) (mt_target (string-intersperse (map cadr keyvals) "/")) (debug-param (append (if (args:get-arg "-debug") (list "-debug" (args:get-arg "-debug")) '()) (if (args:get-arg "-logging")(list "-logging") '())))) + (setenv "MT_ITEMPATH" item-path) (if hosts (set! hosts (string-split hosts))) ;; set the megatest to be called on the remote host (if (not remote-megatest)(set! remote-megatest local-megatest)) ;; "megatest")) (set! mt-bindir-path (pathname-directory remote-megatest)) (if launcher (set! launcher (string-split launcher))) @@ -676,19 +725,23 @@ (append (list (list "MT_TEST_RUN_DIR" work-area) (list "MT_TEST_NAME" test-name) (list "MT_ITEM_INFO" (conc itemdat)) (list "MT_RUNNAME" runname) (list "MT_TARGET" mt_target) + (list "MT_ITEMPATH" item-path) ) itemdat))) ;; Launchwait defaults to true, must override it to turn off wait (launchwait (if (equal? (configf:lookup *configdat* "setup" "launchwait") "no") #f #t)) (launch-results (apply (if launchwait cmd-run-with-stderr->list process-run) (if useshell - (string-intersperse fullcmd " ") + (let ((cmdstr (string-intersperse fullcmd " "))) + (if launchwait + cmdstr + (conc cmdstr " >> mt_launch.log 2>&1"))) (car fullcmd)) (if useshell '() (cdr fullcmd))))) (if (not launchwait) ;; give the OS a little time to allow the process to start ADDED lock-queue.scm Index: lock-queue.scm ================================================================== --- /dev/null +++ lock-queue.scm @@ -0,0 +1,134 @@ +;; Copyright 2006-2013, 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. + +;;====================================================================== +;; launch a task - this runs on the originating host, tests themselves +;; +;;====================================================================== + +(use sqlite3 srfi-18) +(import (prefix sqlite3 sqlite3:)) + +(declare (unit lock-queue)) +(declare (uses common)) + +;;====================================================================== +;; attempt to prevent overlapping updates of rollup files by queueing +;; update requests in an sqlite db +;;====================================================================== + +(define (lock-queue:open-db fname) + (let* ((actualfname (conc fname ".lockdb")) + (dbexists (file-exists? actualfname)) + (db (sqlite3:open-database actualfname)) + (handler (make-busy-timeout 136000))) + (if dbexists + db + (begin + (sqlite3:execute + db + "CREATE TABLE IF NOT EXISTS queue ( + id INTEGER PRIMARY KEY, + test_id INTEGER, + start_time INTEGER, + state TEXT, + CONSTRAINT queue_constraint UNIQUE (test_id));") + (sqlite3:execute + db + "CREATE TABLE IF NOT EXISTS runlocks ( + id INTEGER PRIMARY KEY, + test_id INTEGER, + run_lock TEXT, + CONSTRAINT runlock_constraint UNIQUE (run_lock));"))) + (sqlite3:set-busy-handler! db handler) + db)) + +(define (lock-queue:set-state db test-id newstate) + (sqlite3:execute db "UPDATE queue SET state=? WHERE test_id=?;" + newstate + test-id)) + +(define (lock-queue:any-younger? db mystart test-id) + (let ((res #f)) + (sqlite3:for-each-row + (lambda (tid) + ;; Actually this should not be needed as mystart cannot be simultaneously less than and test-id same as + (if (not (equal? tid test-id)) + (set! res tid))) + db + "SELECT test_id FROM queue WHERE start_time > ?;" mystart) + res)) + +(define (lock-queue:get-lock db test-id) + (let ((res #f) + (lckqry (sqlite3:prepare db "SELECT test_id,run_lock FROM runlocks WHERE run_lock='locked';")) + (mklckqry (sqlite3:prepare db "INSERT INTO runlocks (test_id,run_lock) VALUES (?,'locked');"))) + (let ((result + (handle-exceptions + exn + #f + (sqlite3:with-transaction + db + (lambda () + (sqlite3:for-each-row (lambda (tid lockstate) + (set! res (list tid lockstate))) + lckqry) + (if res + (if (equal? (car res) test-id) + #t ;; already have the lock + #f) + (begin + (sqlite3:execute mklckqry test-id) + ;; if no error handled then return #t for got the lock + #t))))))) + (sqlite3:finalize! lckqry) + (sqlite3:finalize! mklckqry) + result))) + +(define (lock-queue:release-lock fname test-id) + (let ((db (lock-queue:open-db fname))) + (sqlite3:execute db "DELETE FROM runlocks WHERE test_id=?;" test-id) + (sqlite3:finalize! db))) + +(define (lock-queue:steal-lock db test-id) + (sqlite3:execute db "DELETE FROM runlocks WHERE run_lock='locked';") + (lock-queue:get-lock db test-it)) + +;; returns #f if ok to skip the task +;; returns #t if ok to proceed with task +;; otherwise waits +;; +(define (lock-queue:wait-turn fname test-id) + (let ((db (lock-queue:open-db fname)) + (mystart (current-seconds))) + (sqlite3:execute + db + "INSERT OR REPLACE INTO queue (test_id,start_time,state) VALUES (?,?,'waiting');" + test-id mystart) + (thread-sleep! 1) ;; give other tests a chance to register + (let ((result + (let loop ((younger-waiting (lock-queue:any-younger? db mystart test-id))) + (if younger-waiting + (begin + ;; no need for us to wait. mark in the lock queue db as skipping + (lock-queue:set-state db test-id "skipping") + #f) ;; let the calling process know that nothing needs to be done + (if (lock-queue:get-lock db test-id) + #t + (if (> (- (current-seconds) mystart) 36000) ;; waited too long, steal the lock + (lock-queue:steal-lock db test-id) + (begin + (thread-sleep! 1) + (loop (lock-queue:any-younger? db mystart test-id))))))))) + (sqlite3:finalize! db) + result))) + + +;; (use trace) +;; (trace lock-queue:get-lock lock-queue:release-lock lock-queue:wait-turn lock-queue:any-younger? lock-queue:set-state) 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.5506) +(define megatest-version 1.5512) Index: megatest.scm ================================================================== --- megatest.scm +++ megatest.scm @@ -108,10 +108,11 @@ -dumpmode json : dump in json format instead of sexpr -show-cmdinfo : dump the command info for a test (run in test environment) Misc -rebuild-db : bring the database schema up to date + -cleanup-db : remove any orphan records, vacuum the db -update-meta : update the tests metadata for all tests -env2file fname : write the environment to fname.csh and fname.sh -setvars VAR1=val1,VAR2=val2 : Add environment variables to a run NB// these are overwritten by values set in config files. -server -|hostname : start the server (reduces contention on megatest.db), use @@ -228,10 +229,11 @@ "-test-paths" ;; get path(s) to a test, ordered by youngest first "-runall" ;; run all tests "-remove-runs" "-rebuild-db" + "-cleanup-db" "-rollup" "-update-meta" "-gen-megatest-area" "-logging" @@ -251,14 +253,39 @@ (print megatest-version) (exit))) (define *didsomething* #f) -(if (and (or (args:get-arg "-list-targets") - (args:get-arg "-list-db-targets")) - (not (args:get-arg "-transport"))) - (hash-table-set! args:arg-hash "-transport" "fs")) +;; Overall exit handling setup immediately +;; +(if (or (args:get-arg "-process-reap")) + ;; (args:get-arg "-runtests") + ;; (args:get-arg "-execute") + ;; (args:get-arg "-remove-runs") + ;; (args:get-arg "-runstep")) + (let ((original-exit (exit-handler))) + (exit-handler (lambda (#!optional (exit-code 0)) + (printf "Preparing to exit with exit code ~A ...\n" exit-code) + (for-each + (lambda (pid) + (handle-exceptions + exn + #t + (let-values (((pid-val exit-status exit-code) (process-wait pid #t))) + (if (or (eq? pid-val pid) + (eq? pid-val 0)) + (begin + (printf "Sending signal/term to ~A\n" pid) + (process-signal pid signal/term)))))) + (process:children #f)) + (original-exit exit-code))))) + +;; Force default transport to fs +;; (if ;; (and (or (args:get-arg "-list-targets") +;; ;; (args:get-arg "-list-db-targets")) +;; (not (args:get-arg "-transport")) +;; (hash-table-set! args:arg-hash "-transport" "fs")) ;;====================================================================== ;; Misc setup stuff ;;====================================================================== @@ -300,48 +327,83 @@ ;; Start the server - can be done in conjunction with -runall or -runtests (one day...) ;; we start the server if not running else start the client thread ;;====================================================================== (if (args:get-arg "-server") - (let ((transport (args:get-arg "-transport" "http"))) + + ;; Server? Start up here. + ;; + (let ((tl (setup-for-run)) + (transport (or (configf:lookup *configdat* "setup" "transport") + (args:get-arg "-transport" "http")))) (debug:print 2 "Launching server using transport " transport) (server:launch (string->symbol transport))) - (if (not (null? (lset-intersection + + ;; Not a server? This section will decide how to communicate + ;; + ;; Setup client for all expect listed here + (if (null? (lset-intersection equal? (hash-table-keys args:arg-hash) - '("-runtests" "-list-runs" "-rollup" - "-remove-runs" "-lock" "-unlock" - "-update-meta" "-extract-ods")))) + '("-list-servers" + "-stop-server" + "-show-cmdinfo"))) (if (setup-for-run) - (let loop ((servers (open-run-close tasks:get-best-server tasks:open-db)) - (trycount 0)) - (if (or (not servers) - (null? servers)) - (begin - (if (even? trycount) ;; just do the server start every other time through this loop (every 8 seconds) - (begin - (debug:print 0 "INFO: Starting server as none running ...") - ;; (server:launch (string->symbol (args:get-arg "-transport" "http")))) - ;; no need to use fork, no need to do the list-servers trick. Just start the damn server, it will exit on it's own - ;; if there is an existing server - (system "megatest -server - -daemonize") - (thread-sleep! 3) - ;; (process-run (car (argv)) (list "-server" "-" "-daemonize" "-transport" (args:get-arg "-transport" "http"))) - ;; (system (conc "megatest -list-servers | egrep '" megatest-version ".*alive' || megatest -server - -daemonize && sleep 3")) - ;; (process-fork (lambda () - ;; (daemon:ize) - ;; (server:launch (string->symbol (args:get-arg "-transport" "http"))))) - ) - (begin - (debug:print-info 0 "Waiting for server to start") - (thread-sleep! 4))) - (if (< trycount 10) - (loop (open-run-close tasks:get-best-server tasks:open-db) - (+ trycount 1)) - (debug:print 0 "WARNING: Couldn't start or find a server."))) - (debug:print 0 "INFO: Server(s) running " servers) - ))))) + (begin + + ;; if not list or kill then start a client (if appropriate) + (if (or (args-defined? "-h" "-version" "-gen-megatest-area" "-gen-megatest-test") + (eq? (length (hash-table-keys args:arg-hash)) 0)) + (debug:print-info 1 "Server connection not needed") + ;; ok, so lets connect to the server + (let* ((transport-from-config (configf:lookup *configdat* "setup" "transport")) + (transport-from-cmdln (args:get-arg "-transport")) + (transport-from-cmdinfo (if (getenv "MT_CMDINFO") + (let ((res (assoc 'transport + (read + (open-input-string + (base64:base64-decode + (getenv "MT_CMDINFO"))))))) + (if res (cadr res) #f)) + #f)) + (chosen-transport (string->symbol (or transport-from-cmdln + 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) + (server:ensure-running) + (client:launch)) + (else ;; (fs) + (set! *transport-type* 'fs) + (set! *megatest-db* (open-db)))))))))) +;; (cond +;; ;; command line overrides other mechanisms +;; (transport-from-cmdln +;; (if (equal? transport-from-cmdln "fs") +;; (set! *transport-type* 'fs) +;; (begin +;; (server:ensure-running) +;; (client:launch)))) +;; ;; cmdinfo is second priority +;; (transport-from-cmdinfo +;; (if (equal? transport-from-cmdinfo "fs") +;; (set! *transport-type* 'fs) +;; (begin +;; (server:ensure-running) +;; (client:launch)))) +;; ;; config file is next highest priority for determinining transport +;; (transport-from-config +;; (if (equal? transport-from-config "fs") +;; (set! *transport-type* 'fs) +;; (begin +;; (server:ensure-running) +;; (client:launch)))) +;; (else +;; (set! *transport-type* 'fs))))))))) (if (or (args:get-arg "-list-servers") (args:get-arg "-stop-server")) (let ((tl (setup-for-run))) (if tl @@ -386,17 +448,11 @@ (tasks:kill-server status hostname pullport pid transport))))) servers) (debug:print-info 1 "Done with listservers") (set! *didsomething* #t) (exit)) ;; must do, would have to add checks to many/all calls below - (exit))) - ;; if not list or kill then start a client (if appropriate) - (if (or (args-defined? "-h" "-version" "-gen-megatest-area" "-gen-megatest-test") - (eq? (length (hash-table-keys args:arg-hash)) 0)) - (debug:print-info 1 "Server connection not needed") - ;; ok, so lets connect to the server - (client:launch))) + (exit)))) ;;====================================================================== ;; Weird special calls that need to run *after* the server has started? ;;====================================================================== @@ -439,11 +495,12 @@ (else (debug:print 0 "ERROR: -dumpmode of " (args:get-arg "-dumpmode") " not recognised"))) (set! *didsomething* #t))) (if (args:get-arg "-show-config") - (let ((data *configdat*)) ;; (read-config "megatest.config" #f #t))) + (let ((tl (setup-for-run)) + (data *configdat*)) ;; (read-config "megatest.config" #f #t))) ;; keep this one local (cond ((not (args:get-arg "-dumpmode")) (pp (hash-table->alist data))) ((string=? (args:get-arg "-dumpmode") "json") @@ -451,15 +508,17 @@ (else (debug:print 0 "ERROR: -dumpmode of " (args:get-arg "-dumpmode") " not recognised"))) (set! *didsomething* #t))) (if (args:get-arg "-show-cmdinfo") - (let ((data (read (open-input-string (base64:base64-decode (getenv "MT_CMDINFO")))))) - (if (equal? (args:get-arg "-dumpmode") "json") - (json-write data) - (pp data)) - (set! *didsomething* #t))) + (if (getenv "MT_CMDINFO") + (let ((data (read (open-input-string (base64:base64-decode (getenv "MT_CMDINFO")))))) + (if (equal? (args:get-arg "-dumpmode") "json") + (json-write data) + (pp data)) + (set! *didsomething* #t)) + (debug:print-info 0 "environment variable MT_CMDINFO is not set"))) ;;====================================================================== ;; Remove old run(s) ;;====================================================================== @@ -693,11 +752,11 @@ (status (args:get-arg ":status")) (target (args:get-arg "-target")) (toppath (assoc/default 'toppath cmdinfo))) (change-directory toppath) ;; (set! *runremote* runremote) - (set! *transport-type* (string->symbol transport)) + ;; (set! *transport-type* (string->symbol transport)) (if (not target) (begin (debug:print 0 "ERROR: -target is required.") (exit 1))) (if (not (setup-for-run)) @@ -744,11 +803,11 @@ (state (args:get-arg ":state")) (status (args:get-arg ":status")) (target (args:get-arg "-target"))) (change-directory testpath) ;; (set! *runremote* runremote) - (set! *transport-type* (string->symbol transport)) + ;; (set! *transport-type* (string->symbol transport)) (if (not target) (begin (debug:print 0 "ERROR: -target is required.") (exit 1))) (if (not (setup-for-run)) @@ -786,12 +845,12 @@ (let ((db #f) (outputfile (args:get-arg "-extract-ods")) (runspatt (args:get-arg ":runname")) (pathmod (args:get-arg "-pathmod"))) ;; (keyvalalist (keys->alist keys "%"))) - (debug:print 2 "Extract ods, outputfile: " outputfile " runspatt: " runspatt " keyvalalist: " keyvals) - (cdb:remote-run db:extract-ods-file db outputfile keyvalalist (if runspatt runspatt "%") pathmod))))) + (debug:print 2 "Extract ods, outputfile: " outputfile " runspatt: " runspatt " keyvals: " keyvals) + (cdb:remote-run db:extract-ods-file db outputfile keyvals (if runspatt runspatt "%") pathmod))))) ;;====================================================================== ;; execute the test ;; - gets called on remote host ;; - receives info from the -execute param @@ -825,11 +884,12 @@ (itemdat (assoc/default 'itemdat cmdinfo)) (work-area (assoc/default 'work-area cmdinfo)) (db #f)) (change-directory testpath) ;; (set! *runremote* runremote) - (set! *transport-type* (string->symbol transport)) + ;; The transport is handled earlier in the loading process of megatest. + ;; (set! *transport-type* (string->symbol transport)) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) (if (and state status) @@ -876,18 +936,19 @@ (itemdat (assoc/default 'itemdat cmdinfo)) (work-area (assoc/default 'work-area cmdinfo)) (db #f) ;; (open-db)) (state (args:get-arg ":state")) (status (args:get-arg ":status"))) - (change-directory testpath) ;; (set! *runremote* runremote) - (set! *transport-type* (string->symbol transport)) + ;; (set! *transport-type* (string->symbol transport)) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) + (if (args:get-arg "-runstep")(debug:print-info 1 "Running -runstep, first change to directory " work-area)) + (change-directory work-area) ;; can setup as client for server mode now ;; (client:setup) (if (args:get-arg "-load-test-data") ;; has sub commands that are rdb: @@ -899,11 +960,11 @@ (if (args:get-arg "-set-toplog") ;; DO NOT run remote (tests:test-set-toplog! db run-id test-name (args:get-arg "-set-toplog"))) (if (args:get-arg "-summarize-items") ;; DO NOT run remote - (tests:summarize-items db run-id test-name #t)) ;; do force here + (tests:summarize-items db run-id test-id test-name #t)) ;; do force here (if (args:get-arg "-runstep") (if (null? remargs) (begin (debug:print 0 "ERROR: nothing specified to run!") (if db (sqlite3:finalize! db)) @@ -924,15 +985,15 @@ ") " redir " " logfile))) ;; mark the start of the test ;; DO NOT run remote (db:teststep-set-status! db test-id stepname "start" "n/a" (args:get-arg "-m") logfile work-area: work-area) ;; run the test step - (debug:print-info 2 "Running \"" fullcmd "\"") + (debug:print-info 2 "Running \"" fullcmd "\" in directory \"" startingdir) (change-directory startingdir) (set! exitstat (system fullcmd)) ;; cmd params)) (set! *globalexitstatus* exitstat) - (change-directory testpath) + ;; (change-directory testpath) ;; run logpro if applicable ;; (process-run "ls" (list "/foo" "2>&1" "blah.log")) (if logprofile (let* ((htmllogfile (conc stepname ".html")) (oldexitstat exitstat) (cmd (string-intersperse (list "logpro" logprofile htmllogfile "<" logfile ">" (conc stepname "_logpro.log")) " "))) @@ -1007,11 +1068,11 @@ (let ((testname (args:get-arg "-gen-megatest-test"))) (genexample:mk-megatest-test testname) (set! *didsomething* #t))) ;;====================================================================== -;; Update the database schema on request +;; Update the database schema, clean up the db ;;====================================================================== (if (args:get-arg "-rebuild-db") (begin (if (not (setup-for-run)) @@ -1019,10 +1080,20 @@ (debug:print 0 "Failed to setup, exiting") (exit 1))) ;; keep this one local (open-run-close patch-db #f) (set! *didsomething* #t))) + +(if (args:get-arg "-cleanup-db") + (begin + (if (not (setup-for-run)) + (begin + (debug:print 0 "Failed to setup, exiting") + (exit 1))) + ;; keep this one local + (open-run-close db:clean-up #f) + (set! *didsomething* #t))) ;;====================================================================== ;; Wait on a run to complete ;;====================================================================== @@ -1060,12 +1131,10 @@ (db (if toppath (open-db) #f))) (if db (begin (set! *db* db) (set! *client-non-blocking-mode* #t) - ;; (client:setup) - ;; (client:launch) (import readline) (import apropos) (gnu-history-install-file-manager (string-append (or (get-environment-variable "HOME") ".") "/.megatest_history")) Index: mt.scm ================================================================== --- mt.scm +++ mt.scm @@ -39,27 +39,46 @@ ;; ;; Use: (db-get-value-by-header (db:get-header runinfo)(db:get-row runinfo)) ;; to extract info from the structure returned ;; (define (mt:get-runs-by-patt keys runnamepatt targpatt) - (cdb:remote-run db:get-runs-by-patt #f 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) + (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) + (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) + (loop next-batch + full-list + new-offset + limit)) + (vector header full-list))))) ;;====================================================================== ;; T E S T S ;;====================================================================== -(define (mt:get-tests-for-run run-id testpatt states status #!key (not-in #t) (sort-by #f) (qryvals #f)) - (let loop ((testsdat (cdb:remote-run db:get-tests-for-run #f run-id testpatt states status 0 500 not-in sort-by qryvals: qryvals)) +(define (mt:get-tests-for-run run-id testpatt states status #!key (not-in #t) (sort-by 'event_time) (sort-order "ASC") (qryvals #f)) + (let loop ((testsdat (cdb:remote-run db:get-tests-for-run #f run-id testpatt states status 0 500 not-in sort-by sort-order qryvals: qryvals)) (res '()) (offset 0) (limit 500)) (let* ((full-list (append res testsdat)) (have-more (eq? (length testsdat) limit))) (if have-more (let ((new-offset (+ offset limit))) (debug:print-info 4 "More than " limit " tests, have " (length full-list) " tests so far.") - (loop (cdb:remote-run db:get-tests-for-run #f run-id testpatt states status new-offset limit not-in sort-by qryvals: qryvals) + (loop (cdb:remote-run db:get-tests-for-run #f run-id testpatt states status new-offset limit not-in sort-by sort-order qryvals: qryvals) full-list new-offset limit)) full-list)))) @@ -66,5 +85,94 @@ (define (mt:get-prereqs-not-met run-id waitons ref-item-path #!key (mode 'normal)) (db:get-prereqs-not-met run-id waitons ref-item-path mode: mode)) (define (mt:get-run-stats) (cdb:remote-run db:get-run-stats #f)) + +;;====================================================================== +;; T R I G G E R S +;;====================================================================== + +(define (mt:process-triggers test-id newstate newstatus) + (let* ((test-dat (mt:lazy-get-test-info-by-id test-id)) + (test-rundir (db:test-get-rundir test-dat)) + (test-name (db:test-get-testname test-dat)) + (tconfig #f) + (state (if newstate newstate (db:test-get-state test-dat))) + (status (if newstatus newstatus (db:test-get-status test-dat)))) + (if (and (file-exists? test-rundir) + (directory? test-rundir)) + (begin + (push-directory test-rundir) + (set! tconfig (mt:lazy-read-test-config test-name)) + (pop-directory) + (for-each (lambda (trigger) + (let ((cmd (configf:lookup tconfig "triggers" trigger)) + (logf (conc test-rundir "/last-trigger.log"))) + (if cmd + ;; Putting the commandline into ( )'s means no control over the shell. + ;; stdout and stderr will be caught in the NBFAKE or mt_launch.log files + ;; or equivalent. No need to do this. Just run it? + (let ((fullcmd (conc cmd " " test-id " " test-rundir " " trigger "&"))) + (debug:print-info 0 "TRIGGERED on " trigger ", running command " fullcmd) + (process-run fullcmd))))) + (list + (conc state "/" status) + (conc state "/") + (conc "/" status))))))) + +;;====================================================================== +;; S T A T E A N D S T A T U S F O R T E S T S +;;====================================================================== + +(define (mt:roll-up-pass-fail-counts run-id test-name item-path status) + (if (and (not (equal? item-path "")) + (member status '("PASS" "WARN" "FAIL" "WAIVED" "RUNNING" "CHECK" "SKIP"))) + (begin + (cdb:update-pass-fail-counts *runremote* run-id test-name) + (if (equal? status "RUNNING") + (cdb:top-test-set-running *runremote* run-id test-name) + (cdb:top-test-set-per-pf-counts *runremote* run-id test-name)) + #f) + #f)) + +;; speed up for common cases with a little logic +(define (mt:test-set-state-status-by-id test-id newstate newstatus newcomment) + (cond + ((and newstate newstatus newcomment) + (cdb:client-call *runremote* 'state-status-msg #t *default-numtries* newstate newstatus newcomment test-id)) + ((and newstate newstatus) + (cdb:client-call *runremote* 'state-status #t *default-numtries* newstate newstatus test-id)) + (else + (if newstate (cdb:client-call *runremote* 'set-test-state #t *default-numtries* newstate test-id)) + (if newstatus (cdb:client-call *runremote* 'set-test-status #t *default-numtries* newstatus test-id)) + (if newcomment (cdb:client-call *runremote* 'set-test-comment #t *default-numtries* newcomment test-id)))) + (mt:process-triggers test-id newstate newstatus) + #t) + +(define (mt:lazy-get-test-info-by-id test-id) + (let* ((tdat (hash-table-ref/default *test-info* test-id #f))) + (if (and tdat + (< (current-seconds)(+ (vector-ref tdat 0) 10))) + (vector-ref tdat 1) + ;; no need to update *test-info* as that is done in cdb:get-test-info-by-id + (cdb:get-test-info-by-id *runremote* test-id)))) + +(define (mt:lazy-read-test-config test-name) + (let ((tconf (hash-table-ref/default *testconfigs* test-name #f))) + (if tconf + tconf + (let ((test-dirs (tests:get-tests-search-path *configdat*))) + (let loop ((hed (car test-dirs)) + (tal (cdr test-dirs))) + (let ((tconfig-file (conc hed "/" test-name "/testconfig"))) + (if (and (file-exists? tconfig-file) + (file-read-access? tconfig-file)) + (let ((newtcfg (read-config tconfig-file #f #f))) ;; NOTE: Does NOT run [system ...] + (hash-table-set! *testconfigs* test-name newtcfg) + newtcfg) + (if (null? tal) + (begin + (debug:print 0 "ERROR: No readable testconfig found for " test-name) + #f) + (loop (car tal)(cdr tal)))))))))) + Index: process.scm ================================================================== --- process.scm +++ process.scm @@ -109,5 +109,21 @@ (begin (thread-sleep! 2) (loop (+ i 1))) (values pid-val exit-status exit-code)))))) +;;====================================================================== +;; MISC PROCESS RELATED STUFF +;;====================================================================== + +(define (process:children proc) + (with-input-from-pipe + (conc "ps h --ppid " (current-process-id) " -o pid") + (lambda () + (let loop ((inl (read-line)) + (res '())) + (if (eof-object? inl) + (reverse res) + (let ((pid (string->number inl))) + (if proc (proc pid)) + (loop (read-line) (cons pid res)))))))) + Index: runconfig.scm ================================================================== --- runconfig.scm +++ runconfig.scm @@ -40,11 +40,14 @@ (if section-dat (for-each (lambda (envvar) (let ((val (cadr (assoc envvar section-dat)))) (hash-table-set! whatfound section (+ (hash-table-ref/default whatfound section 0) 1)) - (if change-env (setenv envvar val)) + (if (and (string? envvar) + (string? val) + change-env) + (setenv envvar val)) (hash-table-set! finaldat envvar val))) (map car section-dat))))) sections) (if already-seen (begin Index: runs.scm ================================================================== --- runs.scm +++ runs.scm @@ -135,10 +135,30 @@ ;; (define *last-num-running-tests* 0) (define *runs:can-run-more-tests-count* 0) (define (runs:shrink-can-run-more-tests-count) ;; the db is a dummy var so we can use cdb:remote-run (set! *runs:can-run-more-tests-count* 0)) ;; (/ *runs:can-run-more-tests-count* 2))) + +;; Temporary globals. Move these into the logic or into common +;; +(define *seen-cant-run-tests* (make-hash-table)) ;; use to track tests that we suspect cannot be run +(define (runs:inc-cant-run-tests testname) + (hash-table-set! *seen-cant-run-tests* testname + (+ (hash-table-ref/default *seen-cant-run-tests* testname 0) 1))) +(define (runs:can-keep-running? testname n) + (< (hash-table-ref/default *seen-cant-run-tests* testname 0) n)) + +(define *runs:denoise* (make-hash-table)) ;; key => last-time-ran + +(define (runs:lownoise key waitval) + (let ((lasttime (hash-table-ref/default *runs:denoise* key 0)) + (currtime (current-seconds))) + (if (> (- currtime lasttime) waitval) + (begin + (hash-table-set! *runs:denoise* key currtime) + #t) + #f))) (define (runs:can-run-more-tests 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))) @@ -155,12 +175,13 @@ (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)) - (debug:print 0 "WARNING: Max running jobs exceeded, current number running: " num-running - ", max_concurrent_jobs: " 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)) @@ -174,27 +195,29 @@ ;; 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 (cdb:remote-run db:register-run #f 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)) - (all-test-names (tests:get-valid-tests *toppath* "%"))) ;; we need a list of all valid tests to check waiton names + (let* ((keys (keys:config-get-fields *configdat*)) + (keyvals (keys:target->keyval keys target)) + (run-id (cdb:remote-run db:register-run #f 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)) + (all-tests-registry (tests:get-all)) ;; (tests:get-valid-tests (make-hash-table) test-search-path)) ;; all valid tests to check waiton names + (all-test-names (hash-table-keys all-tests-registry)) + (test-names (tests:filter-test-names all-test-names test-patts))) (set-megatest-env-vars run-id inkeys: keys) ;; these may be needed by the launching process (if (file-exists? runconfigf) (setup-env-defaults runconfigf run-id *already-seen-runconfig-info* keyvals "pre-launch-env-vars") (debug:print 0 "WARNING: You do not have a run config file: " runconfigf)) ;; look up all tests matching the comma separated list of globs in ;; test-patts (using % as wildcard) - (set! test-names (delete-duplicates (tests:get-valid-tests *toppath* test-patts))) + ;; (set! test-names (delete-duplicates (tests:get-valid-tests *toppath* test-patts))) (debug:print-info 0 "test names " test-names) ;; on the first pass or call to run-tests set FAILS to NOT_STARTED if ;; -keepgoing is specified (if (eq? *passnum* 0) @@ -207,16 +230,19 @@ (cdb:remote-run db:set-tests-state-status #f run-id test-names #f "FAIL" "NOT_STARTED" "FAIL"))) ;; now add non-directly referenced dependencies (i.e. waiton) ;;====================================================================== ;; refactoring this block into tests:get-full-data + ;; + ;; What happended, this code is now duplicated in tests!? + ;; ;;====================================================================== (if (not (null? test-names)) (let loop ((hed (car test-names)) (tal (cdr test-names))) ;; 'return-procs tells the config reader to prep running system but return a proc (change-directory *toppath*) ;; PLEASE OPTIMIZE ME!!! I think this should be a no-op but there are several places where change-directories could be happening. - (let* ((config (tests:get-testconfig hed 'return-procs)) + (let* ((config (tests:get-testconfig hed all-tests-registry 'return-procs)) (waitons (let ((instr (if config (config-lookup config "requirements" "waiton") (begin ;; No config means this is a non-existant test (debug:print 0 "ERROR: non-existent required test \"" hed "\"") (exit 1))))) @@ -230,11 +256,11 @@ ((string? instr) instr) (else ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print 0 "ERROR: something went wrong in processing waitons for test " hed) ""))))) (filter (lambda (x) - (if (member x all-test-names) + (if (hash-table-ref/default all-tests-registry x #f) #t (begin (debug:print 0 "ERROR: test " hed " has unrecognised waiton testname " x) #f))) newwaitons))))) @@ -295,11 +321,11 @@ (debug:print-info 1 "Adding " required-tests " to the run queue")) ;; NOTE: these are all parent tests, items are not expanded yet. (debug:print-info 4 "test-records=" (hash-table->alist test-records)) (let ((reglen (configf:lookup *configdat* "setup" "runqueue"))) (if (> (length (hash-table-keys test-records)) 0) - (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen)) + (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen) all-tests-registry) (debug:print-info 0 "No tests to run"))) (debug:print-info 4 "All done by here"))) ;; loop logic. These are used in runs:run-tests-queue to make it a bit more readable. @@ -339,11 +365,13 @@ (cdr reg) (if (null? tal) ;; if tal is null and reg not full then '() as reg contents moved to tal '() reg))) -(define (runs:expand-items hed tal reg reruns regfull newtal jobgroup max-concurrent-jobs run-id waitons item-path testmode test-record can-run-more items runname tconfig reglen) +(define runs:nothing-left-in-queue-count 0) + +(define (runs:expand-items hed tal reg reruns regfull newtal jobgroup max-concurrent-jobs run-id waitons item-path testmode test-record can-run-more items runname tconfig reglen test-registry) (let* ((loop-list (list hed tal reg reruns)) (prereqs-not-met (mt:get-prereqs-not-met run-id waitons item-path mode: testmode)) (fails (runs:calc-fails prereqs-not-met)) (non-completed (runs:calc-not-completed prereqs-not-met))) (debug:print-info 4 "START OF INNER COND #2 " @@ -356,13 +384,37 @@ "\n (eq? testmode 'toplevel): " (eq? testmode 'toplevel) "\n (null? non-completed): " (null? non-completed) "\n reruns: " reruns "\n items: " items "\n can-run-more: " can-run-more) + (cond ;; all prereqs met, fire off the test ;; or, if it is a 'toplevel test and all prereqs not met are COMPLETED then launch + + ((member (hash-table-ref/default test-registry (runs:make-full-test-name hed item-path) 'n/a) + '(DONOTRUN removed)) ;; *common:cant-run-states-sym*) ;; '(COMPLETED KILLED WAIVED UNKNOWN INCOMPLETE)) ;; try to catch repeat processing of COMPLETED tests here + (debug:print-info 1 "Test " hed " set to \"" (hash-table-ref test-registry (runs:make-full-test-name hed item-path)) "\". Removing it from the queue") + (if (or (not (null? tal)) + (not (null? reg))) + (list (runs:queue-next-hed tal reg reglen regfull) + (runs:queue-next-tal tal reg reglen regfull) + (runs:queue-next-reg tal reg reglen regfull) + reruns) + (begin + (debug:print-info 0 "Nothing left in the queue!") + ;; If get here twice then we know we've tried to expand all items + ;; since there must be a logic issue with the handling of loops in the + ;; items expand phase we will brute force an exit here. + (if (> runs:nothing-left-in-queue-count 2) + (begin + (debug:print 0 "WARNING: this condition is triggered when there were no items to expand and nothing to run. Please check your run for completeness") + (exit 0)) + (set! runs:nothing-left-in-queue-count (+ runs:nothing-left-in-queue-count 1))) + #f))) + + ;; ((or (null? prereqs-not-met) (and (eq? testmode 'toplevel) (null? non-completed))) (debug:print-info 4 "runs:expand-items: (or (null? prereqs-not-met) (and (eq? testmode 'toplevel)(null? non-completed)))") (let ((test-name (tests:testqueue-get-testname test-record))) @@ -376,36 +428,151 @@ (list hed tal reg reruns)) (begin (debug:print 0 "ERROR: The proc from reading the setup did not yield a list - please report this") (exit 1)))))) - ((null? fails) - (debug:print-info 4 "fails is null, moving on in the queue but keeping " hed " for now") - ;; num-retries code was here - ;; we use this opportunity to move contents of reg to tal - (list (car newtal)(append (cdr newtal) reg) '() reruns)) ;; an issue with prereqs not yet met? + ((and (null? fails) + (not (null? non-completed))) + (let* ((allinqueue (map (lambda (x)(if (string? x) x (db:test-get-testname x))) + (append newtal reruns))) + ;; prereqstrs is a list of test names as strings that are prereqs for hed + (prereqstrs (delete-duplicates (map (lambda (x)(if (string? x) x (db:test-get-testname x))) + prereqs-not-met))) + ;; a prereq that is not found in allinqueue will be put in the notinqueue list + ;; + ;; (notinqueue (filter (lambda (x) + ;; (not (member x allinqueue))) + ;; prereqstrs)) + (give-up #f)) + + ;; We can get here when a prereq has not been run due to *it* having a prereq that failed. + ;; We need to use this to dequeue this item as CANNOTRUN + (for-each (lambda (prereq) + (if (eq? (hash-table-ref/default test-registry prereq 'justfine) 'CANNOTRUN) + (set! give-up #t))) + prereqstrs) + (if (and give-up + (not (and (null? tal)(null? reg)))) + (begin + (debug:print 1 "WARNING: test " hed " has no discarded prerequisites, removing it from the queue") + (list (runs:queue-next-hed tal reg reglen regfull) + (runs:queue-next-tal tal reg reglen regfull) + (runs:queue-next-reg tal reg reglen regfull) + reruns)) + (list (car newtal)(append (cdr newtal) reg) '() reruns)))) + + + ;; (debug:print-info 1 "allinqueue: " allinqueue) + ;; (debug:print-info 1 "prereqstrs: " prereqstrs) + ;; (debug:print-info 1 "notinqueue: " notinqueue) + ;; (debug:print-info 1 "tal: " tal) + ;; (debug:print-info 1 "newtal: " newtal) + ;; (debug:print-info 1 "reg: " reg) + +;; == == ;; num-retries code was here +;; == == ;; we use this opportunity to move contents of reg to tal +;; == == ;; but also lets check that the prerequisites are all in the newtal or reruns lists +;; == == +;; == == (let* ((allinqueue (map (lambda (x)(if (string? x) x (db:test-get-testname x))) +;; == == (append newtal reruns))) +;; == == ;; prereqstrs is a list of test names as strings that are prereqs for hed +;; == == (prereqstrs (map (lambda (x)(if (string? x) x (db:test-get-testname x))) +;; == == prereqs-not-met)) +;; == == ;; a prereq that is not found in allinqueue will be put in the notinqueue list +;; == == ;; +;; == == (notinqueue (filter (lambda (x) +;; == == (not (member x allinqueue))) +;; == == prereqstrs))) +;; == == (if (not (null? notinqueue)) +;; == == (if (runs:can-keep-running? hed 5) ;; try five times +;; == == (begin +;; == == (debug:print-info 4 "increment cant-run-tests for " hed) +;; == == (runs:inc-cant-run-tests hed) +;; == == (list (car newtal)(append (cdr newtal) reg) '() reruns)) +;; == == (begin +;; == == +;; == == (if (runs:lownoise (conc "no fails prereq, null notinqueue " hed) 30) +;; == == (begin +;; == == (debug:print 1 "WARNING: test " hed " has no failed prerequisites but does have prerequistes that are NOT in the queue: " (string-intersperse notinqueue ", ")) +;; == == (debug:print-info 4 "allinqueue: " allinqueue) +;; == == (debug:print-info 4 "prereqstrs: " prereqstrs) +;; == == (debug:print-info 4 "notinqueue: " notinqueue))) +;; == == (if (and (null? tal)(null? reg)) +;; == == (list (car newtal)(append (cdr newtal) reg) '() reruns) +;; == == (list (runs:queue-next-hed tal reg reglen regfull) +;; == == (runs:queue-next-tal tal reg reglen regfull) +;; == == (runs:queue-next-reg tal reg reglen regfull) +;; == == reruns)))) +;; == == ;; have prereqs in queue, keep going. +;; == == (begin +;; == == (if (runs:lownoise (conc "no fails prereq " hed) 30) +;; == == (debug:print-info 1 "no fails in prerequisites for " hed ", waiting on tests; " +;; == == (string-intersperse (map (lambda (x) +;; == == (if (string? x) +;; == == x +;; == == (runs:make-full-test-name (db:test-get-testname x) +;; == == (db:test-get-item-path x)))) +;; == == non-completed) ", ") +;; == == ". Delaying launch of " hed ".")) +;; == == (list (car newtal)(append (cdr newtal) reg) '() reruns))))) ;; an issue with prereqs not yet met? + + ((and (null? fails) + (null? non-completed)) + (if (runs:can-keep-running? hed 5) + (begin + (runs:inc-cant-run-tests hed) + (debug:print-info 1 "no fails in prerequisites for " hed " but also none running, keeping " hed " for now. Try count: " (hash-table-ref/default *seen-cant-run-tests* hed 0)) + ;; num-retries code was here + ;; we use this opportunity to move contents of reg to tal + (list (car newtal)(append (cdr newtal) reg) '() reruns)) ;; an issue with prereqs not yet met? + (begin + (debug:print-info 1 "no fails in prerequisites for " hed " but nothing seen running in a while, dropping test " hed " from the run queue") + (list (runs:queue-next-hed tal reg reglen regfull) + (runs:queue-next-tal tal reg reglen regfull) + (runs:queue-next-reg tal reg reglen regfull) + reruns)))) ((and (not (null? fails))(eq? testmode 'normal)) (debug:print-info 1 "test " hed " (mode=" testmode ") has failed prerequisite(s); " (string-intersperse (map (lambda (t)(conc (db:test-get-testname t) ":" (db:test-get-state t)"/"(db:test-get-status t))) fails) ", ") ", removing it from to-do list") (if (or (not (null? reg))(not (null? tal))) - (list (runs:queue-next-hed tal reg reglen regfull) - (runs:queue-next-tal tal reg reglen regfull) - (runs:queue-next-reg tal reg reglen regfull) - (cons hed reruns)) + (begin + (hash-table-set! test-registry hed 'CANNOTRUN) + (list (runs:queue-next-hed tal reg reglen regfull) + (runs:queue-next-tal tal reg reglen regfull) + (runs:queue-next-reg tal reg reglen regfull) + (cons hed reruns))) #f)) ;; #f flags do not loop + ((and (not (null? fails))(eq? testmode 'toplevel)) + (if (or (not (null? reg))(not (null? tal))) + (list (car newtal)(append (cdr newtal) reg) '() reruns) + #f)) (else - (debug:print 4 "ERROR: No handler for this condition.") - (list (car newtal)(cdr newtal) reg reruns))))) + (debug:print 1 "WARNING: FAILS or incomplete tests are preventing completion of this run. Dropping test " hed " from the run queue") + (list (runs:queue-next-hed tal reg reglen regfull) + (runs:queue-next-tal tal reg reglen regfull) + (runs:queue-next-reg tal reg reglen regfull) + reruns))))) ;; (list (car newtal)(cdr newtal) reg reruns))))) + +(define (runs:mixed-list-testname-and-testrec->list-of-strings inlst) + (map (lambda (t) + (cond + ((vector? t) + (conc (db:test-get-state t) "/" (db:test-get-status t))) + ((string? t) + t) + (else + (conc t)))) + inlst)) -(define (runs:process-expanded-tests hed tal reg reruns reglen regfull test-record runname test-name item-path jobgroup max-concurrent-jobs run-id waitons item-path testmode test-patts required-tests test-registry registry-mutex flags keyvals run-info newtal) +(define (runs:process-expanded-tests hed tal reg reruns reglen regfull test-record runname test-name item-path jobgroup max-concurrent-jobs run-id waitons item-path testmode test-patts required-tests test-registry registry-mutex flags keyvals run-info newtal all-tests-registry) (let* ((run-limits-info (runs:can-run-more-tests jobgroup max-concurrent-jobs)) ;; look at the test jobgroup and tot jobs running (have-resources (car run-limits-info)) (num-running (list-ref run-limits-info 1)) - (num-running-in-jobgroup (list-ref run-limits-info 2)) + (num-running-in-jobgroup (list-ref run-limits-info 2)) (max-concurrent-jobs (list-ref run-limits-info 3)) (job-group-limit (list-ref run-limits-info 4)) (prereqs-not-met (mt:get-prereqs-not-met run-id waitons item-path mode: testmode)) (fails (runs:calc-fails prereqs-not-met)) (non-completed (runs:calc-not-completed prereqs-not-met)) @@ -416,10 +583,13 @@ (if (vector? t) (conc (db:test-get-state t) "/" (db:test-get-status t)) (conc " WARNING: t is not a vector=" t ))) prereqs-not-met) ", ") ") fails: " fails) + (if (not (null? prereqs-not-met)) + (debug:print-info 1 "waiting on tests; " (string-intersperse (runs:mixed-list-testname-and-testrec->list-of-strings prereqs-not-met) ", "))) + ;; Don't know at this time if the test have been launched at some time in the past ;; i.e. is this a re-launch? (debug:print-info 4 "run-limits-info = " run-limits-info) (cond @@ -439,23 +609,27 @@ ;; Register tests ;; ((not (hash-table-ref/default test-registry (runs:make-full-test-name test-name item-path) #f)) (debug:print-info 4 "Pre-registering test " test-name "/" item-path " to create placeholder" ) - (let ((th (make-thread (lambda () - (mutex-lock! registry-mutex) - (hash-table-set! test-registry (runs:make-full-test-name test-name item-path) 'start) - (mutex-unlock! registry-mutex) - ;; If haven't done it before register a top level test if this is an itemized test - (if (not (eq? (hash-table-ref/default test-registry (runs:make-full-test-name test-name "") #f) 'done)) - (cdb:tests-register-test *runremote* run-id test-name "")) - (cdb:tests-register-test *runremote* run-id test-name item-path) - (mutex-lock! registry-mutex) - (hash-table-set! test-registry (runs:make-full-test-name test-name item-path) 'done) - (mutex-unlock! registry-mutex)) - (conc test-name "/" item-path)))) - (thread-start! th)) + (if (eq? *transport-type* 'fs) ;; no point in parallel registration if use fs + (begin + (cdb:tests-register-test *runremote* run-id test-name item-path) + (hash-table-set! test-registry (runs:make-full-test-name test-name item-path) 'done)) + (let ((th (make-thread (lambda () + (mutex-lock! registry-mutex) + (hash-table-set! test-registry (runs:make-full-test-name test-name item-path) 'start) + (mutex-unlock! registry-mutex) + ;; If haven't done it before register a top level test if this is an itemized test + (if (not (eq? (hash-table-ref/default test-registry (runs:make-full-test-name test-name "") #f) 'done)) + (cdb:tests-register-test *runremote* run-id test-name "")) + (cdb:tests-register-test *runremote* run-id test-name item-path) + (mutex-lock! registry-mutex) + (hash-table-set! test-registry (runs:make-full-test-name test-name item-path) 'done) + (mutex-unlock! registry-mutex)) + (conc test-name "/" item-path)))) + (thread-start! th))) (runs:shrink-can-run-more-tests-count) ;; DELAY TWEAKER (still needed?) (if (and (null? tal)(null? reg)) (list hed tal (append reg (list hed)) reruns) (list (runs:queue-next-hed tal reg reglen regfull) (runs:queue-next-tal tal reg reglen regfull) @@ -480,11 +654,12 @@ (list hed tal reg reruns)) ;; If no resources are available just kill time and loop again ;; ((not have-resources) ;; simply try again after waiting a second - (debug:print-info 1 "no resources to run new tests, waiting ...") + (if (runs:lownoise "no resources" 60) + (debug:print-info 1 "no resources to run new tests, waiting ...")) ;; Have gone back and forth on this but db starvation is an issue. ;; wait one second before looking again to run jobs. (thread-sleep! 1) ;; could have done hed tal here but doing car/cdr of newtal to rotate tests (list (car newtal)(cdr newtal) reg reruns)) @@ -493,11 +668,11 @@ ;; ((and have-resources (or (null? prereqs-not-met) (and (eq? testmode 'toplevel) (null? non-completed)))) - (run:test run-id run-info keyvals runname test-record flags #f test-registry) + (run:test run-id run-info keyvals runname test-record flags #f test-registry all-tests-registry) (hash-table-set! test-registry (runs:make-full-test-name test-name item-path) 'running) (runs:shrink-can-run-more-tests-count) ;; DELAY TWEAKER (still needed?) ;; (thread-sleep! *global-delta*) (if (or (not (null? tal))(not (null? reg))) (list (runs:queue-next-hed tal reg reglen regfull) @@ -510,16 +685,19 @@ ;; (else (debug:print 4 "FAILS: " fails) ;; 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 (not (null? prereqs-not-met)) + (debug:print-info 1 "waiting on tests; " (string-intersperse prereqs-not-met ", "))) + (if (null? fails) (begin ;; couldn't run, take a breather - (debug:print-info 4 "Shouldn't really get here, race condition? Unable to launch more tests at this moment, killing time ...") - ;; (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 @@ -531,16 +709,18 @@ (list (runs:queue-next-hed tal reg reglen regfull) (runs:queue-next-tal tal reg reglen regfull) (runs:queue-next-reg tal reg reglen regfull) (cons hed reruns))) (begin - (debug:print 1 "WARN: Test not processed correctly. Could be a race condition in your test implementation? " hed) ;; " as it has prerequistes that are FAIL. (NOTE: hed is not a vector)") + (debug:print 0 "WARNING: Test not processed correctly. Could be a race condition in your test implementation? Dropping test " hed) ;; " as it has prerequistes that are FAIL. (NOTE: hed is not a vector)") (runs:shrink-can-run-more-tests-count) ;; DELAY TWEAKER (still needed?) - (list hed tal reg reruns))))))))) + ;; (list hed tal reg reruns) + (list (car newtal)(cdr newtal) reg reruns) + )))))))) ;; test-records is a hash table testname:item_path => vector < testname testconfig waitons priority items-info ... > -(define (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests reglen-in) +(define (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests reglen-in all-tests-registry) ;; 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 ", flags: " (hash-table->alist flags)) (let ((run-info (cdb:remote-run db:get-run-info #f run-id)) (tests-info (mt:get-tests-for-run run-id #f '() '())) ;; qryvals: "id,testname,item_path")) @@ -560,19 +740,21 @@ (for-each (lambda (trec) (let ((id (db:test-get-id trec)) (tn (db:test-get-testname trec)) (ip (db:test-get-item-path trec)) (st (db:test-get-state trec))) - (hash-table-set! test-registry (runs:make-full-test-name tn ip) (string->symbol st)))) + (if (not (equal? st "DELETED")) + (hash-table-set! test-registry (runs:make-full-test-name tn ip) (string->symbol st))))) tests-info) (set! max-retries (if (and max-retries (string->number max-retries))(string->number max-retries) 100)) (let loop ((hed (car sorted-test-names)) (tal (cdr sorted-test-names)) (reg '()) ;; registered, put these at the head of tal (reruns '())) (if (not (null? reruns))(debug:print-info 4 "reruns=" reruns)) + ;; (print "Top of loop, hed=" hed ", tal=" tal " ,reruns=" reruns) (let* ((test-record (hash-table-ref test-records hed)) (test-name (tests:testqueue-get-testname test-record)) (tconfig (tests:testqueue-get-testconfig test-record)) (jobgroup (config-lookup tconfig "requirements" "jobgroup")) @@ -585,15 +767,23 @@ (item-path (item-list->path itemdat)) (tfullname (runs:make-full-test-name test-name item-path)) (newtal (append tal (list hed))) (regfull (>= (length reg) reglen))) - ;; Fast skip of tests that are already "COMPLETED" + ;; Ensure all top level tests get registered. This way they show up as "NOT_STARTED" on the dashboard + ;; and it is clear they *should* have run but did not. + (if (not (hash-table-ref/default test-registry (runs:make-full-test-name test-name "") #f)) + (begin + (cdb:tests-register-test *runremote* run-id test-name "") + (hash-table-set! test-registry (runs:make-full-test-name test-name "") 'done))) + + ;; Fast skip of tests that are already "COMPLETED" - NO! Cannot do that as the items may not have been expanded yet :( ;; - (if (equal? (hash-table-ref/default test-registry tfullname #f) 'COMPLETED) + (if (member (hash-table-ref/default test-registry tfullname #f) + '(DONOTRUN removed)) ;; *common:cant-run-states-sym*) ;; '(COMPLETED KILLED WAIVED UNKNOWN INCOMPLETE)) (begin - (debug:print-info 0 "Skipping COMPLETED test " tfullname) + (debug:print-info 0 "Skipping test " tfullname " as it has been marked do not run due to being completed or not runnable") (if (or (not (null? tal))(not (null? reg))) (loop (runs:queue-next-hed tal reg reglen regfull) (runs:queue-next-tal tal reg reglen regfull) (runs:queue-next-reg tal reg reglen regfull) reruns)))) @@ -629,11 +819,11 @@ ((not items) (debug:print-info 4 "OUTER COND: (not items)") (if (and (not (tests:match test-patts (tests:testqueue-get-testname test-record) item-path required: required-tests)) (not (null? tal))) (loop (car tal)(cdr tal) reg reruns)) - (let ((loop-list (runs:process-expanded-tests hed tal reg reruns reglen regfull test-record runname test-name item-path jobgroup max-concurrent-jobs run-id waitons item-path testmode test-patts required-tests test-registry registry-mutex flags keyvals run-info newtal))) + (let ((loop-list (runs:process-expanded-tests hed tal reg reruns reglen regfull test-record runname test-name item-path jobgroup max-concurrent-jobs run-id waitons item-path testmode test-patts required-tests test-registry registry-mutex flags keyvals run-info newtal all-tests-registry))) (if loop-list (apply loop loop-list)))) ;; items processed into a list but not came in as a list been processed ;; ((and (list? items) ;; thus we know our items are already calculated @@ -643,12 +833,18 @@ (if (and (list? items) (> (length items) 0) (and (list? (car items)) (> (length (car items)) 0)) (debug:debug-mode 1)) - (pp items)) - + (debug:print 2 (map (lambda (row) + (conc (string-intersperse + (map (lambda (varval) + (string-intersperse varval "=")) + row) + " ") + "\n")) + items))) (for-each (lambda (my-itemdat) (let* ((new-test-record (let ((newrec (make-tests:testqueue))) (vector-copy! test-record newrec) newrec)) @@ -678,11 +874,11 @@ ;; EXPAND ITEMS ((or (procedure? items)(eq? items 'have-procedure)) (let ((can-run-more (runs:can-run-more-tests jobgroup max-concurrent-jobs))) (if (and (list? can-run-more) (car can-run-more)) - (let ((loop-list (runs:expand-items hed tal reg reruns regfull newtal jobgroup max-concurrent-jobs run-id waitons item-path testmode test-record can-run-more items runname tconfig reglen))) + (let ((loop-list (runs:expand-items hed tal reg reruns regfull newtal jobgroup max-concurrent-jobs run-id waitons item-path testmode test-record can-run-more items runname tconfig reglen test-registry))) (if loop-list (apply loop loop-list))) ;; if can't run more just loop with next possible test (loop (car newtal)(cdr newtal) reg reruns)))) @@ -737,17 +933,17 @@ (define (runs:make-full-test-name testname itempath) (if (equal? itempath "") testname (conc testname "/" itempath))) ;; parent-test is there as a placeholder for when parent-tests can be run as a setup step -(define (run:test run-id run-info keyvals runname test-record flags parent-test test-registry) +(define (run:test run-id run-info keyvals runname test-record flags parent-test test-registry all-tests-registry) ;; All these vars might be referenced by the testconfig file reader (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 tests:get-testconfig here ... + (test-path (hash-table-ref all-tests-registry test-name)) ;; (conc *toppath* "/tests/" test-name)) ;; could use tests: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)) (item-path "") (db #f) @@ -762,10 +958,11 @@ "\n test-config: " (hash-table->alist test-conf) "\n itemdat: " itemdat ) (debug:print 2 "Attempting to launch test " full-test-name) (setenv "MT_TEST_NAME" test-name) ;; + (setenv "MT_ITEMPATH" item-path) (setenv "MT_RUNNAME" runname) (set-megatest-env-vars run-id inrunname: runname) ;; these may be needed by the launching process (change-directory *toppath*) ;; Here is where the test_meta table is best updated @@ -778,11 +975,11 @@ ;; itemdat => ((ripeness "overripe") (temperature "cool") (season "summer")) (let* ((new-test-path (string-intersperse (cons test-path (map cadr itemdat)) "/")) (test-id (cdb:remote-run db:get-test-id #f run-id test-name item-path)) (testdat (cdb:get-test-info-by-id *runremote* test-id))) (if (not testdat) - (begin + (let loop () ;; ensure that the path exists before registering the test ;; NOPE: Cannot! Don't know yet which disk area will be assigned.... ;; (system (conc "mkdir -p " new-test-path)) ;; ;; (open-run-close tests:register-test db run-id test-name item-path) @@ -794,15 +991,24 @@ (begin (debug:print 2 "WARN: Test not pre-created? test-name=" test-name ", item-path=" item-path ", run-id=" run-id) (cdb:tests-register-test *runremote* run-id test-name item-path) (set! test-id (cdb:remote-run db:get-test-id #f run-id test-name item-path)))) (debug:print-info 4 "test-id=" test-id ", run-id=" run-id ", test-name=" test-name ", item-path=\"" item-path "\"") - (set! testdat (cdb:get-test-info-by-id *runremote* test-id)))) + (set! testdat (cdb:get-test-info-by-id *runremote* test-id)) + (if (not testdat) + (begin + (debug:print-info 0 "WARNING: server is overloaded, trying again in one second") + (thread-sleep! 1) + (loop))))) (if (not testdat) ;; should NOT happen (debug:print 0 "ERROR: failed to get test record for test-id " test-id)) (set! test-id (db:test-get-id testdat)) - (change-directory test-path) + (if (file-exists? test-path) + (change-directory test-path) + (begin + (debug:print "ERROR: test run path not created before attempting to run the test. Perhaps you are running -remove-runs at the same time?") + (change-directory *toppath*))) (case (if force ;; (args:get-arg "-force") 'NOT_STARTED (if testdat (string->symbol (test:get-state testdat)) 'failed-to-insert)) @@ -817,14 +1023,14 @@ ((member (test:get-state testdat) '("DELETED" "NOT_STARTED"))(set! runflag #t)) ;; not -rerun and PASS, WARN or CHECK, do no run ((and (or (not rerun) keepgoing) ;; Require to force re-run for COMPLETED or *anything* + PASS,WARN or CHECK - (or (member (test:get-status testdat) '("PASS" "WARN" "CHECK" "SKIP")) + (or (member (test:get-status testdat) '("PASS" "WARN" "CHECK" "SKIP" "WAIVED")) (member (test:get-state testdat) '("COMPLETED")))) (debug:print-info 2 "running test " test-name "/" item-path " suppressed as it is " (test:get-state testdat) " and " (test:get-status testdat)) - (hash-table-set! test-registry full-test-name 'COMPLETED) + (hash-table-set! test-registry full-test-name 'DONOTRUN) ;; COMPLETED) (set! runflag #f)) ;; -rerun and status is one of the specifed, run it ((and rerun (let* ((rerunlst (string-split rerun ",")) (must-rerun (member (test:get-status testdat) rerunlst))) @@ -855,37 +1061,44 @@ (cond ;; Have to check for skip conditions. This one skips if there are same-named tests ;; currently running ((and skip-check (configf:lookup test-conf "skip" "prevrunning")) - (let ((running-tests (cdb:remote-run db:get-tests-for-runs-mindata #f #f full-test-name '("RUNNING") '() #f))) + (let ((running-tests (cdb:remote-run db:get-tests-for-runs-mindata #f #f full-test-name '("RUNNING" "REMOTEHOSTSTART" "LAUNCHED") '() #f))) (if (not (null? running-tests)) ;; have to skip (set! skip-test "Skipping due to previous tests running")))) ((and skip-check (configf:lookup test-conf "skip" "fileexists")) (if (file-exists? (configf:lookup test-conf "skip" "fileexists")) (set! skip-test (conc "Skipping due to existance of file " (configf:lookup test-conf "skip" "fileexists")))))) (if skip-test (begin - (cdb:remote-run db:test-set-state-status-by-id #f test-id "COMPLETED" "SKIP" skip-test) + (mt:test-set-state-status-by-id test-id "COMPLETED" "SKIP" skip-test) (debug:print-info 1 "SKIPPING Test " full-test-name " due to " skip-test)) (if (not (launch-test test-id run-id run-info keyvals runname test-conf 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: " full-test-name " is already running or was explictly killed, use -force to launch it.")) + (debug:print 1 "NOTE: " full-test-name " is already running or was explictly killed, use -force to launch it.") + (hash-table-set! test-registry (runs:make-full-test-name test-name test-path) 'DONOTRUN)) ;; KILLED)) ((LAUNCHED REMOTEHOSTSTART RUNNING) (if (> (- (current-seconds)(+ (db:test-get-event_time testdat) (db:test-get-run_duration testdat))) 600) ;; i.e. no update for more than 600 seconds (begin (debug:print 0 "WARNING: Test " test-name " appears to be dead. Forcing it to state INCOMPLETE and status STUCK/DEAD") (tests:test-set-status! test-id "INCOMPLETE" "STUCK/DEAD" "Test is stuck or dead" #f)) (debug:print 2 "NOTE: " test-name " is already running"))) - (else (debug:print 0 "ERROR: Failed to launch test " full-test-name ". Unrecognised state " (test:get-state testdat))))))) + (else + (debug:print 0 "ERROR: Failed to launch test " full-test-name ". Unrecognised state " (test:get-state testdat)) + (case (string->symbol (test:get-state testdat)) + ((COMPLETED INCOMPLETE) + (hash-table-set! test-registry (runs:make-full-test-name test-name test-path) 'DONOTRUN)) + (else + (hash-table-set! test-registry (runs:make-full-test-name test-name test-path) 'DONOTRUN)))))))) ;;====================================================================== ;; END OF NEW STUFF ;;====================================================================== @@ -893,10 +1106,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 @@ -959,89 +1196,97 @@ (test-retry-time (make-hash-table)) (allow-run-time 10)) ;; seconds to allow for killing tests before just brutally killing 'em (let loop ((test (car sorted-tests)) (tal (cdr sorted-tests))) (let* ((test-id (db:test-get-id test)) - (new-test-dat (cdb:remote-run db:get-test-info-by-id #f test-id)) - (item-path (db:test-get-item-path new-test-dat)) - (test-name (db:test-get-testname new-test-dat)) - (run-dir (db:test-get-rundir new-test-dat)) ;; run dir is from the link tree - (real-dir (if (file-exists? run-dir) - (resolve-pathname run-dir) - #f)) - (test-state (db:test-get-state new-test-dat)) - (test-fulln (db:test-get-fullname new-test-dat))) - (case action - ((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))) - (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 - (debug:print 0 "WARNING: could not gracefully remove test " test-fulln ", tried to kill it to no avail. Forcing state to FAILEDKILL and continuing") - (cdb:remote-run db:test-set-state-status-by-id db (db:test-get-id test) "FAILEDKILL" "n/a" #f) - (thread-sleep! 1)) - (begin - (cdb:remote-run db:test-set-state-status-by-id db (db:test-get-id test) "KILLREQ" "n/a" #f) - (thread-sleep! 1))) - ;; 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)) - (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")) - (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) - (begin - (debug:print-info 1 "Removing symlink " run-dir) - (handle-exceptions - exn - (debug:print 0 "ERROR: Failed to remove symlink " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue") - (delete-file run-dir))) - (if (directory? run-dir) - (if (> (directory-fold (lambda (f x)(+ 1 x)) 0 run-dir) 0) - (debug:print 0 "WARNING: refusing to remove " run-dir " as it is not empty") - (handle-exceptions - exn - (debug:print 0 "ERROR: Failed to remove directory " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue") - (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.")) - )) - (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) - (if (not (null? tal)) - (loop (car tal)(cdr tal)))) - ((run-wait) - (debug:print-info 2 "still waiting, " (length tests) " tests still running") - (thread-sleep! 10) - (let ((new-tests (proc-get-tests run-id))) - (if (null? new-tests) - (debug:print-info 1 "Run completed according to zero tests matching provided criteria.") - (loop (car new-tests)(cdr new-tests)))))))) - ))) + (new-test-dat (cdb:get-test-info-by-id *runremote* test-id))) + (if (not new-test-dat) + (begin + (debug:print 0 "ERROR: We have a test-id of " test-id " but no record was found. NOTE: No locking of records is done between processes, do not simultaneously remove the same run from two processes!") + (if (not (null? tal)) + (loop (car tal)(cdr tal)))) + (let* ((item-path (db:test-get-item-path new-test-dat)) + (test-name (db:test-get-testname new-test-dat)) + (run-dir (db:test-get-rundir new-test-dat)) ;; run dir is from the link tree + (real-dir (if (file-exists? run-dir) + (resolve-pathname run-dir) + #f)) + (test-state (db:test-get-state new-test-dat)) + (test-fulln (db:test-get-fullname new-test-dat))) + (case action + ((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)) + (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 + (debug:print 0 "WARNING: could not gracefully remove test " test-fulln ", tried to kill it to no avail. Forcing state to FAILEDKILL and continuing") + (mt:test-set-state-status-by-id (db:test-get-id test) "FAILEDKILL" "n/a" #f) + (thread-sleep! 1)) + (begin + (mt:test-set-state-status-by-id (db:test-get-id test) "KILLREQ" "n/a" #f) + (thread-sleep! 1))) + ;; 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 + (mt:test-set-state-status-by-id (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) + (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) + (begin + (debug:print-info 1 "Removing symlink " run-dir) + (handle-exceptions + exn + (debug:print 0 "ERROR: Failed to remove symlink " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue") + (delete-file run-dir))) + (if (directory? run-dir) + (if (> (directory-fold (lambda (f x)(+ 1 x)) 0 run-dir) 0) + (debug:print 0 "WARNING: refusing to remove " run-dir " as it is not empty") + (handle-exceptions + exn + (debug:print 0 "ERROR: Failed to remove directory " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue") + (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)) + (mt:test-set-state-status-by-id (db:test-get-id test) (car state-status)(cadr state-status) #f) + (if (not (null? tal)) + (loop (car tal)(cdr tal)))) + ((run-wait) + (debug:print-info 2 "still waiting, " (length tests) " tests still running") + (thread-sleep! 10) + (let ((new-tests (proc-get-tests run-id))) + (if (null? new-tests) + (debug:print-info 1 "Run completed according to zero tests matching provided criteria.") + (loop (car new-tests)(cdr new-tests)))))))) + ))))) ;; remove the run if zero tests remain (if (eq? action 'remove-runs) (let ((remtests (mt:get-tests-for-run (db:get-value-by-header run header "id") #f '("DELETED") '("n/a") not-in: #t))) (if (null? remtests) ;; no more tests remaining (let* ((dparts (string-split lasttpath "/")) @@ -1164,17 +1409,13 @@ ;; Update test_meta for all tests (define (runs:update-all-test_meta db) (let ((test-names (tests:get-valid-tests))) (for-each (lambda (test-name) - (let* ((test-path (conc *toppath* "/tests/" test-name)) - (test-configf (conc test-path "/testconfig")) - (testexists (and (file-exists? test-configf)(file-read-access? test-configf))) - ;; read configs with tricks turned off (i.e. no system) - (test-conf (if testexists (read-config test-configf #f #f)(make-hash-table)))) + (let* ((test-conf (mt:lazy-read-test-config test-name))) ;; use the cdb:remote-run instead of passing in db - (runs:update-test_meta test-name test-conf))) + (if test-conf (runs:update-test_meta test-name test-conf)))) test-names))) ;; This could probably be refactored into one complex query ... (define (runs:rollup-run keys runname user keyvals) (debug:print 4 "runs:rollup-run, keys: " keys " :runname " runname " user: " user) Index: server.scm ================================================================== --- server.scm +++ server.scm @@ -51,11 +51,11 @@ (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" transport + ((fs) (exit)) ;; there is no "fs" server transport ((http) (http-transport:launch)) ((zmq) (zmq-transport:launch)) (else (debug:print "WARNING: unrecognised transport " transport) (exit)))) @@ -117,5 +117,31 @@ (send-message pub-socket (db:obj->string (vector success/fail query-sig result))))) (else (debug:print 0 "ERROR: unrecognised transport type: " *transport-type*) result))) +(define (server:ensure-running) + (let loop ((servers (open-run-close tasks:get-best-server tasks:open-db)) + (trycount 0)) + (if (or (not servers) + (null? servers)) + (begin + (if (even? trycount) ;; just do the server start every other time through this loop (every 8 seconds) + (let ((cmdln (conc (if (getenv "MT_MEGATEST") (getenv "MT_MEGATEST") "megatest") + " -server - -daemonize"))) + (debug:print 0 "INFO: Starting server (" cmdln ") as none running ...") + ;; (server:launch (string->symbol (args:get-arg "-transport" "http")))) + ;; no need to use fork, no need to do the list-servers trick. Just start the damn server, it will exit on it's own + ;; if there is an existing server + (system cmdln) + (thread-sleep! 3) + ;; (process-run (car (argv)) (list "-server" "-" "-daemonize" "-transport" (args:get-arg "-transport" "http"))) + ) + (begin + (debug:print-info 0 "Waiting for server to start") + (thread-sleep! 4))) + (if (< trycount 10) + (loop (open-run-close tasks:get-best-server tasks:open-db) + (+ trycount 1)) + (debug:print 0 "WARNING: Couldn't start or find a server."))) + (debug:print 2 "INFO: Server(s) running " servers) + ))) Index: tasks.scm ================================================================== --- tasks.scm +++ tasks.scm @@ -199,21 +199,26 @@ ;; ping each server in the db and return first found that responds. ;; remove any others. will not necessarily remove all! (define (tasks:get-best-server mdb) (let ((res '()) - (best #f)) + (best #f) + (transport (if (and *transport-type* + (not (eq? *transport-type* 'fs))) + (conc *transport-type*) + "%"))) (sqlite3:for-each-row (lambda (id interface port pubport transport pid hostname) (set! res (cons (vector id interface port pubport transport pid hostname) res)) ;;(debug:print-info 2 "Found existing server " hostname ":" port " registered in db")) ) mdb "SELECT id,interface,port,pubport,transport,pid,hostname FROM servers WHERE strftime('%s','now')-heartbeat < 10 - AND mt_version=? ORDER BY start_time DESC LIMIT 1;" (common:version-signature)) + AND mt_version=? AND transport LIKE ? + ORDER BY start_time DESC LIMIT 1;" (common:version-signature) transport) ;; for now we are keeping only one server registered in the db, return #f or first server found (if (null? res) #f (car res)))) ;; BUG: This logic is probably needed unless methodology changes completely... ;; Index: tests.scm ================================================================== --- tests.scm +++ tests.scm @@ -15,10 +15,11 @@ (use sqlite3 srfi-1 posix regex regex-case srfi-69 dot-locking tcp directory-utils) (import (prefix sqlite3 sqlite3:)) (declare (unit tests)) +(declare (uses lock-queue)) (declare (uses db)) (declare (uses common)) (declare (uses items)) (declare (uses runconfig)) @@ -26,19 +27,42 @@ (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") (include "test_records.scm") -(define (tests:get-valid-tests testsdir test-patts) ;; #!key (test-names '())) - (let ((tests (glob (conc testsdir "/tests/*")))) ;; " (string-translate patt "%" "*"))))) - (set! tests (filter (lambda (test)(file-exists? (conc test "/testconfig"))) tests)) - (delete-duplicates - (filter (lambda (testname) - (tests:match test-patts testname #f)) - (map (lambda (testp) - (last (string-split testp "/"))) - tests))))) +;; Call this one to do all the work and get a standardized list of tests +(define (tests:get-all) + (let* ((test-search-path (cons (conc *toppath* "/tests") ;; the default + (tests:get-tests-search-path *configdat*)))) + (tests:get-valid-tests (make-hash-table) test-search-path))) + +(define (tests:get-tests-search-path cfgdat) + (let ((paths (map cadr (configf:get-section cfgdat "tests-paths")))) + (cons (conc *toppath* "/tests") paths))) + +(define (tests:get-valid-tests test-registry tests-paths) + (if (null? tests-paths) + test-registry + (let loop ((hed (car tests-paths)) + (tal (cdr tests-paths))) + (if (file-exists? hed) + (for-each (lambda (test-path) + (let* ((tname (last (string-split test-path "/"))) + (tconfig (conc test-path "/testconfig"))) + (if (and (not (hash-table-ref/default test-registry tname #f)) + (file-exists? tconfig)) + (hash-table-set! test-registry tname test-path)))) + (glob (conc hed "/*")))) + (if (null? tal) + test-registry + (loop (car tal)(cdr tal)))))) + +(define (tests:filter-test-names test-names test-patts) + (delete-duplicates + (filter (lambda (testname) + (tests:match test-patts testname #f)) + test-names))) ;; tests:glob-like-match (define (tests:glob-like-match patt str) (let ((like (substring-index "%" patt))) (let* ((notpatt (equal? (substring-index "~" patt) 0)) @@ -133,11 +157,11 @@ ;; if found then return that matching test record (debug:print 4 "selstr: " selstr ", qrystr: " qrystr ", keyvals: " keyvals ", previous run ids found: " prev-run-ids) (if (null? prev-run-ids) #f (let loop ((hed (car prev-run-ids)) (tal (cdr prev-run-ids))) - (let ((results (db:get-tests-for-run db hed (conc test-name "/" item-path)'() '() #f #f #f #f))) + (let ((results (db:get-tests-for-run db hed (conc test-name "/" item-path)'() '() #f #f #f #f #f))) (debug:print 4 "Got tests for run-id " run-id ", test-name " test-name ", item-path " item-path ": " results) (if (and (null? results) (not (null? tal))) (loop (car tal)(cdr tal)) (if (null? results) #f @@ -174,11 +198,11 @@ (debug:print 4 "selstr: " selstr ", qrystr: " qrystr ", keyvals: " keyvals ", previous run ids found: " prev-run-ids) (if (null? prev-run-ids) '() ;; no previous runs? return null (let loop ((hed (car prev-run-ids)) (tal (cdr prev-run-ids))) - (let ((results (db:get-tests-for-run db hed (conc test-name "/" item-path) '() '() #f #f #f #f))) + (let ((results (db:get-tests-for-run db hed (conc test-name "/" item-path) '() '() #f #f #f #f #f))) (debug:print 4 "Got tests for run-id " run-id ", test-name " test-name ", item-path " item-path " results: " (intersperse results "\n")) ;; Keep only the youngest of any test/item combination (for-each (lambda (testdat) @@ -195,63 +219,72 @@ (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%") (logpro-rule "diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html")) - (push-directory test-rundir) - (let ((result (if (null? waivers) - #f - (let loop ((hed (car waivers)) - (tal (cdr waivers))) - (debug:print 0 "INFO: Applying waiver rule \"" hed "\"") - (let* ((waiver (configf:lookup testconfig "waivers" hed)) - (wparts (if waiver (string-match waiver-rx waiver) #f)) - (waiver-rule (if wparts (cadr wparts) #f)) - (waiver-glob (if wparts (caddr wparts) #f)) - (logpro-file (if waiver - (let ((fname (conc hed ".logpro"))) - (if (file-exists? fname) - fname - (begin - (debug:print 0 "INFO: No logpro file " fname " falling back to diff") - #f))) - #f)) - ;; if rule by name of waiver-rule is found in testconfig - use it - ;; else if waivername.logpro exists use logpro-rule - ;; else default to diff-rule - (rule-string (let ((rule (configf:lookup testconfig "waiver_rules" waiver-rule))) - (if rule - rule - (if logpro-file - logpro-rule - (begin - (debug:print 0 "INFO: No logpro file " logpro-file " found, using diff rule") - diff-rule))))) - ;; (string-substitute "%file1%" "foofoo.txt" "This is %file1% and so is this %file1%." #t) - (processed-cmd (string-substitute - "%file1%" (conc test-rundir "/" waiver-glob) - (string-substitute - "%file2%" (conc prev-rundir "/" waiver-glob) - (string-substitute - "%waivername%" hed rule-string #t) #t) #t)) - (res #f)) - (debug:print 0 "INFO: waiver command is \"" processed-cmd "\"") - (if (eq? (system processed-cmd) 0) - (if (null? tal) - #t - (loop (car tal)(cdr tal))) - #f)))))) - (pop-directory) - result))) - + (if (not (file-exists? test-rundir)) + (begin + (debug:print 0 "ERROR: test run directory is gone, cannot propagate waiver") + #f) + (begin + (push-directory test-rundir) + (let ((result (if (null? waivers) + #f + (let loop ((hed (car waivers)) + (tal (cdr waivers))) + (debug:print 0 "INFO: Applying waiver rule \"" hed "\"") + (let* ((waiver (configf:lookup testconfig "waivers" hed)) + (wparts (if waiver (string-match waiver-rx waiver) #f)) + (waiver-rule (if wparts (cadr wparts) #f)) + (waiver-glob (if wparts (caddr wparts) #f)) + (logpro-file (if waiver + (let ((fname (conc hed ".logpro"))) + (if (file-exists? fname) + fname + (begin + (debug:print 0 "INFO: No logpro file " fname " falling back to diff") + #f))) + #f)) + ;; if rule by name of waiver-rule is found in testconfig - use it + ;; else if waivername.logpro exists use logpro-rule + ;; else default to diff-rule + (rule-string (let ((rule (configf:lookup testconfig "waiver_rules" waiver-rule))) + (if rule + rule + (if logpro-file + logpro-rule + (begin + (debug:print 0 "INFO: No logpro file " logpro-file " found, using diff rule") + diff-rule))))) + ;; (string-substitute "%file1%" "foofoo.txt" "This is %file1% and so is this %file1%." #t) + (processed-cmd (string-substitute + "%file1%" (conc test-rundir "/" waiver-glob) + (string-substitute + "%file2%" (conc prev-rundir "/" waiver-glob) + (string-substitute + "%waivername%" hed rule-string #t) #t) #t)) + (res #f)) + (debug:print 0 "INFO: waiver command is \"" processed-cmd "\"") + (if (eq? (system processed-cmd) 0) + (if (null? tal) + #t + (loop (car tal)(cdr tal))) + #f)))))) + (pop-directory) + result))))) + +(define (tests:test-force-state-status! test-id state status) + (cdb:test-set-status-state *runremote* test-id status state #f) + (mt:process-triggers test-id state status)) ;; Do not rpc this one, do the underlying calls!!! (define (tests:test-set-status! test-id state status comment dat #!key (work-area #f)) (debug:print-info 4 "tests:test-set-status! test-id=" test-id ", state=" state ", status=" status ", dat=" dat) (let* ((db #f) @@ -291,11 +324,13 @@ (debug:print 4 "real-status " real-status ", waived " waived ", status " status) ;; update the primary record IF state AND status are defined (if (and state status) - (cdb:test-set-status-state *runremote* test-id real-status state (if waived waived comment))) + (begin + (cdb:test-set-status-state *runremote* test-id real-status state (if waived waived comment)) + (mt:process-triggers test-id state real-status))) ;; if status is "AUTO" then call rollup (note, this one modifies data in test ;; run area, it does remote calls under the hood. (if (and test-id state status (equal? status "AUTO")) (db:test-data-rollup #f test-id status work-area: work-area)) @@ -336,11 +371,11 @@ (db:csv->test-data #f test-id dat)))) ;; need to update the top test record if PASS or FAIL and this is a subtest (if (not (equal? item-path "")) - (cdb:roll-up-pass-fail-counts *runremote* run-id test-name item-path status)) + (mt:roll-up-pass-fail-counts run-id test-name item-path status)) (if (or (and (string? comment) (string-match (regexp "\\S+") comment)) waived) (let ((cmt (if waived waived comment))) @@ -349,21 +384,22 @@ (define (tests:test-set-toplog! db run-id test-name logf) (cdb:client-call *runremote* 'tests:test-set-toplog #t 2 logf run-id test-name)) -(define (tests:summarize-items db run-id test-name force) +(define (tests:summarize-items db run-id test-id test-name force) ;; if not force then only update the record if one of these is true: ;; 1. logf is "log/final.log ;; 2. logf is same as outputfilename (let* ((outputfilename (conc "megatest-rollup-" test-name ".html")) (orig-dir (current-directory)) (logf-info (cdb:remote-run db:test-get-logfile-info #f run-id test-name)) (logf (if logf-info (cadr logf-info) #f)) (path (if logf-info (car logf-info) #f))) ;; This query finds the path and changes the directory to it for the test - (if (directory? path) + (if (and (string? path) + (directory? path)) ;; can get #f here under some wierd conditions. why, unknown ... (begin (debug:print 4 "Found path: " path) (change-directory path)) ;; (set! outputfilename (conc path "/" outputfilename))) (print "No such path: " path)) @@ -370,12 +406,13 @@ (debug:print 4 "summarize-items with logf " logf ", outputfilename " outputfilename " and force " force) (if (or (equal? logf "logs/final.log") (equal? logf outputfilename) force) (begin - (if (not (obtain-dot-lock outputfilename 1 5 7)) ;; retry every second for 20 seconds, call it dead after 30 seconds and steal the lock - (print "Failed to obtain lock for " outputfilename) + (if ;; (not (obtain-dot-lock outputfilename 1 5 7)) ;; retry every second for 20 seconds, call it dead after 30 seconds and steal the lock + (not (lock-queue:wait-turn outputfilename test-id)) + (print "Not updating " outputfilename " as another test item has signed up for the job") (begin (print "Obtained lock for " outputfilename) (let ((oup (open-output-file outputfilename)) (counts (make-hash-table)) (statecounts (make-hash-table)) @@ -432,38 +469,41 @@ (print "" "" outtxt "
ItemStateStatusComment
") (release-dot-lock outputfilename))) (close-output-port oup) + (lock-queue:release-lock outputfilename test-id) (change-directory orig-dir) ;; NB// tests:test-set-toplog! is remote internal... (tests:test-set-toplog! db run-id test-name outputfilename) ))))))) ;;====================================================================== ;; Gather data from test/task specifications ;;====================================================================== -(define (tests:get-valid-tests testsdir test-patts) ;; #!key (test-names '())) - (let ((tests (glob (conc testsdir "/tests/*")))) ;; " (string-translate patt "%" "*"))))) - (set! tests (filter (lambda (test)(file-exists? (conc test "/testconfig"))) tests)) - (delete-duplicates - (filter (lambda (testname) - (tests:match test-patts testname #f)) - (map (lambda (testp) - (last (string-split testp "/"))) - tests))))) - -(define (tests:get-testconfig test-name system-allowed) - (let* ((test-path (conc *toppath* "/tests/" test-name)) +;; (define (tests:get-valid-tests testsdir test-patts) ;; #!key (test-names '())) +;; (let ((tests (glob (conc testsdir "/tests/*")))) ;; " (string-translate patt "%" "*"))))) +;; (set! tests (filter (lambda (test)(file-exists? (conc test "/testconfig"))) tests)) +;; (delete-duplicates +;; (filter (lambda (testname) +;; (tests:match test-patts testname #f)) +;; (map (lambda (testp) +;; (last (string-split testp "/"))) +;; tests))))) + +(define (tests:get-testconfig test-name test-registry system-allowed) + (let* ((test-path (hash-table-ref/default test-registry test-name (conc *toppath* "/tests/" test-name))) (test-configf (conc test-path "/testconfig")) - (testexists (and (file-exists? test-configf)(file-read-access? test-configf)))) - (if testexists - (read-config test-configf #f system-allowed environ-patt: (if system-allowed - "pre-launch-env-vars" - #f)) - #f))) + (testexists (and (file-exists? test-configf)(file-read-access? test-configf))) + (tcfg (if testexists + (read-config test-configf #f system-allowed environ-patt: (if system-allowed + "pre-launch-env-vars" + #f)) + #f))) + (hash-table-set! *testconfigs* test-name tcfg) + tcfg)) ;; sort tests by priority and waiton ;; Move test specific stuff to a test unit FIXME one of these days (define (tests:sort-by-priority-and-waiton test-records) (let ((mungepriority (lambda (priority) @@ -520,27 +560,32 @@ (test-id (cdb:remote-run db:get-test-id #f run-id test-name item-path)) (tdat (cdb:get-test-info-by-id *runremote* test-id))) (if tdat (begin ;; Look at the test state and status - (if (or (member (db:test-get-status tdat) - '("PASS" "WARN" "WAIVED" "CHECK" "SKIP")) + (if (or (and (member (db:test-get-status tdat) + '("PASS" "WARN" "WAIVED" "CHECK" "SKIP")) + (equal? (db:test-get-state tdat) "COMPLETED")) (member (db:test-get-state tdat) - '("INCOMPLETE" "KILLED"))) + '("INCOMPLETE" "KILLED"))) (set! keep-test #f)) ;; examine waitons for any fails. If it is FAIL or INCOMPLETE then eliminate this test ;; from the runnable list (if keep-test (for-each (lambda (waiton) ;; for now we are waiting only on the parent test (let* ((parent-test-id (cdb:remote-run db:get-test-id #f run-id waiton "")) - (wtdat (cdb:get-test-info-by-id *runremote* test-id))) - (if (or (member (db:test-get-status wtdat) - '("FAIL" "KILLED")) - (member (db:test-get-state wtdat) - '("INCOMPETE"))) + (wtdat (cdb:get-test-info-by-id *runremote* test-id))) + (if (or (and (equal? (db:test-get-state wtdat) "COMPLETED") + (member (db:test-get-status wtdat) '("FAIL"))) + (member (db:test-get-status wtdat) '("KILLED")) + (member (db:test-get-state wtdat) '("INCOMPETE"))) + ;; (if (or (member (db:test-get-status wtdat) + ;; '("FAIL" "KILLED")) + ;; (member (db:test-get-state wtdat) + ;; '("INCOMPETE"))) (set! keep-test #f)))) ;; no point in running this one again waitons)))) (if keep-test (set! runnables (cons testkeyname runnables))))) testkeynames) runnables)) @@ -548,16 +593,16 @@ ;;====================================================================== ;; refactoring this block into tests:get-full-data from line 263 of runs.scm ;;====================================================================== ;; hed is the test name ;; test-records is a hash of test-name => test record -(define (tests:get-full-data test-names test-records required-tests) +(define (tests:get-full-data test-names test-records required-tests all-tests-registry) (if (not (null? test-names)) (let loop ((hed (car test-names)) (tal (cdr test-names))) ;; 'return-procs tells the config reader to prep running system but return a proc (debug:print-info 4 "hed=" hed " at top of loop") - (let* ((config (tests:get-testconfig hed 'return-procs)) + (let* ((config (tests:get-testconfig hed all-tests-registry 'return-procs)) (waitons (let ((instr (if config (config-lookup config "requirements" "waiton") (begin ;; No config means this is a non-existant test (debug:print 0 "ERROR: non-existent required test \"" hed "\", grep through your testconfigs to find and remove or create the test. Discarding and continuing.") "")))) @@ -650,42 +695,43 @@ tdb "SELECT count(id) FROM test_rundat;") res)) 0) -(define (tests:update-central-meta-info test-id cpuload diskfree minutes num-records uname hostname) +(define (tests:update-central-meta-info test-id cpuload diskfree minutes uname hostname) ;; This is a good candidate for threading the requests to enable ;; transactionized write at the server (cdb:tests-update-cpuload-diskfree *runremote* test-id cpuload diskfree) - ;; (let ((db (open-db))) - ;; (sqlite3:execute db "UPDATE tests SET cpuload=?,diskfree=? WHERE id=?;" - ;; cpuload - ;; diskfree - ;; test-id) - (if minutes - (cdb:tests-update-run-duration *runremote* test-id minutes)) - ;; (sqlite3:execute db "UPDATE tests SET run_duration=? WHERE id=?;" minutes test-id)) - (if (eq? num-records 0) - (cdb:tests-update-uname-host *runremote* test-id uname hostname)) - ;;(sqlite3:execute db "UPDATE tests SET uname=?,host=? WHERE id=?;" uname hostname test-id)) - ;;(sqlite3:finalize! db)) - ) - -(define (tests:set-meta-info db test-id run-id testname itemdat minutes work-area) + (if minutes + (cdb:tests-update-run-duration *runremote* test-id minutes)) + (if (and uname hostname) + (cdb:tests-update-uname-host *runremote* test-id uname hostname))) + +(define (tests:set-full-meta-info db test-id run-id minutes work-area) + ;; DOES cdb:remote-run under the hood! + (let* ((num-records 0) ;; (test:tdb-get-rundat-count tdb)) + (cpuload (get-cpu-load)) + (diskfree (get-df (current-directory))) + (uname (get-uname "-srvpio")) + (hostname (get-host-name))) + (tests:update-testdat-meta-info db test-id work-area cpuload diskfree minutes) + (tests:update-central-meta-info test-id cpuload diskfree minutes uname hostname))) + +(define (tests:set-partial-meta-info db test-id run-id minutes work-area) ;; DOES cdb:remote-run under the hood! - (let* ((tdb (db:open-test-db-by-test-id db test-id work-area: work-area)) - (num-records (test:tdb-get-rundat-count tdb)) - (cpuload (get-cpu-load)) + (let* ((cpuload (get-cpu-load)) (diskfree (get-df (current-directory)))) - (if (eq? (modulo num-records 10) 0) ;; every ten records update central - (let ((uname (get-uname "-srvpio")) - (hostname (get-host-name))) - (tests:update-central-meta-info test-id cpuload diskfree minutes num-records uname hostname))) + (tests:update-testdat-meta-info db test-id work-area cpuload diskfree minutes) + ;; Update central with uname and hostname = #f + (tests:update-central-meta-info test-id cpuload diskfree minutes #f #f))) + +(define (tests:update-testdat-meta-info db test-id work-area cpuload diskfree minutes) + (let ((tdb (db:open-test-db-by-test-id db test-id work-area: work-area))) (sqlite3:execute tdb "INSERT INTO test_rundat (update_time,cpuload,diskfree,run_duration) VALUES (strftime('%s','now'),?,?,?);" cpuload diskfree minutes) (sqlite3:finalize! tdb))) - + ;;====================================================================== ;; A R C H I V I N G ;;====================================================================== (define (test:archive db test-id) Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -128,17 +128,20 @@ for fs in afs nfs zfs; do \ for dpath in none tmp; do \ (cd fullrun;$(MEGATEST) -runtests priority_10_waiton_1 -target $$sys/$$fs/$$dpath :runname $(RUNNAME) &);\ done;done;done +test11 : + cd fullrun;time (for a in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 ;do (megatest -test-paths -target %/%/% > /dev/null ) & done; wait; ) + minsetup : cd ..;make && make install mkdir -p mintest/runs mintest/links cd mintest;megatest -stop-server 0 cd mintest;megatest -server - -debug $(DEBUG) > server.log 2> server.log & sleep 3 - cd mintest;dashboard -rows 20 & + cd mintest;dashboard -rows 18 & cleanprep : ../*.scm Makefile */*.config mkdir -p fullrun/tmp/mt_runs fullrun/tmp/mt_links cd ..;make;make install rm -f */logging.db @@ -147,11 +150,14 @@ fullprep : cleanprep cd fullrun;$(MEGATEST) -remove-runs :runname $(RUNNAME)% -target %/%/% -testpatt %/% cd fullrun;$(BINPATH)/dashboard -rows 15 & dashboard : cleanprep - cd fullrun && $(BINPATH)/dashboard -rows 25 & + cd fullrun && $(BINPATH)/dashboard -transport fs -rows 20 & + +dashboard-http : cleanprep + cd fullrun && $(BINPATH)/dashboard -transport http -rows 20 & remove : cd fullrun;$(MEGATEST) -remove-runs :runname $(RUN) -testpatt % -itempatt % :sysname % :fsname % :datapath % clean : Index: tests/fdktestqa/fdk.config ================================================================== --- tests/fdktestqa/fdk.config +++ tests/fdktestqa/fdk.config @@ -2,11 +2,11 @@ SYSTEM TEXT RELEASE TEXT [setup] # Adjust max_concurrent_jobs to limit how much you load your machines -max_concurrent_jobs 500 +max_concurrent_jobs 150 # This is your link path, you can move it but it is generally better to keep it stable linktree #{shell readlink -f #{getenv PWD}/../simplelinks} [include testqa/configs/megatest.abc.config] Index: tests/fdktestqa/testqa/Makefile ================================================================== --- tests/fdktestqa/testqa/Makefile +++ tests/fdktestqa/testqa/Makefile @@ -5,23 +5,25 @@ all : $(MEGATEST) -remove-runs -target a/b :runname c -testpatt %/% $(MEGATEST) -runtests % -target a/b :runname c bigbig : + $(MEGATEST) -server - -daemonize ; sleep 3 for tn in a b c d;do \ ($(MEGATEST) -runtests % -target a/b :runname $tn & ) ; \ done bigrun : $(MEGATEST) -runtests bigrun -target a/bigrun :runname a bigrun2 : - $(MEGATEST) -runtests bigrun2 -target a/bigrun2 :runname a + $(MEGATEST) -runtests bigrun2 -target a/bigrun2 :runname a -transport http dashboard : $(DASHBOARD) -rows 20 & compile : + $(MEGATEST) -stop-server 0 (cd ../../..;make && make install) clean : rm -rf ../simple*/*/* megatest.db 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/megatest.config ================================================================== --- tests/fdktestqa/testqa/megatest.config +++ tests/fdktestqa/testqa/megatest.config @@ -1,8 +1,10 @@ [setup] testcopycmd cp --remove-destination -rlv TEST_SRC_PATH/. TEST_TARG_PATH/. >> TEST_TARG_PATH/mt_launch.log 2>> TEST_TARG_PATH/mt_launch.log -runqueue 2 +runqueue 20 +transport http +launchwait no [include ../fdk.config] [server] -timeout 0.05 +port 9080 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 Index: tests/fullrun/config/mt_include_1.config ================================================================== --- tests/fullrun/config/mt_include_1.config +++ tests/fullrun/config/mt_include_1.config @@ -1,17 +1,19 @@ [setup] # exectutable /path/to/megatest -max_concurrent_jobs 150 +max_concurrent_jobs 50 linktree #{getenv MT_RUN_AREA_HOME}/tmp/mt_links [jobtools] useshell yes # ## launcher launches jobs, the job is managed on the target host ## by megatest, comment out launcher to run local # workhosts localhost hermes +# launcher exec nbfake launcher nbfake +# launcher nbfind # launcher nodanggood ## use "xterm -e csi -- " as a launcher to examine the launch environment. ## exit with (exit) ## get a shell with (system "bash") Index: tests/fullrun/megatest.config ================================================================== --- tests/fullrun/megatest.config +++ tests/fullrun/megatest.config @@ -8,19 +8,31 @@ [refareas] area1 /tmp/oldarea/megatest [include config/mt_include_1.config] +[misc] +home #{shell readlink -f $MT_RUN_AREA_HOME} +parent #{shell readlink -f $MT_RUN_AREA_HOME/..} + +[tests-paths] +1 #{get misc parent}/simplerun/tests + [setup] -# Set launchwait to yes to use the old launch run code that waits for the launch process to return before -# proceeding. -# launchwait yes +# Set launchwait to no to use the more agressive code that does not wait for the launch to complete before proceeding +# this may save a few milliseconds on launching tests +# launchwait no + +# Use http instead of direct filesystem access +# transport http +transport fs # If set to "default" the old code is used. Otherwise defaults to 200 or uses # numeric value given. # runqueue 20 + # It is possible (but not recommended) to override the rsync command used # to populate the test directories. For test development the following # example can be useful # @@ -36,19 +48,34 @@ throttle 0.2 # Max retries allows megatest to re-check that a tests status has changed # as tests can have transient FAIL status occasionally maxretries 20 +# Setup continued. +[setup] + +# override the logview command +# +logviewer (%MTCMD%) 2> /dev/null > /dev/null + +# override the html viewer launch command +# +# htmlviewercmd firefox -new-window +htmlviewercmd konqueror + [validvalues] state start end 0 1 - 2 status pass fail n/a 0 1 running - 2 # These are set before all tests, override them # in the testconfig [pre-launch-env-overrides] section [env-override] +# MT_XTERM_CMD overrides the terminal command +# MT_XTERM_CMD xterm -bg lightgreen -fg black + SPECIAL_ENV_VARS overide them here - should be seen at launch and in the runs -TESTVAR [system realpath .] +TESTVAR [system echo $PWD] DEADVAR [system ls] VARWITHDOLLAR $HOME/.zshrc WACKYVAR #{system ls > /dev/null} WACKYVAR2 #{get validvalues state} WACKYVAR3 #{getenv USER} ADDED tests/fullrun/tests/blocktestxz/main.sh Index: tests/fullrun/tests/blocktestxz/main.sh ================================================================== --- /dev/null +++ tests/fullrun/tests/blocktestxz/main.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +$MT_MEGATEST -test-status :state $THESTATE :status $THESTATUS -setlog "nada.html" + +# By exiting with non-zero we tell Megatest to preseve the state and status +exit 1 ADDED tests/fullrun/tests/blocktestxz/testconfig Index: tests/fullrun/tests/blocktestxz/testconfig ================================================================== --- /dev/null +++ tests/fullrun/tests/blocktestxz/testconfig @@ -0,0 +1,20 @@ +[setup] +runscript main.sh + +[items] +THESTATE UNKNOWN INCOMPLETE KILLED KILLREQ STUCK BOZZLEBLONKED STUCK/DEAD +THESTATUS PASS FAIL STUCK/DEAD SKIP + +[requirements] +waiton sqlitespeed + +[test_meta] +author matt +owner bob +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 Index: tests/fullrun/tests/ez_exit2_fail/testconfig ================================================================== --- tests/fullrun/tests/ez_exit2_fail/testconfig +++ tests/fullrun/tests/ez_exit2_fail/testconfig @@ -5,11 +5,11 @@ lookithome ls /home [test_meta] author matt owner bob -description This test runs two steps; the first exits with - code 2 (a fail because not using logpro) and the second - is a pass +description This test runs two steps; the first exits with\ + code 2 (a fail because not using logpro) and the second\ + is a pass tags first,single reviewed 09/10/2011, by Matt ADDED tests/fullrun/tests/ez_fail_quick/testconfig Index: tests/fullrun/tests/ez_fail_quick/testconfig ================================================================== --- /dev/null +++ tests/fullrun/tests/ez_fail_quick/testconfig @@ -0,0 +1,18 @@ +[requirements] +priority 10 + +[ezsteps] +# should fail on next step +lookitnada ls /nada + +[triggers] +# run like this: cmd test-id test-rundir trigger +COMPLETED/FAIL xterm;echo + +[test_meta] +author matt +owner bob +description This test runs a single ezstep which fails immediately. + +tags first,single +reviewed 09/10/2011, by Matt Index: tests/fullrun/tests/ezlog_fail_then_pass/testconfig ================================================================== --- tests/fullrun/tests/ezlog_fail_then_pass/testconfig +++ tests/fullrun/tests/ezlog_fail_then_pass/testconfig @@ -4,10 +4,10 @@ firststep main.sh [test_meta] author matt owner bob -description This test runs a single ezstep which is logpro clean - but fails based on -test-data loaded. +description This test runs a single ezstep which is logpro clean\ + but fails based on -test-data loaded. tags first,single reviewed 09/10/2011, by Matt Index: tests/fullrun/tests/manual_example/testconfig ================================================================== --- tests/fullrun/tests/manual_example/testconfig +++ tests/fullrun/tests/manual_example/testconfig @@ -5,9 +5,9 @@ # launch launchxterm [test_meta] author matt owner bob -description This test runs a single ezstep which is expected to pass - using a simple logpro file. +description This test runs a single ezstep which is expected to pass\ + using a simple logpro file. tags first,single reviewed 09/10/2011, by Matt Index: tests/fullrun/tests/priority_2/main.sh ================================================================== --- tests/fullrun/tests/priority_2/main.sh +++ tests/fullrun/tests/priority_2/main.sh @@ -1,10 +1,10 @@ #!/bin/bash # a bunch of steps in 2 second increments for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17;do $MT_MEGATEST -step step$i :state start :status running -setlog results$i.html - sleep 2 + sleep 5 $MT_MEGATEST -step step$i :state end :status 0 done exit 0 Index: tests/fullrun/tests/priority_2/testconfig ================================================================== --- tests/fullrun/tests/priority_2/testconfig +++ tests/fullrun/tests/priority_2/testconfig @@ -2,11 +2,11 @@ runscript main.sh [requirements] priority 2 # runtimelim 1d 1h 1m 10s -runtimelim 10s +runtimelim 20s [test_meta] author matt owner bob description This test checks that a multi-lineitem test with mix of pass and non-fail rolls up a PASS Index: tests/fullrun/tests/runfirst/main.sh ================================================================== --- tests/fullrun/tests/runfirst/main.sh +++ tests/fullrun/tests/runfirst/main.sh @@ -23,9 +23,14 @@ $MT_MEGATEST -load-test-data << EOF cat, var, val, exp, comp, units, comment, status, type ameas,iout,1.2,1.9,>,Amps,Comment,,meas EOF +loadstatus=$? -$MT_MEGATEST -test-status :state COMPLETED :status $? -m "This is a test level comment" :value 10e6 :expected_value 1.1e6 :tol 100e3 :category nada :variable sillyvar :units mFarks :comment "This is the value/expected comment" +if [[ `basename $PWD` == "mustfail" ]];then + $MT_MEGATEST -test-status :state COMPLETED :status FAIL +else + $MT_MEGATEST -test-status :state COMPLETED :status $loadstatus -m "This is a test level comment" :value 10e6 :expected_value 1.1e6 :tol 100e3 :category nada :variable sillyvar :units mFarks :comment "This is the value/expected comment" +fi # $MT_MEGATEST -test-status :state COMPLETED :status FAIL Index: tests/fullrun/tests/runfirst/testconfig ================================================================== --- tests/fullrun/tests/runfirst/testconfig +++ tests/fullrun/tests/runfirst/testconfig @@ -6,19 +6,19 @@ # host. This can be used to control remote launch tools, e.g. to # to choose the target host, select the launch tool etc. SPECIAL_ENV_VAR override with everything after the first space. [items] -SEASON summer winter fall spring +SEASON summer winter fall spring [itemstable] BLOCK a b TOCK 1 2 [test_meta] author matt owner bob -description This test must +description This test must\ be run before the other tests tags first,single reviewed 1/1/1965 Index: tests/fullrun/tests/singletest/main.sh ================================================================== --- tests/fullrun/tests/singletest/main.sh +++ tests/fullrun/tests/singletest/main.sh @@ -2,8 +2,8 @@ # megatest -step wasting_time :state start :status n/a -m "This is a test step comment" # sleep 20 # megatest -step wasting_time :state end :status $? -$MT_MEGATEST -runstep wasting_time -logpro wasting_time.logpro "sleep 5;echo all done eh?" -m "This is a test step comment" +$MT_MEGATEST -runstep wasting_time -logpro wasting_time.logpro "sleep 5;echo alldone" -m "This is a test step comment" $MT_MEGATEST -test-status :state COMPLETED :status $? -m "This is a test level comment" -set-toplog the_top_log.html :first_err "This is the first error" ADDED tests/fullrun/tests/testxz/testconfig Index: tests/fullrun/tests/testxz/testconfig ================================================================== --- /dev/null +++ tests/fullrun/tests/testxz/testconfig @@ -0,0 +1,15 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +listfiles ls + +# Test requirements are specified here +[requirements] +waiton blocktestxz + +# test_meta is a section for storing additional data on your test +[test_meta] +author mrwellan +owner mrwellan +description This test should never get run due to blocktestxz failing +tags tagone,tagtwo +reviewed never ADDED tests/installall/config/megatest.config.dat Index: tests/installall/config/megatest.config.dat ================================================================== --- /dev/null +++ tests/installall/config/megatest.config.dat @@ -0,0 +1,1 @@ +../megatest.config ADDED tests/installall/config/runconfigs.config.dat Index: tests/installall/config/runconfigs.config.dat ================================================================== --- /dev/null +++ tests/installall/config/runconfigs.config.dat @@ -0,0 +1,1 @@ +../runconfigs.config ADDED tests/installall/config/sheet-names.cfg Index: tests/installall/config/sheet-names.cfg ================================================================== --- /dev/null +++ tests/installall/config/sheet-names.cfg @@ -0,0 +1,2 @@ +megatest.config +runconfigs.config ADDED tests/installall/config/sxml/_sheets.sxml Index: tests/installall/config/sxml/_sheets.sxml ================================================================== --- /dev/null +++ tests/installall/config/sxml/_sheets.sxml @@ -0,0 +1,51 @@ +((@ (http://www.w3.org/2001/XMLSchema-instance:schemaLocation + "http://www.gnumeric.org/v9.xsd")) + (http://www.gnumeric.org/v10.dtd:Version + (@ (Minor "17") (Major "10") (Full "1.10.17") (Epoch "1"))) + (http://www.gnumeric.org/v10.dtd:Attributes + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_horizontal_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_vertical_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::show_notebook_tabs") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::do_auto_completion") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::is_protected") + (http://www.gnumeric.org/v10.dtd:value "FALSE"))) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:document-meta + (@ (urn:oasis:names:tc:opendocument:xmlns:office:1.0:version "1.2")) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:meta + (http://purl.org/dc/elements/1.1/:date "2013-07-21T23:45:07Z") + (urn:oasis:names:tc:opendocument:xmlns:meta:1.0:creation-date + "2013-07-21T23:42:35Z"))) + (http://www.gnumeric.org/v10.dtd:Calculation + (@ (MaxIterations "100") + (ManualRecalc "0") + (IterationTolerance "0.001") + (FloatRadix "2") + (FloatDigits "53") + (EnableIteration "1"))) + (http://www.gnumeric.org/v10.dtd:SheetNameIndex + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "megatest.config") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "runconfigs.config")) + (http://www.gnumeric.org/v10.dtd:Geometry (@ (Width "1440") (Height "647"))) + (http://www.gnumeric.org/v10.dtd:UIData (@ (SelectedTab "0")))) ADDED tests/installall/config/sxml/_workbook.sxml Index: tests/installall/config/sxml/_workbook.sxml ================================================================== --- /dev/null +++ tests/installall/config/sxml/_workbook.sxml @@ -0,0 +1,1 @@ +(*TOP* (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"")) ADDED tests/installall/config/sxml/megatest.config.sxml Index: tests/installall/config/sxml/megatest.config.sxml ================================================================== --- /dev/null +++ tests/installall/config/sxml/megatest.config.sxml @@ -0,0 +1,108 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "5") + (http://www.gnumeric.org/v10.dtd:MaxRow "7") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"megatest.config\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[TAB]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "Page &[PAGE]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "112.5") (No "0") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo (@ (Unit "48") (No "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "63.75") (No "2") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo (@ (Unit "48") (No "3"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "86.25") (No "4") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo (@ (Unit "48") (No "5")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.75")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.75") (No "0") (Count "8")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "0") (CursorCol "0")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "0")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0")))) ADDED tests/installall/config/sxml/runconfigs.config.sxml Index: tests/installall/config/sxml/runconfigs.config.sxml ================================================================== --- /dev/null +++ tests/installall/config/sxml/runconfigs.config.sxml @@ -0,0 +1,111 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "3") + (http://www.gnumeric.org/v10.dtd:MaxRow "7") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"runconfigs.config\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[TAB]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "Page &[PAGE]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "108.8") (No "0") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "97.5") (No "1") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "100.5") (No "2") (HardSize "1") (Count "2")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.75")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "0") (Count "2"))) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "12.75") (No "2"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "3") (Count "2"))) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "12.75") (No "5"))) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "13.5") (No "6"))) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "12.75") (No "7")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "7") (CursorCol "3")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "7") (startCol "3") (endRow "7") (endCol "3")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0")))) ADDED tests/installall/configs/chicken-4.8.0.4.config Index: tests/installall/configs/chicken-4.8.0.4.config ================================================================== --- /dev/null +++ tests/installall/configs/chicken-4.8.0.4.config @@ -0,0 +1,1 @@ +CHICKEN_URL http://code.call-cc.org/releases/4.8.0/chicken-4.8.0.4.tar.gz ADDED tests/installall/configs/chicken-4.8.1.config Index: tests/installall/configs/chicken-4.8.1.config ================================================================== --- /dev/null +++ tests/installall/configs/chicken-4.8.1.config @@ -0,0 +1,1 @@ +CHICKEN_URL http://code.call-cc.org/dev-snapshots/2013/01/04/chicken-4.8.1.tar.gz ADDED tests/installall/megatest.config Index: tests/installall/megatest.config ================================================================== --- /dev/null +++ tests/installall/megatest.config @@ -0,0 +1,24 @@ +[fields] +CHICKEN_VERSION TEXT +MEGATEST_VERSION TEXT +IUPMODE TEXT +BUILD_TAG TEXT + +[setup] +max_concurrent_jobs 6 +linktree #{getenv MT_RUN_AREA_HOME}/links +testcopycmd cp --remove-destination -rsv TEST_SRC_PATH/. TEST_TARG_PATH/. >> TEST_TARG_PATH/mt_launch.log 2>> TEST_TARG_PATH/mt_launch.log + +[jobtools] +useshell yes +launcher nbfind + +[env-override] +EXAMPLE_VAR example value + +[server] +port 9080 + +[disks] +disk0 #{getenv MT_RUN_AREA_HOME}/runs + ADDED tests/installall/runconfigs.config Index: tests/installall/runconfigs.config ================================================================== --- /dev/null +++ tests/installall/runconfigs.config @@ -0,0 +1,38 @@ +[.............] +# +# [CHICKEN_VERSION/MEGATEST_VERSION/IUPMODE/PLATFORM/BUILD_TAG] +# + +[default] +ALLTESTS see this variable +PREFIX #{getenv MT_RUN_AREA_HOME}/#{getenv BUILD_TAG}/#{getenv MT_RUNNAME} +DOWNLOADS #{getenv MT_RUN_AREA_HOME}/downloads +IUPLIB 26g4 +PLATFORM linux +LOGPRO_VERSION v1.05 +BUILDSQLITE yes +SQLITE3_VERSION 3071401 +ZEROMQ_VERSION 2.2.0 +logpro_VERSION v1.08 +stml_VERSION v0.901 +megatest_VERSION v1.5511 + +[include configs/hicken-#{getenv CHICKEN_VERSION}.config] + +# Currently must have at least one variable in a section +[4.8.0/trunk/bin/std] +IUP_VERSION na + +[4.8.0.4/trunk/src/std] +CHICKEN_URL http://code.call-cc.org/releases/4.8.0/chicken-4.8.0.4.tar.gz +IUP_VERSION na + +[4.8.1/trunk/src/std] +IUP_VERSION na + +[4.8.0/v1.5508/opt] +IUP_VERSION na +PREFIX /opt/chicken/4.8.0 + +[4.8.0/trunk/centos5.7vm] +BUILDSQLITE no ADDED tests/installall/tests/canvas-draw/install.logpro Index: tests/installall/tests/canvas-draw/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/canvas-draw/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/canvas-draw/install.sh Index: tests/installall/tests/canvas-draw/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/canvas-draw/install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/canvas-draw/testconfig Index: tests/installall/tests/canvas-draw/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/canvas-draw/testconfig @@ -0,0 +1,18 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +install install.sh + +# Test requirements are specified here +[requirements] +waiton iuplib setup + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the canvas-draw egg +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/chicken/compile.logpro Index: tests/installall/tests/chicken/compile.logpro ================================================================== --- /dev/null +++ tests/installall/tests/chicken/compile.logpro @@ -0,0 +1,10 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Leaving directory ..." #/Leaving directory/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:ignore in "LogFileBody" >= 0 "Ignore HAVE_STRERROR" #/HAVE_STRERROR/) + +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/chicken/compile.sh Index: tests/installall/tests/chicken/compile.sh ================================================================== --- /dev/null +++ tests/installall/tests/chicken/compile.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +cd chicken-${CHICKEN_VERSION} +make PLATFORM=${PLATFORM} PREFIX=${PREFIX} ADDED tests/installall/tests/chicken/download.logpro Index: tests/installall/tests/chicken/download.logpro ================================================================== --- /dev/null +++ tests/installall/tests/chicken/download.logpro @@ -0,0 +1,11 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "README file must be seen" #/README$/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! + +(expect:ignore in "LogFileBody" >= 0 "Ignore error flagged by finalizer-error-test" #/\w+-error/) + +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/chicken/download.sh Index: tests/installall/tests/chicken/download.sh ================================================================== --- /dev/null +++ tests/installall/tests/chicken/download.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +if [ ! -e ${DOWNLOADS}/chicken-${CHICKEN_VERSION}.tar.gz ]; then + if [ "${CHICKEN_URL}" == "" ]; then + CHICKEN_URL=http://code.call-cc.org/releases/${CHICKEN_VERSION}/chicken-${CHICKEN_VERSION}.tar.gz + fi + echo "Downloading $CHICKEN_URL" + (cd ${DOWNLOADS};wget ${CHICKEN_URL}) +fi + +ls -l ${DOWNLOADS}/chicken-${CHICKEN_VERSION}.tar.gz + +tar xfvz ${DOWNLOADS}/chicken-${CHICKEN_VERSION}.tar.gz + +ls -l chicken-${CHICKEN_VERSION} ADDED tests/installall/tests/chicken/install.logpro Index: tests/installall/tests/chicken/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/chicken/install.logpro @@ -0,0 +1,11 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Leaving directory" #/Leaving directory/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! + +(expect:ignore in "LogFileBody" >= 0 "Ignore error in some filenames" #/\w+-errors/) + +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/chicken/install.sh Index: tests/installall/tests/chicken/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/chicken/install.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh +# source $PREFIX + +cd chicken-${CHICKEN_VERSION} +make PLATFORM=${PLATFORM} PREFIX=${PREFIX} install + +ls -l ${PREFIX}/bin ADDED tests/installall/tests/chicken/testconfig Index: tests/installall/tests/chicken/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/chicken/testconfig @@ -0,0 +1,22 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +download download.sh +compile compile.sh +install install.sh + +# Test requirements are specified here +[requirements] +waiton setup +# priority 10 + +# Iteration for your tests are controlled by the items section +[items] +# CHICKEN_VERSION 4.8.0 + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Download and install chicken scheme +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/eggs/install.logpro Index: tests/installall/tests/eggs/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/eggs/install.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Last thing done is chmod ..." #/chmod /) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" >= 0 "Ignore someword-errors" #/\w+-error/) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/eggs/install.sh Index: tests/installall/tests/eggs/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/eggs/install.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +$PREFIX/bin/chicken-install $PROX $EGG_NAME + ADDED tests/installall/tests/eggs/testconfig Index: tests/installall/tests/eggs/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/eggs/testconfig @@ -0,0 +1,20 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +install install.sh + +# Test requirements are specified here +[requirements] +waiton chicken setup +priority 9 + +# Iteration for your tests are controlled by the items section +[items] +EGG_NAME matchable readline apropos base64 regex-literals format regex-case test coops trace csv dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt json md5 ssax sxml-serializer sxml-modifications salmonella sql-de-lite postgresql + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Download and install eggs with no significant prerequisites +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/ffcall/compile.logpro Index: tests/installall/tests/ffcall/compile.logpro ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/compile.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Leaving directory" #/Leaving directory/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/ffcall/compile.sh Index: tests/installall/tests/ffcall/compile.sh ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/compile.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +cd ffcall +./configure --prefix=${PREFIX} --enable-shared +make ADDED tests/installall/tests/ffcall/download.logpro Index: tests/installall/tests/ffcall/download.logpro ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/download.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "VERSION" #/ VERSION/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/ffcall/download.sh Index: tests/installall/tests/ffcall/download.sh ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/download.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +if ! [[ -e ${DOWNLOADS}/ffcall.tar.gz ]] ; then + (cd ${DOWNLOADS};wget http://www.kiatoa.com/matt/iup/ffcall.tar.gz ) +fi + +tar xfvz ${DOWNLOADS}/ffcall.tar.gz + +ls -l ffcall ADDED tests/installall/tests/ffcall/install.logpro Index: tests/installall/tests/ffcall/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Leaving directory" #/Leaving directory/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/ffcall/install.sh Index: tests/installall/tests/ffcall/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/install.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +cd ffcall +make install ADDED tests/installall/tests/ffcall/testconfig Index: tests/installall/tests/ffcall/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/ffcall/testconfig @@ -0,0 +1,20 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +download download.sh +compile compile.sh +install install.sh + +# Test requirements are specified here +[requirements] +waiton setup + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the ffcall library +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/iup/install.logpro Index: tests/installall/tests/iup/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iup/install.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "chmod is roughly last thing that happens" #/chmod /) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" >= 0 "Ignore setup-error-handling" #/\w+-error/) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iup/install.sh Index: tests/installall/tests/iup/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/iup/install.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh +# source $PREFIX/setup-chicken4x.sh + +export CSCLIBS=`echo $LD_LIBRARY_PATH | sed 's/:/ -L/g'` +CSC_OPTIONS="-I$PREFIX/include -L$CSCLIBS" $PREFIX/bin/chicken-install $PROX -D no-library-checks -feature disable-iup-web iup +# CSC_OPTIONS="-I$PREFIX/include -L$CSCLIBS" $CHICKEN_INSTALL $PROX -D no-library-checks -feature disable-iup-web -deploy -prefix $DEPLOYTARG iup +# iup:1.0.2 +CSC_OPTIONS="-I$PREFIX/include -L$CSCLIBS" $PREFIX/bin/chicken-install $PROX -D no-library-checks canvas-draw +# CSC_OPTIONS="-I$PREFIX/include -L$CSCLIBS" $CHICKEN_INSTALL $PROX -D no-library-checks -deploy -prefix $DEPLOYTARG canvas-draw ADDED tests/installall/tests/iup/testconfig Index: tests/installall/tests/iup/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/iup/testconfig @@ -0,0 +1,18 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +install install.sh + +# Test requirements are specified here +[requirements] +waiton iup#{getenv IUPMODE}lib tougheggs + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install iup egg +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/iupbinlib/compile.logpro Index: tests/installall/tests/iupbinlib/compile.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/compile.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupbinlib/compile.sh Index: tests/installall/tests/iupbinlib/compile.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/compile.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/iupbinlib/download.logpro Index: tests/installall/tests/iupbinlib/download.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/download.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "README file should show up" #/README/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupbinlib/download.sh Index: tests/installall/tests/iupbinlib/download.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/download.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh +# source $PREFIX/setup-chicken4x.sh + +if [[ `uname -a | grep x86_64` == "" ]]; then + export ARCHSIZE='' +else + export ARCHSIZE=64_ +fi + # export files="cd-5.4.1_Linux${IUPLIB}_lib.tar.gz im-3.6.3_Linux${IUPLIB}_lib.tar.gz iup-3.5_Linux${IUPLIB}_lib.tar.gz" +if [[ x$USEOLDIUP == "x" ]];then + export files="cd-5.5.1_Linux${IUPLIB}_${ARCHSIZE}lib.tar.gz im-3.8_Linux${IUPLIB}_${ARCHSIZE}lib.tar.gz iup-3.6_Linux${IUPLIB}_${ARCHSIZE}lib.tar.gz" +else + echo WARNING: Using old IUP libraries + export files="cd-5.4.1_Linux${IUPLIB}_${ARCHSIZE}lib.tar.gz im-3.6.3_Linux${IUPLIB}_${ARCHSIZE}lib.tar.gz iup-3.5_Linux${IUPLIB}_${ARCHSIZE}lib.tar.gz" +fi + +mkdir -p $PREFIX/iuplib +for a in `echo $files` ; do + if ! [[ -e ${DOWNLOADS}/$a ]] ; then + (cd ${DOWNLOADS};wget http://www.kiatoa.com/matt/iup/$a) + fi + echo Untarring $a into $PREFIX/lib + (cd $PREFIX/lib;tar xfvz ${DOWNLOADS}/$a;mv include/* ../include) +done + ADDED tests/installall/tests/iupbinlib/install.logpro Index: tests/installall/tests/iupbinlib/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupbinlib/install.sh Index: tests/installall/tests/iupbinlib/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/install.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/iupbinlib/testconfig Index: tests/installall/tests/iupbinlib/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/testconfig @@ -0,0 +1,18 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +download download.sh + +# Test requirements are specified here +[requirements] +waiton ffcall setup + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the iup library if it is not already installed +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/iupbinlib/untar.logpro Index: tests/installall/tests/iupbinlib/untar.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/untar.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupbinlib/untar.sh Index: tests/installall/tests/iupbinlib/untar.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupbinlib/untar.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/iupsrclib/cd.logpro Index: tests/installall/tests/iupsrclib/cd.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/cd.logpro @@ -0,0 +1,3 @@ +(expect:ignore in "LogFileBody" >= 0 "Ignore these binary operator errors for now" #/error: missing binary operator/) + +(load "compile.logpro") ADDED tests/installall/tests/iupsrclib/compile.logpro Index: tests/installall/tests/iupsrclib/compile.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/compile.logpro @@ -0,0 +1,12 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Completed signature" #/(Dynamic Library.*Done|Leaving directory|Nothing to be done)/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" >= 0 "Ignore files with error in name" #/error.[ch]/) +(expect:ignore in "LogFileBody" >= 0 "Ignore files with errors in name" #/errors.[ch]/) +(expect:ignore in "LogFileBody" >= 0 "Ignore files with warn in name" #/warning.[ch]/) + +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupsrclib/compile.sh Index: tests/installall/tests/iupsrclib/compile.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/compile.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Run your step here + +pkg=$1 + +source $PREFIX/buildsetup.sh + +export LUA_SUFFIX= +export LUA_INC=$MT_TEST_RUN_DIR/lua52/include + +if [[ $pkg == "lua52" ]]; then + (cd $pkg/src;make $PLATFORM) +else + (cd $pkg/src;make) +fi + ADDED tests/installall/tests/iupsrclib/download.logpro Index: tests/installall/tests/iupsrclib/download.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/download.logpro @@ -0,0 +1,13 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "README file should show up" #/README/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! + +(expect:ignore in "LogFileBody" >= 0 "Ignore files with error in name" #/error.[ch]/) +(expect:ignore in "LogFileBody" >= 0 "Ignore files with errors in name" #/errors.[ch]/) +(expect:ignore in "LogFileBody" >= 0 "Ignore files with warn in name" #/warning.[ch]/) + +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupsrclib/download.sh Index: tests/installall/tests/iupsrclib/download.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/download.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh + +mkdir -p $PREFIX/iuplib +for a in cd-5.6.1_Sources.tar.gz im-3.8.1_Sources.tar.gz iup-3.8_Sources.tar.gz lua-5.2.1_Sources.tar.gz; do + if ! [[ -e ${DOWNLOADS}/$a ]] ; then + (cd ${DOWNLOADS};wget http://www.kiatoa.com/matt/iup/$a) + fi + tar xfvz ${DOWNLOADS}/$a +done + +find . -type d -exec chmod ug+x {} \; ADDED tests/installall/tests/iupsrclib/im.logpro Index: tests/installall/tests/iupsrclib/im.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/im.logpro @@ -0,0 +1,1 @@ +(load "compile.logpro") ADDED tests/installall/tests/iupsrclib/install.logpro Index: tests/installall/tests/iupsrclib/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupsrclib/install.sh Index: tests/installall/tests/iupsrclib/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/install.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh + +# The so files +cp -f im/lib/Linux26g4/*.so $PREFIX/lib +cp -f cd/lib/Linux26g4/*.so $PREFIX/lib +cp -f iup/lib/Linux26g4/*.so $PREFIX/lib + +# The development files +mkdir -p $PREFIX/include/im +cp -fR im/include/*.h $PREFIX/include/im +cp -f im/lib/Linux26g4/*.a $PREFIX/lib + +mkdir -p $PREFIX/include/cd +cp -f cd/include/*.h $PREFIX/include/cd +cp -f cd/lib/Linux26g4/*.a $PREFIX/lib + +mkdir -p /usr/include/iup +cp -f iup/include/*.h $PREFIX/include/iup +cp -f iup/lib/Linux26g4/*.a $PREFIX/lib ADDED tests/installall/tests/iupsrclib/iup.logpro Index: tests/installall/tests/iupsrclib/iup.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/iup.logpro @@ -0,0 +1,3 @@ +(expect:ignore in "LogFileBody" >= 0 "Ignore these binary operator errors for now" #/error: missing binary operator/ expires: "10/10/2013") + +(load "compile.logpro") ADDED tests/installall/tests/iupsrclib/lua.logpro Index: tests/installall/tests/iupsrclib/lua.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/lua.logpro @@ -0,0 +1,1 @@ +(load "compile.logpro") ADDED tests/installall/tests/iupsrclib/testconfig Index: tests/installall/tests/iupsrclib/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/testconfig @@ -0,0 +1,22 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +download download.sh +lua compile.sh lua52 +im compile.sh im +cd compile.sh cd +iup compile.sh iup + +# Test requirements are specified here +[requirements] +waiton ffcall setup + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the iup library if it is not already installed +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/iupsrclib/untar.logpro Index: tests/installall/tests/iupsrclib/untar.logpro ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/untar.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/iupsrclib/untar.sh Index: tests/installall/tests/iupsrclib/untar.sh ================================================================== --- /dev/null +++ tests/installall/tests/iupsrclib/untar.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/mmisc/clone.logpro Index: tests/installall/tests/mmisc/clone.logpro ================================================================== --- /dev/null +++ tests/installall/tests/mmisc/clone.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Output from fossil" #/^repository:\s+/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/i) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/mmisc/clone.sh Index: tests/installall/tests/mmisc/clone.sh ================================================================== --- /dev/null +++ tests/installall/tests/mmisc/clone.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh + +fossil clone http://www.kiatoa.com/fossils/$FSLPKG $FSLPKG.fossil + +mkdir src +cd src +fossil open ../$FSLPKG.fossil --nested +fossil co ${$FSLPKG}_VERSION} ADDED tests/installall/tests/mmisc/install.logpro Index: tests/installall/tests/mmisc/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/mmisc/install.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Always get a chmod at the end of install" #/chmod.*logpro.setup-info/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in setup-error-handling" #/setup-error-handling/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/i) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/mmisc/install.sh Index: tests/installall/tests/mmisc/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/mmisc/install.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh +cd src +if [ $FSLPKG == "logpro" ];then + chicken-install +elif [ $FSLPKG == "stml" ];then + cp install.cfg.template install.cfg + cp requirements.scm.template requirements.scm + make + make install +else + make + make install PREFIX=$PREFIX +fi ADDED tests/installall/tests/mmisc/testconfig Index: tests/installall/tests/mmisc/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/mmisc/testconfig @@ -0,0 +1,21 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +clone clone.sh +install install.sh + +# Test requirements are specified here +[requirements] +waiton eggs setup + +# Iteration for your tests are controlled by the items section +[items] +FSLPKG logpro stml megatest + + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the logpro tool +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/opensrc/clone.logpro Index: tests/installall/tests/opensrc/clone.logpro ================================================================== --- /dev/null +++ tests/installall/tests/opensrc/clone.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Output from fossil" (list #/^repository:\s+/ #/comment:/)) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/i) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/opensrc/clone.sh Index: tests/installall/tests/opensrc/clone.sh ================================================================== --- /dev/null +++ tests/installall/tests/opensrc/clone.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh + +parentdir=$MT_LINKTREE/$MT_TARGET/$MT_RUNNAME + +lockfile $parentdir/clone.lock +if [ ! -e $parentdir/opensrc.fossil ];then + fossil clone http://www.kiatoa.com/fossils/opensrc $parentdir/opensrc.fossil +fi + +if [ ! -e $parentdir/src/dbi ];then + mkdir -p $parentdir/src + (cd $parentdir/src;fossil open $parentdir/opensrc.fossil --nested) +else + (cd $parentdir/src;fossil sync;fossil co trunk;fossil status) +fi +rm -f $parentdir/clone.lock + +ln -sf $parentdir/src $MT_TEST_RUN_DIR/src + ADDED tests/installall/tests/opensrc/install.logpro Index: tests/installall/tests/opensrc/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/opensrc/install.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Always get a chmod at the end of install" #/chmod.*.setup-info/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in setup-error-handling" #/setup-error-handling/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/i) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/opensrc/install.sh Index: tests/installall/tests/opensrc/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/opensrc/install.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh +cd src/$MODULE_NAME +chicken-install ADDED tests/installall/tests/opensrc/testconfig Index: tests/installall/tests/opensrc/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/opensrc/testconfig @@ -0,0 +1,20 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +clone clone.sh +install install.sh + +# Test requirements are specified here +[requirements] +waiton eggs setup sqlite3 + +# Iteration for your tests are controlled by the items section +[items] +MODULE_NAME dbi margs qtree vcd xfig mutils + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the eggs from the opensrc fossil +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/setup/setup.logpro Index: tests/installall/tests/setup/setup.logpro ================================================================== --- /dev/null +++ tests/installall/tests/setup/setup.logpro @@ -0,0 +1,10 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "ALL DONE" #/ALL DONE$/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! + + +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/setup/setup.sh Index: tests/installall/tests/setup/setup.sh ================================================================== --- /dev/null +++ tests/installall/tests/setup/setup.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Run your step here + +cksetupsh=$PREFIX/setup-chicken4x.sh +cksetupcsh=$PREFIX/setup-chicken4x.csh +setupsh=$PREFIX/buildsetup.sh + +# make a cache dir +mkdir -p $DOWNLOADS +mkdir -p $PREFIX + +# File for users to source to run chicken +echo "# Source me to setup to to run chicken" > $cksetupsh +echo "export PATH=$PREFIX/bin:\$PATH" > $cksetupsh +echo "export LD_LIBRARY_PATH=$PREFIX/lib" >> $cksetupsh + +# tcsh version +echo "setenv PATH $PREFIX/bin:\$PATH" > $cksetupcsh +echo "setenv LD_LIBRARY_PATH $PREFIX/lib" >> $cksetupcsh + +# File to source for build process +echo "export PATH=$PREFIX/bin:\$PATH" > $setupsh +echo "export LD_LIBRARY_PATH=$PREFIX/lib" >> $setupsh + +if [[ $proxy == "" ]]; then + echo 'Please set the environment variable "proxy" to host.com:port (e.g. foo.com:1234) to use a proxy' +else + echo "export http_proxy=http://$proxy" >> $setupsh + echo "export PROX=\"-proxy $proxy\"" >> $setupsh +fi + +echo "export PREFIX=$PREFIX" >> $setupsh + +echo ALL DONE ADDED tests/installall/tests/setup/testconfig Index: tests/installall/tests/setup/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/setup/testconfig @@ -0,0 +1,18 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +setup setup.sh + +# Test requirements are specified here +[requirements] +# priority 10 + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Download and install chicken scheme +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/sqlite3/compile.logpro Index: tests/installall/tests/sqlite3/compile.logpro ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/compile.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Leaving directory" #/(Leaving directory|Nothing to be done for|creating sqlite3)/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" >= 0 "Ignore strerror_r" #/strerror_r/i) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/sqlite3/compile.sh Index: tests/installall/tests/sqlite3/compile.sh ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/compile.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +cd sqlite-autoconf-$SQLITE3_VERSION +./configure --prefix=$PREFIX + +make ADDED tests/installall/tests/sqlite3/download.logpro Index: tests/installall/tests/sqlite3/download.logpro ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/download.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "sqlite-autoconf" #/sqlite-autoconf/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/sqlite3/download.sh Index: tests/installall/tests/sqlite3/download.sh ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/download.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +echo Install sqlite3 +if ! [[ -e ${DOWNLOADS}/sqlite-autoconf-${SQLITE3_VERSION}.tar.gz ]]; then + (cd ${DOWNLOADS};wget http://www.sqlite.org/sqlite-autoconf-${SQLITE3_VERSION}.tar.gz) +fi + +tar xfz ${DOWNLOADS}/sqlite-autoconf-${SQLITE3_VERSION}.tar.gz + +ls -l sqlite-autoconf-${SQLITE3_VERSION}.tar.gz ADDED tests/installall/tests/sqlite3/install.logpro Index: tests/installall/tests/sqlite3/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Leaving directory" #/Leaving directory/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/sqlite3/install.sh Index: tests/installall/tests/sqlite3/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +cd sqlite-autoconf-$SQLITE3_VERSION +make install + ADDED tests/installall/tests/sqlite3/installegg.logpro Index: tests/installall/tests/sqlite3/installegg.logpro ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/installegg.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "chmod sqlite3" #/chmod.*sqlite3/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" >= 0 "Ignore setup-error-handling" #/setup-error-handling/) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/sqlite3/installegg.sh Index: tests/installall/tests/sqlite3/installegg.sh ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/installegg.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +CSC_OPTIONS="-I$PREFIX/include -L$PREFIX/lib" $PREFIX/bin/chicken-install $PROX sqlite3 ADDED tests/installall/tests/sqlite3/testconfig Index: tests/installall/tests/sqlite3/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/sqlite3/testconfig @@ -0,0 +1,24 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +download download.sh +compile compile.sh +install install.sh +installegg installegg.sh + +# Test requirements are specified here +[requirements] +# We waiton chicken because this one installs the egg. It would behove us to split this +# into two tests ... +waiton tougheggs +priority 2 + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install sqlite3 library for systems where it is not installed +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/tougheggs/install.logpro Index: tests/installall/tests/tougheggs/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/tougheggs/install.logpro @@ -0,0 +1,9 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Last thing done is chmod ..." #/chmod /) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" >= 0 "Ignore someword-errors" #/\w+-error/) +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/tougheggs/install.sh Index: tests/installall/tests/tougheggs/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/tougheggs/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh + +lockfile $PREFIX/eggs.lock +$PREFIX/bin/chicken-install $PROX $EGG_NAME +rm -f $PREFIX/eggs.lock ADDED tests/installall/tests/tougheggs/testconfig Index: tests/installall/tests/tougheggs/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/tougheggs/testconfig @@ -0,0 +1,19 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +install install.sh + +# Test requirements are specified here +[requirements] +waiton eggs + +# Iteration for your tests are controlled by the items section +[items] +EGG_NAME intarweb http-client awful uri-common spiffy-request-vars spiffy apropos spiffy-directory-listing + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Download and install eggs with no significant prerequisites +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/zmq/install.logpro Index: tests/installall/tests/zmq/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/zmq/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/zmq/install.sh Index: tests/installall/tests/zmq/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/zmq/install.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/zmq/testconfig Index: tests/installall/tests/zmq/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/zmq/testconfig @@ -0,0 +1,18 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +install install.sh + +# Test requirements are specified here +[requirements] +waiton zmqlib chicken setup + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the zmq egg +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/zmqlib/compile.logpro Index: tests/installall/tests/zmqlib/compile.logpro ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/compile.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/zmqlib/compile.sh Index: tests/installall/tests/zmqlib/compile.sh ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/compile.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/zmqlib/download.logpro Index: tests/installall/tests/zmqlib/download.logpro ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/download.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/zmqlib/download.sh Index: tests/installall/tests/zmqlib/download.sh ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/download.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/zmqlib/install.logpro Index: tests/installall/tests/zmqlib/install.logpro ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/install.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/zmqlib/install.sh Index: tests/installall/tests/zmqlib/install.sh ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# Run your step here + +source $PREFIX/buildsetup.sh ADDED tests/installall/tests/zmqlib/testconfig Index: tests/installall/tests/zmqlib/testconfig ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/testconfig @@ -0,0 +1,21 @@ +# Add additional steps here. Format is "stepname script" +[ezsteps] +download download.sh +untar untar.sh +compile compile.sh +install install.sh + +# Test requirements are specified here +[requirements] +waiton setup + +# Iteration for your tests are controlled by the items section +[items] + +# test_meta is a section for storing additional data on your test +[test_meta] +author matt +owner matt +description Install the zmq library if it doesn't already exist +tags tagone,tagtwo +reviewed never ADDED tests/installall/tests/zmqlib/untar.logpro Index: tests/installall/tests/zmqlib/untar.logpro ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/untar.logpro @@ -0,0 +1,8 @@ +;; You should have at least one expect:required. This ensures that your process ran +(expect:required in "LogFileBody" > 0 "Put description here" #/put pattern here/) + +;; You may need ignores to suppress false error or warning hits from the later expects +;; NOTE: Order is important here! +(expect:ignore in "LogFileBody" < 99 "Ignore the word error in comments" #/^\/\/.*error/) +(expect:warning in "LogFileBody" = 0 "Any warning" #/warn/) +(expect:error in "LogFileBody" = 0 "Any error" (list #/ERROR/ #/error/i)) ;; but disallow any other errors ADDED tests/installall/tests/zmqlib/untar.sh Index: tests/installall/tests/zmqlib/untar.sh ================================================================== --- /dev/null +++ tests/installall/tests/zmqlib/untar.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Run your step here +source $PREFIX/buildsetup.sh ADDED txtdb/metadat.scm Index: txtdb/metadat.scm ================================================================== --- /dev/null +++ txtdb/metadat.scm @@ -0,0 +1,553 @@ +(define minimal-sxml + '(*TOP* (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"") + (http://www.gnumeric.org/v10.dtd:Workbook + (@ (http://www.w3.org/2001/XMLSchema-instance:schemaLocation + "http://www.gnumeric.org/v9.xsd")) + (http://www.gnumeric.org/v10.dtd:Version + (@ (Minor "17") (Major "10") (Full "1.10.17") (Epoch "1"))) + (http://www.gnumeric.org/v10.dtd:Attributes + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_horizontal_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_vertical_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_notebook_tabs") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::do_auto_completion") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::is_protected") + (http://www.gnumeric.org/v10.dtd:value "FALSE"))) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:document-meta + (@ (urn:oasis:names:tc:opendocument:xmlns:office:1.0:version "1.2")) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:meta + (http://purl.org/dc/elements/1.1/:date "2013-07-26T05:41:51Z") + (urn:oasis:names:tc:opendocument:xmlns:meta:1.0:creation-date + "2013-07-26T05:41:10Z"))) + (http://www.gnumeric.org/v10.dtd:Calculation + (@ (MaxIterations "100") + (ManualRecalc "0") + (IterationTolerance "0.001") + (FloatRadix "2") + (FloatDigits "53") + (EnableIteration "1"))) + (http://www.gnumeric.org/v10.dtd:SheetNameIndex + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "Sheet1")) + (http://www.gnumeric.org/v10.dtd:Geometry + (@ (Width "1440") (Height "647"))) + (http://www.gnumeric.org/v10.dtd:Sheets + (http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:Name "Sheet1") + (http://www.gnumeric.org/v10.dtd:MaxCol "-1") + (http://www.gnumeric.org/v10.dtd:MaxRow "-1") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"Sheet1\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:left + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles + (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[TAB]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "Page &[PAGE]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") + (startCol "0") + (endRow "65535") + (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols (@ (DefaultSizePts "48"))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.75"))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "0") (CursorCol "0")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "0")))) + (http://www.gnumeric.org/v10.dtd:Cells) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0"))))) + (http://www.gnumeric.org/v10.dtd:UIData (@ (SelectedTab "0")))))) + +(define sheet-meta + '(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "8") + (http://www.gnumeric.org/v10.dtd:MaxRow "18") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"First_Sheet\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "1")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "1") (startCol "0") (endRow "17") (endCol "1")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "hh\":\"mm\":\"ss AM/PM") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "18") (startCol "0") (endRow "31") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "32") (startCol "0") (endRow "255") (endCol "7")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "256") (startCol "0") (endRow "65535") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "2") (endRow "1") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "2") (startCol "2") (endRow "17") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "0") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "3") (endRow "31") (endCol "7")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "8") (endRow "255") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "64") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo (@ (Unit "48") (No "0"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "99") (No "1") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "64.01") (No "2") (Count "7")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "12.64") (No "0"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "1") (Count "17"))) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "12.1") (No "18")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "3") (CursorCol "1")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "3") (startCol "1") (endRow "3") (endCol "1")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout + (@ (TopLeft "A2")) + (http://www.gnumeric.org/v10.dtd:FreezePanes + (@ (UnfrozenTopLeft "A2") (FrozenTopLeft "A1")))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0"))))) + +(define sheets-meta + '((@ (http://www.w3.org/2001/XMLSchema-instance:schemaLocation + "http://www.gnumeric.org/v9.xsd")) + (http://www.gnumeric.org/v10.dtd:Version + (@ (Minor "17") (Major "10") (Full "1.10.17") (Epoch "1"))) + (http://www.gnumeric.org/v10.dtd:Attributes + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_horizontal_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_vertical_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::show_notebook_tabs") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::do_auto_completion") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::is_protected") + (http://www.gnumeric.org/v10.dtd:value "FALSE"))) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:document-meta + (@ (urn:oasis:names:tc:opendocument:xmlns:office:1.0:version "1.2")) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:meta + (http://purl.org/dc/elements/1.1/:date "2013-07-26T04:47:02Z") + (urn:oasis:names:tc:opendocument:xmlns:meta:1.0:creation-date + "2013-07-26T04:46:14Z"))) + (http://www.gnumeric.org/v10.dtd:Calculation + (@ (MaxIterations "100") + (ManualRecalc "0") + (IterationTolerance "0.001") + (FloatRadix "2") + (FloatDigits "53") + (EnableIteration "1"))) + (http://www.gnumeric.org/v10.dtd:SheetNameIndex + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "First_Sheet") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "Second-sheet") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "RunsToDo") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "RunsToLock")) + (http://www.gnumeric.org/v10.dtd:Geometry (@ (Width "1440") (Height "647"))) + (http://www.gnumeric.org/v10.dtd:UIData (@ (SelectedTab "1"))))) + +(define workbook-meta + '(*TOP* (*PI* xml "version=\"1.0\" encoding=\"UTF-8\""))) + ADDED txtdb/nada3/First_Sheet.dat Index: txtdb/nada3/First_Sheet.dat ================================================================== --- /dev/null +++ txtdb/nada3/First_Sheet.dat @@ -0,0 +1,153 @@ +[Time] +BLANKVAL +A 0.324305555555556 +B 0.33125 +C 0.334722222222222 +D 0.336805555555556 +E 0.338888888888889 +F 0.340972222222222 +G 0.343055555555556 +H 0.345833333333333 +I 0.347916666666667 +J 0.351388888888889 +K 0.366666666666667 +L 0.379166666666667 +M 0.395833333333333 +N 0.422222222222222 +O 0.452083333333333 +P 0.491666666666667 +Q 0.570833333333333 + +[DeltaTime] +A 0 +B =days(B3,$B$2)*24*60 +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q + +[Ambient] +A 35.4 +B 35.4 +C 35 +D 35 +E 35 +F 35 +G 35 +H 36 +I 36 +J 37 +K 37 +L 38 +M 39 +N 40 +O 41 +P 41 +Q 41.5 + +[Firebox] +A 34.3 +B 72 +C 100 +D 130 +E 145 +F 150 +G 150 +H 158 +I 156 +J 152 +K 134 +L 117 +M 100 +N 91 +O 79 +P 68 +Q 51 + +[2nd_row] +A 34.3 +B 60 +C 90 +D 116 +E 121 +F 125 +G 128 +H 129 +I 128 +J 126 +K 117 +L 108 +M 100 +N 90 +O 78 +P 63 +Q 51 + +[3rd_row] +A 34.1 +B 42 +C 57 +D 69 +E 73 +F 78 +G 82 +H 86 +I 87 +J 89 +K 94 +L 96 +M 93 +N 88 +O 77 +P 64 +Q 51 + +[4th_row] +A 34 +B 39 +C 46 +D 52 +E 54 +F 56 +G 60 +H 62 +I 65 +J 67 +K 77 +L 82 +M 82 +N 81 +O 72 +P 62 +Q 51 + +[Exit] +A 34 +B 68 +C 68 +D 68 +E 68 +F 68 +G 69 +H 70 +I 72 +J 75 +K 107 +L 106 +M 106 +N 100 +O 79 +P 68 +Q 51 + ADDED txtdb/nada3/RunsToDo.dat Index: txtdb/nada3/RunsToDo.dat ================================================================== --- /dev/null +++ txtdb/nada3/RunsToDo.dat @@ -0,0 +1,15 @@ +[a/b/c] +123 a +456 b +789 c + +[d/e/f] +123 e +456 f +789 g + +[g/h/i] +123 h +456 i +789 j + ADDED txtdb/nada3/RunsToLock.dat Index: txtdb/nada3/RunsToLock.dat ================================================================== --- /dev/null +++ txtdb/nada3/RunsToLock.dat @@ -0,0 +1,11 @@ +[def] +ghi jkl +qrst +uvwx +yz12 + +[mno] +abc +def xyz +jkl +mnop ADDED txtdb/nada3/Second-sheet.dat Index: txtdb/nada3/Second-sheet.dat ================================================================== --- /dev/null +++ txtdb/nada3/Second-sheet.dat @@ -0,0 +1,34 @@ +[2] +V2 X +V6 Y +V8 Z +V12 E +V15 B +V17 + + +[A1] +V8 Z +V17 = + +# Just a test really +# +V1 X +V3 X +V5 Y +V7 Y +V10 Z +V11 E +V13 E +V14 B +V16 B +[3] +V2 John, +V6 Tom +V8 Fred +V17 ~ + +# a deeply held belief is a danger to sanity +# +V4 X +row-11 Z +row-18 B ADDED txtdb/nada3/Sheet3.dat Index: txtdb/nada3/Sheet3.dat ================================================================== --- /dev/null +++ txtdb/nada3/Sheet3.dat @@ -0,0 +1,8 @@ +[zeroth title] +row1name +row2name + +[col1title] +row1name row1value +row2nameNoValue +row3name row3value ADDED txtdb/nada3/sheet-names.cfg Index: txtdb/nada3/sheet-names.cfg ================================================================== --- /dev/null +++ txtdb/nada3/sheet-names.cfg @@ -0,0 +1,4 @@ +First_Sheet +Second-sheet +RunsToDo +RunsToLock ADDED txtdb/nada3/sxml/First_Sheet.sxml Index: txtdb/nada3/sxml/First_Sheet.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/First_Sheet.sxml @@ -0,0 +1,460 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "8") + (http://www.gnumeric.org/v10.dtd:MaxRow "19") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"First_Sheet\"") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "Pt") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "4096") (startCol "0") (endRow "65535") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "4") (endRow "255") (endCol "15")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "32") (startCol "0") (endRow "255") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "2") (startCol "2") (endRow "17") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "0") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "3") (endRow "31") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "1") (startCol "0") (endRow "17") (endCol "1")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "hh\":\"mm\":\"ss AM/PM") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "18") (startCol "0") (endRow "31") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "16") (endRow "4095") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "2") (endRow "1") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "64") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "256") (startCol "0") (endRow "4095") (endCol "15")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "1")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0"))))))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "0") (MarginB "2") (MarginA "2"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "99") (No "1") (MarginB "2") (MarginA "2") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "64.01") (No "2") (MarginB "2") (MarginA "2") (Count "7")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.64") (No "0") (MarginB "0") (MarginA "0"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "1") (MarginB "0") (MarginA "0") (Count "17"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "18") (MarginB "0") (MarginA "0") (Count "2")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "3") (CursorCol "1")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "3") (startCol "1") (endRow "3") (endCol "1")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout + (@ (TopLeft "A2")) + (http://www.gnumeric.org/v10.dtd:FreezePanes + (@ (UnfrozenTopLeft "A2") (FrozenTopLeft "A1")))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ShowIter "0") + (SensitivityR "0") + (ProgramR "0") + (ProblemType "0") + (PerformR "0") + (NonNeg "1") + (MaxTime "60") + (MaxIter "1000") + (LimitsR "0") + (Discr "0") + (AutoScale "0") + (AnswerR "0")))) ADDED txtdb/nada3/sxml/RunsToDo.sxml Index: txtdb/nada3/sxml/RunsToDo.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/RunsToDo.sxml @@ -0,0 +1,109 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "3") + (http://www.gnumeric.org/v10.dtd:MaxRow "4") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"RunsToDo\"") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "Pt") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[TAB]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "Page &[PAGE]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0"))))))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "0") (MarginB "2") (MarginA "2") (Count "4")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.75")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "0") (MarginB "0") (MarginA "0") (Count "4"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.75") (No "4") (MarginB "0") (MarginA "0")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "3") (CursorCol "2")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "3") (startCol "2") (endRow "3") (endCol "2")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ShowIter "0") + (SensitivityR "0") + (ProgramR "0") + (ProblemType "0") + (PerformR "0") + (NonNeg "1") + (MaxTime "60") + (MaxIter "1000") + (LimitsR "0") + (Discr "0") + (AutoScale "0") + (AnswerR "0")))) ADDED txtdb/nada3/sxml/RunsToLock.sxml Index: txtdb/nada3/sxml/RunsToLock.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/RunsToLock.sxml @@ -0,0 +1,92 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "1") + (http://www.gnumeric.org/v10.dtd:MaxRow "1") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top (@ (PrefUnit "cm") (Points "120"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "cm") (Points "120")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[TAB]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "Page &[PAGE]") (Left "")))) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0"))))))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "0") (MarginB "2") (MarginA "2") (Count "2")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.75")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.75") (No "0") (MarginB "0") (MarginA "0") (Count "2")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "0") (CursorCol "0")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "0")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ShowIter "0") + (SensitivityR "0") + (ProgramR "0") + (ProblemType "1") + (PerformR "0") + (NonNeg "1") + (MaxTime "0") + (MaxIter "0") + (LimitsR "0") + (Inputs "") + (Discr "0") + (AutoScale "0") + (AnswerR "0")))) ADDED txtdb/nada3/sxml/Second-sheet.sxml Index: txtdb/nada3/sxml/Second-sheet.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/Second-sheet.sxml @@ -0,0 +1,428 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "3") + (http://www.gnumeric.org/v10.dtd:MaxRow "21") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"Second-sheet\"") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "Pt") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "Pt") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "4096") (startCol "0") (endRow "65535") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "4") (endRow "255") (endCol "15")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "32") (startCol "0") (endRow "255") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "17") (startCol "3") (endRow "31") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "31") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "16") (startCol "3") (endRow "16") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "1") + (Rotation "0") + (PatternColor "FFFF:FFFF:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:CCCC:0")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "16") (endRow "4095") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "64") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "1") (startCol "3") (endRow "15") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "3") (endRow "0") (endCol "3")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "28") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0")))))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "256") (startCol "0") (endRow "4095") (endCol "15")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans") + (http://www.gnumeric.org/v10.dtd:StyleBorder + (http://www.gnumeric.org/v10.dtd:Top (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Bottom (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Left (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Right (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Diagonal (@ (Style "0"))) + (http://www.gnumeric.org/v10.dtd:Rev-Diagonal (@ (Style "0"))))))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "64.01") (No "0") (MarginB "2") (MarginA "2"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "1") (MarginB "2") (MarginA "2"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "99") (No "2") (MarginB "2") (MarginA "2") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "227.2") (No "3") (MarginB "2") (MarginA "2") (HardSize "1")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "60") (No "0") (MarginB "0") (MarginA "0") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "1") (MarginB "0") (MarginA "0") (Count "17"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "18") (MarginB "0") (MarginA "0") (Count "4")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "0") (CursorCol "3")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "0") (startCol "3") (endRow "0") (endCol "3")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ShowIter "0") + (SensitivityR "0") + (ProgramR "0") + (ProblemType "0") + (PerformR "0") + (NonNeg "1") + (MaxTime "60") + (MaxIter "1000") + (LimitsR "0") + (Discr "0") + (AutoScale "0") + (AnswerR "0")))) ADDED txtdb/nada3/sxml/Sheet3.sxml Index: txtdb/nada3/sxml/Sheet3.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/Sheet3.sxml @@ -0,0 +1,100 @@ +(http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:MaxCol "0") + (http://www.gnumeric.org/v10.dtd:MaxRow "0") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"Sheet3\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "65535") (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo (@ (Unit "64.01") (No "0")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo (@ (Unit "12.82") (No "0")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "0") (CursorCol "0")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "0")))) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0")))) ADDED txtdb/nada3/sxml/_sheets.sxml Index: txtdb/nada3/sxml/_sheets.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/_sheets.sxml @@ -0,0 +1,46 @@ +((@ (http://www.w3.org/2001/XMLSchema-instance:schemaLocation + "http://www.gnumeric.org/v8.xsd")) + (http://www.gnumeric.org/v10.dtd:Version + (@ (Minor "3") (Major "6") (Full "1.6.3") (Epoch "1"))) + (http://www.gnumeric.org/v10.dtd:Attributes + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_horizontal_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_vertical_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::show_notebook_tabs") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::do_auto_completion") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name "WorkbookView::is_protected") + (http://www.gnumeric.org/v10.dtd:value "FALSE"))) + (http://www.gnumeric.org/v10.dtd:Summary + (http://www.gnumeric.org/v10.dtd:Item + (http://www.gnumeric.org/v10.dtd:name "application") + (http://www.gnumeric.org/v10.dtd:val-string "gnumeric")) + (http://www.gnumeric.org/v10.dtd:Item + (http://www.gnumeric.org/v10.dtd:name "author") + (http://www.gnumeric.org/v10.dtd:val-string "matthew.r.welland"))) + (http://www.gnumeric.org/v10.dtd:SheetNameIndex + (http://www.gnumeric.org/v10.dtd:SheetName "First_Sheet") + (http://www.gnumeric.org/v10.dtd:SheetName "Second-sheet") + (http://www.gnumeric.org/v10.dtd:SheetName "RunsToDo") + (http://www.gnumeric.org/v10.dtd:SheetName "RunsToLock")) + (http://www.gnumeric.org/v10.dtd:Geometry (@ (Width "1440") (Height "647"))) + (http://www.gnumeric.org/v10.dtd:UIData (@ (SelectedTab "3"))) + (http://www.gnumeric.org/v10.dtd:Calculation + (@ (MaxIterations "100") + (ManualRecalc "0") + (IterationTolerance "0.001") + (EnableIteration "1")))) ADDED txtdb/nada3/sxml/_workbook.sxml Index: txtdb/nada3/sxml/_workbook.sxml ================================================================== --- /dev/null +++ txtdb/nada3/sxml/_workbook.sxml @@ -0,0 +1,1 @@ +(*TOP* (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"")) ADDED txtdb/testdata.sxml Index: txtdb/testdata.sxml ================================================================== --- /dev/null +++ txtdb/testdata.sxml @@ -0,0 +1,1273 @@ +(*TOP* (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"") + (http://www.gnumeric.org/v10.dtd:Workbook + (@ (http://www.w3.org/2001/XMLSchema-instance:schemaLocation + "http://www.gnumeric.org/v9.xsd")) + (http://www.gnumeric.org/v10.dtd:Version + (@ (Minor "17") (Major "10") (Full "1.10.17") (Epoch "1"))) + (http://www.gnumeric.org/v10.dtd:Attributes + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_horizontal_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_vertical_scrollbar") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::show_notebook_tabs") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::do_auto_completion") + (http://www.gnumeric.org/v10.dtd:value "TRUE")) + (http://www.gnumeric.org/v10.dtd:Attribute + (http://www.gnumeric.org/v10.dtd:type "4") + (http://www.gnumeric.org/v10.dtd:name + "WorkbookView::is_protected") + (http://www.gnumeric.org/v10.dtd:value "FALSE"))) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:document-meta + (@ (urn:oasis:names:tc:opendocument:xmlns:office:1.0:version "1.2")) + (urn:oasis:names:tc:opendocument:xmlns:office:1.0:meta + (http://purl.org/dc/elements/1.1/:date "2013-07-14T22:32:27Z") + (urn:oasis:names:tc:opendocument:xmlns:meta:1.0:creation-date + "2013-07-13T04:38:00Z"))) + (http://www.gnumeric.org/v10.dtd:Calculation + (@ (MaxIterations "100") + (ManualRecalc "0") + (IterationTolerance "0.001") + (FloatRadix "2") + (FloatDigits "53") + (EnableIteration "1"))) + (http://www.gnumeric.org/v10.dtd:SheetNameIndex + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "First_Sheet") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "Second-sheet") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "Sheet3")) + (http://www.gnumeric.org/v10.dtd:Geometry + (@ (Width "1440") (Height "647"))) + (http://www.gnumeric.org/v10.dtd:Sheets + (http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:Name "First_Sheet") + (http://www.gnumeric.org/v10.dtd:MaxCol "8") + (http://www.gnumeric.org/v10.dtd:MaxRow "17") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"First_Sheet\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles + (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "1")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "1") (startCol "0") (endRow "17") (endCol "1")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "hh\":\"mm\":\"ss AM/PM") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "18") (startCol "0") (endRow "31") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "32") (startCol "0") (endRow "255") (endCol "7")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "256") + (startCol "0") + (endRow "65535") + (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "2") (endRow "1") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "2") (startCol "2") (endRow "17") (endCol "2")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "0") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "3") (endRow "31") (endCol "7")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") (startCol "8") (endRow "255") (endCol "63")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") + (startCol "64") + (endRow "65535") + (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "0"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "99") (No "1") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "64.01") (No "2") (Count "7")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.64") (No "0"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "1") (Count "17")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "29") (CursorCol "1")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "29") + (startCol "1") + (endRow "29") + (endCol "1")))) + (http://www.gnumeric.org/v10.dtd:Cells + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "1")) + "Time") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "2")) + "DeltaTime") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "3")) + "Ambient") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "4")) + "Firebox") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "5")) + "2nd row") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "6")) + "3rd row") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "7")) + "4th row") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "8")) + "Exit ") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "1") (Col "0")) + "A") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "1")) + "0.32430555555555557") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "2")) + "0") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "3")) + "35.399999999999999") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "4")) + "34.299999999999997") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "5")) + "34.299999999999997") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "6")) + "34.100000000000001") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "7")) + "34") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "1") (Col "8")) + "34") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "2") (Col "0")) + "B") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "1")) + "0.33124999999999999") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "2") (ExprID "1") (Col "2")) + "=days(B3,$B$2)*24*60") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "3")) + "35.399999999999999") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "4")) + "72") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "5")) + "60") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "6")) + "42") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "7")) + "39") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "2") (Col "8")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "3") (Col "0")) + "C") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "1")) + "0.3347222222222222") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "3") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "3")) + "35") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "4")) + "100") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "5")) + "90") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "6")) + "57") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "7")) + "46") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "3") (Col "8")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "4") (Col "0")) + "D") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "1")) + "0.33680555555555558") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "4") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "3")) + "35") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "4")) + "130") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "5")) + "116") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "6")) + "69") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "7")) + "52") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "4") (Col "8")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "5") (Col "0")) + "E") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "1")) + "0.33888888888888891") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "5") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "3")) + "35") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "4")) + "145") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "5")) + "121") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "6")) + "73") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "7")) + "54") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "5") (Col "8")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "6") (Col "0")) + "F") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "1")) + "0.34097222222222223") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "6") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "3")) + "35") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "4")) + "150") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "5")) + "125") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "6")) + "78") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "7")) + "56") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "6") (Col "8")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "7") (Col "0")) + "G") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "1")) + "0.34305555555555556") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "7") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "3")) + "35") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "4")) + "150") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "5")) + "128") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "6")) + "82") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "7")) + "60") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "7") (Col "8")) + "69") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "8") (Col "0")) + "H") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "1")) + "0.34583333333333333") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "8") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "3")) + "36") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "4")) + "158") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "5")) + "129") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "6")) + "86") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "7")) + "62") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "8") (Col "8")) + "70") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "9") (Col "0")) + "I") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "1")) + "0.34791666666666665") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "9") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "3")) + "36") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "4")) + "156") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "5")) + "128") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "6")) + "87") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "7")) + "65") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "9") (Col "8")) + "72") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "10") (Col "0")) + "J") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "1")) + "0.35138888888888886") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "10") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "3")) + "37") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "4")) + "152") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "5")) + "126") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "6")) + "89") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "7")) + "67") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "10") (Col "8")) + "75") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "11") (Col "0")) + "K") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "1")) + "0.36666666666666664") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "11") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "3")) + "37") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "4")) + "134") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "5")) + "117") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "6")) + "94") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "7")) + "77") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "11") (Col "8")) + "107") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "12") (Col "0")) + "L") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "1")) + "0.37916666666666665") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "12") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "3")) + "38") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "4")) + "117") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "5")) + "108") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "6")) + "96") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "7")) + "82") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "12") (Col "8")) + "106") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "13") (Col "0")) + "M") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "1")) + "0.39583333333333331") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "13") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "3")) + "39") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "4")) + "100") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "5")) + "100") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "6")) + "93") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "7")) + "82") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "13") (Col "8")) + "106") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "14") (Col "0")) + "N") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "1")) + "0.42222222222222222") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "14") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "3")) + "40") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "4")) + "91") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "5")) + "90") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "6")) + "88") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "7")) + "81") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "14") (Col "8")) + "100") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "15") (Col "0")) + "O") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "1")) + "0.45208333333333334") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "15") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "3")) + "41") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "4")) + "79") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "5")) + "78") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "6")) + "77") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "7")) + "72") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "15") (Col "8")) + "79") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "16") (Col "0")) + "P") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "1")) + "0.49166666666666664") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "16") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "3")) + "41") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "4")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "5")) + "63") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "6")) + "64") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "7")) + "62") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "16") (Col "8")) + "68") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "17") (Col "0")) + "Q") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "1")) + "0.5708333333333333") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (Row "17") (ExprID "1") (Col "2"))) + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "3")) + "41.5") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "4")) + "51") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "5")) + "51") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "6")) + "51") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "7")) + "51") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "17") (Col "8")) + "51")) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0")))) + (http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:Name "Second-sheet") + (http://www.gnumeric.org/v10.dtd:MaxCol "4") + (http://www.gnumeric.org/v10.dtd:MaxRow "20") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"Second-sheet\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles + (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") + (startCol "0") + (endRow "65279") + (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "65280") + (startCol "0") + (endRow "65534") + (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans"))) + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "65535") + (startCol "0") + (endRow "65535") + (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "64.01") (No "0"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "1") (Count "4")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "0") (Count "20")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "4") (CursorCol "4")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "4") (startCol "4") (endRow "4") (endCol "4")))) + (http://www.gnumeric.org/v10.dtd:Cells + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "1")) + "A1") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "0") (Col "2")) + "2") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "0") (Col "3")) + "A1") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "40") (Row "0") (Col "4")) + "3") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "1") (Col "0")) + "V1") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "1") (Col "1")) + "X") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "2") (Col "0")) + "V2") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "2") (Col "2")) + "X") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "3") (Col "0")) + "V3") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "3") (Col "3")) + "X") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "4") (Col "0")) + "V4") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "4") (Col "4")) + "X") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "5") (Col "0")) + "V5") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "5") (Col "3")) + "Y") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "6") (Col "0")) + "V6") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "6") (Col "2")) + "Y") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "7") (Col "0")) + "V7") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "7") (Col "1")) + "Y") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "8") (Col "0")) + "V8") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "8") (Col "1")) + "Z") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "9") (Col "0")) + "V8") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "9") (Col "2")) + "Z") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "10") (Col "0")) + "V10") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "10") (Col "3")) + "Z") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "11") (Col "4")) + "Z") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "12") (Col "0")) + "V11") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "12") (Col "3")) + "E") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "13") (Col "0")) + "V12") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "13") (Col "2")) + "E") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "14") (Col "0")) + "V13") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "14") (Col "1")) + "E") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "15") (Col "0")) + "V14") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "15") (Col "1")) + "B") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "16") (Col "0")) + "V15") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "16") (Col "2")) + "B") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "17") (Col "0")) + "V16") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "17") (Col "3")) + "B") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "18") (Col "4")) + "B") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "19") (Col "0")) + "V17") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "19") (Col "1")) + "-") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "19") (Col "2")) + "+") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "19") (Col "3")) + "=") + (http://www.gnumeric.org/v10.dtd:Cell + (@ (ValueType "60") (Row "19") (Col "4")) + "~")) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0")))) + (http://www.gnumeric.org/v10.dtd:Sheet + (@ (Visibility "GNM_SHEET_VISIBILITY_VISIBLE") + (OutlineSymbolsRight "1") + (OutlineSymbolsBelow "1") + (HideZero "0") + (HideRowHeader "0") + (HideGrid "0") + (HideColHeader "0") + (GridColor "0:0:0") + (DisplayOutlines "1") + (DisplayFormulas "0")) + (http://www.gnumeric.org/v10.dtd:Name "Sheet3") + (http://www.gnumeric.org/v10.dtd:MaxCol "0") + (http://www.gnumeric.org/v10.dtd:MaxRow "0") + (http://www.gnumeric.org/v10.dtd:Zoom "1") + (http://www.gnumeric.org/v10.dtd:Names + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Print_Area") + (http://www.gnumeric.org/v10.dtd:value "#REF!") + (http://www.gnumeric.org/v10.dtd:position "A1")) + (http://www.gnumeric.org/v10.dtd:Name + (http://www.gnumeric.org/v10.dtd:name "Sheet_Title") + (http://www.gnumeric.org/v10.dtd:value "\"Sheet3\"") + (http://www.gnumeric.org/v10.dtd:position "A1"))) + (http://www.gnumeric.org/v10.dtd:PrintInformation + (http://www.gnumeric.org/v10.dtd:Margins + (http://www.gnumeric.org/v10.dtd:top + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:bottom + (@ (PrefUnit "mm") (Points "93.26"))) + (http://www.gnumeric.org/v10.dtd:left + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:right + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:header + (@ (PrefUnit "mm") (Points "72"))) + (http://www.gnumeric.org/v10.dtd:footer + (@ (PrefUnit "mm") (Points "72")))) + (http://www.gnumeric.org/v10.dtd:Scale + (@ (type "percentage") (percentage "100"))) + (http://www.gnumeric.org/v10.dtd:vcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:hcenter (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:grid (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:even_if_only_styles + (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:monochrome (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:draft (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:titles (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:do_not_print (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:print_range (@ (value "0"))) + (http://www.gnumeric.org/v10.dtd:order "d_then_r") + (http://www.gnumeric.org/v10.dtd:orientation "portrait") + (http://www.gnumeric.org/v10.dtd:Header + (@ (Right "") (Middle "&[tab]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:Footer + (@ (Right "") (Middle "&[page]") (Left ""))) + (http://www.gnumeric.org/v10.dtd:paper "na_letter") + (http://www.gnumeric.org/v10.dtd:comments "in_place") + (http://www.gnumeric.org/v10.dtd:errors "as_displayed")) + (http://www.gnumeric.org/v10.dtd:Styles + (http://www.gnumeric.org/v10.dtd:StyleRegion + (@ (startRow "0") + (startCol "0") + (endRow "65535") + (endCol "255")) + (http://www.gnumeric.org/v10.dtd:Style + (@ (WrapText "0") + (VAlign "2") + (ShrinkToFit "0") + (Shade "0") + (Rotation "0") + (PatternColor "0:0:0") + (Locked "1") + (Indent "0") + (Hidden "0") + (HAlign "1") + (Format "General") + (Fore "0:0:0") + (Back "FFFF:FFFF:FFFF")) + (http://www.gnumeric.org/v10.dtd:Font + (@ (Unit "10") + (Underline "0") + (StrikeThrough "0") + (Script "0") + (Italic "0") + (Bold "0")) + "Sans")))) + (http://www.gnumeric.org/v10.dtd:Cols + (@ (DefaultSizePts "48")) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "64.01") (No "0")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.82") (No "0")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "0") (CursorCol "0")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "0") (startCol "0") (endRow "0") (endCol "0")))) + (http://www.gnumeric.org/v10.dtd:Cells) + (http://www.gnumeric.org/v10.dtd:SheetLayout (@ (TopLeft "A1"))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0"))))) + (http://www.gnumeric.org/v10.dtd:UIData (@ (SelectedTab "0"))))) Index: txtdb/txtdb.scm ================================================================== --- txtdb/txtdb.scm +++ txtdb/txtdb.scm @@ -1,19 +1,611 @@ -;; Copyright 2006-2012, Matthew Welland. +;; Copyright 2006-2013, 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. (use ssax) +(use sxml-serializer) +(use sxml-modifications) +(use regex) +(use srfi-69) +(use regex-case) +(use posix) +(use json) +(use csv) + +(include "../megatest-fossil-hash.scm") ;; Read a non-compressed gnumeric file -(define (txtdb:read-gnumeric-xml fname) +(define (refdb:read-gnumeric-xml fname) (with-input-from-file fname (lambda () (ssax:xml->sxml (current-input-port) '())))) + +(define (find-section dat section #!key (depth 0)) + (let loop ((hed (car dat)) + (tal (cdr dat))) + (if (list? hed) + (let ((res (find-section hed section depth: (+ depth 1)))) + (if res + res + (if (null? tal) + #f + (loop (car tal)(cdr tal))))) + (if (eq? hed section) + tal + (if (null? tal) + #f + (loop (car tal)(cdr tal))))))) + +(define (remove-section dat section) + (if (null? dat) + '() + (let loop ((hed (car dat)) + (tal (cdr dat)) + (res '())) + (let ((newres (if (and (list? hed) + (not (null? hed)) + (equal? (car hed) section)) + res + (cons hed res)))) + (if (null? tal) + (reverse newres) + (loop (car tal)(cdr tal) newres)))))) + +(define (list-sections dat) + (filter (lambda (x)(and x)) + (map (lambda (section) + (if (and (list? section) + (not (null? section))) + (car section) + #f)) + dat))) + +(define (string->safe-filename str) + (string-substitute (regexp " ") "_" str #t)) + +(define (sheet->refdb dat targdir) + (let* ((comment-rx (regexp "^#CMNT\\d+\\s*")) + (blank-rx (regexp "^#BLNK\\d+\\s*")) + (sheet-name (car (find-section dat 'http://www.gnumeric.org/v10.dtd:Name))) + ;; (safe-name (string->safe-filename sheet-name)) + (cells (find-section dat 'http://www.gnumeric.org/v10.dtd:Cells)) + (remaining (remove-section (remove-section dat 'http://www.gnumeric.org/v10.dtd:Name) + 'http://www.gnumeric.org/v10.dtd:Cells)) + (rownums (make-hash-table)) ;; num -> name + (colnums (make-hash-table)) ;; num -> name + (cols (make-hash-table)) ;; name -> ( (name val) ... ) + (col0title "")) + (for-each (lambda (cell) + (let ((rownum (string->number (car (find-section cell 'Row)))) + (colnum (string->number (car (find-section cell 'Col)))) + (valtype (let ((res (find-section cell 'ValueType))) + (if res (car res) #f))) + (value (let ((res (cdr (filter (lambda (x)(not (list? x))) cell)))) + (if (null? res) "" (car res))))) + ;; If colnum is 0 Then this is a row name, if rownum is 0 then this is a col name + (cond + ((and (not (eq? 0 rownum)) + (eq? 0 colnum)) ;; a blank in column zero is handled with the special name "row-N" + (hash-table-set! rownums rownum (if (equal? value "") + (conc "row-" rownum) + value))) + ((and (not (eq? 0 colnum)) + (eq? 0 rownum)) + (hash-table-set! colnums colnum (if (equal? value "") + (conc "col-" colnum) + value))) + ((and (eq? 0 rownum) + (eq? 0 colnum)) + (set! col0title value)) + (else + (let ((colname (hash-table-ref/default colnums colnum (conc "col-" colnum))) + (rowname (hash-table-ref/default rownums rownum (conc "row-" rownum)))) + (hash-table-set! cols colname (cons (list rowname value) + (hash-table-ref/default cols colname '())))))))) + cells) + (let ((ref-colnums (map (lambda (c) + (list (cdr c)(car c))) + (hash-table->alist colnums)))) + (with-output-to-file (conc targdir "/" sheet-name ".dat") + (lambda () + (print "[" col0title "]") + (for-each (lambda (colname) + (print "[" colname "]") + (for-each (lambda (row) + (let ((key (car row)) + (val (cadr row))) + (if (string-search comment-rx key) + (print val) + (if (string-search blank-rx key) + (print) + (print key " " val))))) + (reverse (hash-table-ref cols colname))) + ;; (print) + ) + (sort (hash-table-keys cols)(lambda (a b) + (let ((colnum-a (assoc a ref-colnums)) + (colnum-b (assoc b ref-colnums))) + (if (and colnum-a colnum-b) + (< (cadr colnum-a)(cadr colnum-b)) + (if (and (string? a) + (string? b)) + (string< a b)))))))))) + (with-output-to-file (conc targdir "/sxml/" sheet-name ".sxml") + (lambda () + (pp remaining))) + sheet-name)) + +(define (sxml->file dat fname) + (with-output-to-file fname + (lambda () + ;; (print (sxml-serializer#serialize-sxml dat)) + (pp dat)))) + +(define (file->sxml fname) + (let ((res (read-file fname read))) + (if (null? res) + (begin + (print "ERROR: file " fname " is malformed for read") + #f) + (car res)))) + +(define (replace-sheet-name-index indat sheets) + (let* ((rem-dat (remove-section indat 'http://www.gnumeric.org/v10.dtd:SheetNameIndex)) + (one-sht (find-section rem-dat 'http://www.gnumeric.org/v10.dtd:SheetName)) ;; for the future if I ever decide to do this "right" + (mk-entry (lambda (sheet-name) + (append '(http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256"))) + (list sheet-name)))) + (new-indx-values (map mk-entry sheets))) + (append rem-dat (list (cons 'http://www.gnumeric.org/v10.dtd:SheetNameIndex + new-indx-values))))) + + +;; Write an sxml gnumeric workbook to a refdb directory structure. +;; +(define (extract-refdb dat targdir) + (create-directory (conc targdir "/sxml") #t) + (let* ((wrkbk (find-section dat 'http://www.gnumeric.org/v10.dtd:Workbook)) + (wrk-rem (remove-section dat 'http://www.gnumeric.org/v10.dtd:Workbook)) + (sheets (find-section wrkbk 'http://www.gnumeric.org/v10.dtd:Sheets)) + (sht-rem (remove-section wrkbk 'http://www.gnumeric.org/v10.dtd:Sheets)) + (sheet-names (map (lambda (sheet) + (sheet->refdb sheet targdir)) + sheets))) + (sxml->file wrk-rem (conc targdir "/sxml/_workbook.sxml")) + (sxml->file sht-rem (conc targdir "/sxml/_sheets.sxml")) + (with-output-to-file (conc targdir "/sheet-names.cfg") + (lambda () + (map print sheet-names))))) + +(define (read-gnumeric-file fname) + (if (not (string-match (regexp ".*.gnumeric$") fname)) + (begin + (print "ERROR: Attempt to import gnumeric file with extention other than .gnumeric") + (exit)) + (let ((tmpf (create-temporary-file (pathname-strip-directory fname)))) + (system (conc " gunzip > " tmpf " < " fname)) + (let ((res (refdb:read-gnumeric-xml tmpf))) + (delete-file tmpf) + res)))) + +(define (import-gnumeric-file fname targdir) + (extract-refdb (read-gnumeric-file fname) targdir)) + +;; Write a gnumeric compressed xml spreadsheet from a refdb directory structure. +;; +(define (refdb-export dbdir fname) + (let* ((sxml-dat (refdb->sxml dbdir)) + (tmpf (create-temporary-file (pathname-strip-directory fname))) + (tmpgzf (conc tmpf ".gz"))) + (with-output-to-file tmpf + (lambda () + (print (sxml-serializer#serialize-sxml sxml-dat ns-prefixes: (list (cons 'gnm "http://www.gnumeric.org/v10.dtd")))))) + (system (conc "gzip " tmpf)) + (file-copy tmpgzf fname #t) + (delete-file tmpgzf))) + +(define (hash-table-reverse-lookup ht val) + (hash-table-fold ht (lambda (k v res)(if (equal? v val) k res)) #f)) + +(define (read-dat fname) + (let ((section-rx (regexp "^\\[(.*)\\]\\s*$")) + (comment-rx (regexp "^#.*")) ;; This means a cell name cannot start with # + (cell-rx (regexp "^(\\S+) (.*)$")) ;; One space only for the cellname content separator + (blank-rx (regexp "^\\s*$")) + (continue-rx (regexp ".*\\\\$")) + (var-no-val-rx (regexp "^(\\S+)\\s*$")) + (inp (open-input-file fname)) + (cmnt-indx (make-hash-table)) + (blnk-indx (make-hash-table)) + (first-section #f)) ;; used for zeroth title + (let loop ((inl (read-line inp)) + (section ".............") + (res '())) + (if (eof-object? inl) + (begin + (close-input-port inp) + (cons (list first-section first-section first-section) + (reverse res))) + (regex-case + inl + (continue-rx _ (loop (conc inl (read-line inp)) section res)) + (comment-rx _ (let ((curr-indx (+ 1 (hash-table-ref/default cmnt-indx section 0)))) + (hash-table-set! cmnt-indx section curr-indx) + (loop (read-line inp) + section + (cons (list (conc "#CMNT" curr-indx) section inl) res)))) + (blank-rx _ (let ((curr-indx (+ 1 (hash-table-ref/default blnk-indx section 0)))) + (hash-table-set! blnk-indx section curr-indx) + (loop (read-line inp) + section + (cons (list (conc "#BLNK" curr-indx) section " ") res)))) + (section-rx (x sname) (begin + (if (not first-section) + (set! first-section sname)) + (loop (read-line inp) + sname + res))) + (cell-rx (x k v) (loop (read-line inp) + section + (cons (list k section v) res))) + (var-no-val-rx (x k) (loop (read-line inp) + section + (cons (list k section "") res))) + (else (begin + (print "ERROR: Unrecognised line in input file " fname ", ignoring it") + (loop (read-line inp) section res)))))))) + +(define (get-value-type val expressions) + (cond + ((string->number val) '(ValueType "40")) + ((equal? val "") '(ValueType "60")) + ((equal? (substring val 0 1) "=") + (let ((exid (hash-table-ref/default expressions val #f))) + (if exid + (list 'ExprID exid) + (let* ((values (hash-table-keys expressions)) ;; note, values are the id numbers + (new-max (+ 1 (if (null? values) 0 (apply max values))))) + (hash-table-set! expressions val new-max) + (list 'ExprID new-max))))) + (else '(ValueType "60")))) + +(define (dat->cells dat) + (let* ((indx (common:sparse-list-generate-index (cdr dat))) + (row-indx (car indx)) + (col-indx (cadr indx)) + (rowdat (map (lambda (row)(list (car row) " " (car row))) row-indx)) + (coldat (map (lambda (col)(list " " (car col) (car col))) col-indx)) + (exprs (make-hash-table))) + (list (cons 'http://www.gnumeric.org/v10.dtd:Cells + (map (lambda (item) + (let* ((row-name (car item)) + (col-name (cadr item)) + (row-num (let ((i (assoc row-name row-indx))) + (if i (cadr i) 0))) ;; 0 for the title row/col + (col-num (let ((i (assoc col-name col-indx))) + (if i (cadr i) 0))) + (value (caddr item)) + (val-type (get-value-type value exprs))) + (list 'http://www.gnumeric.org/v10.dtd:Cell + (list '@ val-type (list 'Row (conc row-num)) (list 'Col (conc col-num))) + value))) + (append rowdat coldat dat)))))) + +(define (refdb->sxml dbdir) + (let* ((sht-names (read-file (conc dbdir "/sheet-names.cfg") read-line)) + (wrk-rem (file->sxml (conc dbdir "/sxml/_workbook.sxml"))) + (sht-rem (file->sxml (conc dbdir "/sxml/_sheets.sxml"))) + (sheets (fold (lambda (sheetname res) + (let* ((sheetdat (read-dat (conc dbdir "/" sheetname ".dat"))) + (cells (dat->cells sheetdat)) + (sht-meta (file->sxml (conc dbdir "/sxml/" sheetname ".sxml")))) + (cons (cons (car sht-meta) + (append (cons (list 'http://www.gnumeric.org/v10.dtd:Name sheetname) + (cdr sht-meta)) + cells)) + res))) + '() + (reverse sht-names)))) + (append wrk-rem (list (append + (cons 'http://www.gnumeric.org/v10.dtd:Workbook + sht-rem) + (list (cons 'http://www.gnumeric.org/v10.dtd:Sheets sheets))))))) + +;; (define ( + +;; +;; optional apply proc to rownum colnum value +;; +;; NB// If a change is made to this routine please look also at applying +;; it to the code in Megatest (http://www.kiatoa.com/fossils/megatest) +;; in the file common.scm +;; +(define (common:sparse-list-generate-index data #!key (proc #f)) + (if (null? data) + (list '() '()) + (let loop ((hed (car data)) + (tal (cdr data)) + (rownames '()) + (colnames '()) + (rownum 0) + (colnum 0)) + (let* ((rowkey (car hed)) + (colkey (cadr hed)) + (value (caddr hed)) + (existing-rowdat (assoc rowkey rownames)) + (existing-coldat (assoc colkey colnames)) + (curr-rownum (if existing-rowdat rownum (+ rownum 1))) + (curr-colnum (if existing-coldat colnum (+ colnum 1))) + (new-rownames (if existing-rowdat rownames (cons (list rowkey curr-rownum) rownames))) + (new-colnames (if existing-coldat colnames (cons (list colkey curr-colnum) colnames)))) + ;; (debug:print-info 0 "Processing record: " hed ) + (if proc (proc curr-rownum curr-colnum rowkey colkey value)) + (if (null? tal) + (list new-rownames new-colnames) + (loop (car tal) + (cdr tal) + new-rownames + new-colnames + (if (> curr-rownum rownum) curr-rownum rownum) + (if (> curr-colnum colnum) curr-colnum colnum) + )))))) +(define help + (conc "Usage: refdb action params ... + +Note: refdbdir is a path to the directory containg sheet-names.cfg + + import filename.gnumeric refdbdir : Import a gnumeric file into a txt db directory + export refdbdir filename.gnumeric : Export a refdb to a gnumeric file + edit refdbdir : Edit a refdbdir using gnumeric. + ls refdbdir : List the keys for specified level + lookup refdbdir sheetname row col : Look up a value in the text db + getrownames refdb sheetname : Get a list of row titles + getcolnames refdb sheetname : Get a list of column titles + +To export to other formats; first export to gnumeric then use ssconvert. + +e.g. + +refdb export mydata mydata.gnumeric +ssconvert -T Gnumeric_html:html40 mydata.gnumeric mydata.html + +Part of the Megatest tool suite. Learn more at http://www.kiatoa.com/fossils/megatest + +Version: " megatest-fossil-hash)) + +(define (list-sheets path) + ;; (cond + ;; ((and path (not sheet)(not row)(not col)) + (if (file-exists? path) + (read-file (conc path "/sheet-names.cfg") read-line) + '())) +;; ((and path sheet (not row)(not col)) + +(define (lookup path sheet row col) + (let ((fname (conc path "/" sheet ".dat"))) + (if (file-exists? fname) + (let ((dat (read-dat fname))) + (if (null? dat) + #f + (let loop ((hed (car dat)) + (tal (cdr dat))) + (if (and (equal? row (car hed)) + (equal? col (cadr hed))) + (caddr hed) + (if (null? tal) + #f + (loop (car tal)(cdr tal))))))) + #f))) + +;; call with proc = car to get row names +;; call with proc = cadr to get col names +(define (get-rowcol-names path sheet proc) + (let ((fname (conc path "/" sheet ".dat")) + (cmnt-rx (regexp "^#CMNT\\d+\\s*")) + (blnk-rx (regexp "^#BLNK\\d+\\s*"))) + (if (file-exists? fname) + (let ((dat (read-dat fname))) + (if (null? dat) + '() + (let loop ((hed (car dat)) + (tal (cdr dat)) + (res '())) + (let* ((row-name (proc hed)) + (newres (if (and (not (member row-name res)) + (not (string-search cmnt-rx row-name)) + (not (string-search blnk-rx row-name))) + (cons row-name res) + res))) + (if (null? tal) + (reverse newres) + (loop (car tal)(cdr tal) newres)))))) + '()))) + +;; (define (get-col-names path sheet) +;; (let ((fname (conc path "/" sheet ".dat"))) +;; (if (file-exists? fname) +;; (let ((dat (read-dat fname))) +;; (if (null? dat) +;; #f +;; (map cadr dat)))))) + +(define (edit-refdb path) + ;; TEMPORARY, REMOVE IN 2014 + (if (not (file-exists? path)) ;; Create new + (begin + (print "\nINFO: Creating new txtdb at " path "\n") + (create-new-db path))) + (if (not (file-exists? (conc path "/sxml/_sheets.sxml"))) + (begin + (print "ERROR: You appear to have the old file structure for txtdb. Please do the following and try again.") + (print) + (print "mv " path "/sxml/sheets.sxml " path "/sxml/_sheets.sxml") + (print "mv " path "/sxml/workbook.sxml " path "/sxml/_workbook.sxml") + (print) + (print "Don't forget to remove the old files from your revision control system and add the new.") + (exit))) + (let* ((dbname (pathname-strip-directory path)) + (tmpf (conc (create-temporary-file dbname) ".gnumeric"))) + (if (file-exists? (conc path "/sheet-names.cfg")) + (refdb-export path tmpf)) + (let ((pid (process-run "gnumeric" (list tmpf)))) + (process-wait pid) + (import-gnumeric-file tmpf path)))) + +;;====================================================================== +;; This routine dispaches or executes most of the commands for refdb +;;====================================================================== +;; +(define (process-action action-str . param) + (let ((num-params (length param)) + (action (string->symbol action-str))) + (cond + ((eq? num-params 1) + (case action + ((edit) + (edit-refdb (car param))) + ((ls) + (map print (list-sheets (car param)))))) + ((eq? num-params 2) + (let ((param1 (car param)) + (param2 (cadr param))) + (case action + ((getrownames) (print (string-intersperse (get-rowcol-names param1 param2 car) " "))) + ((getcolnames) (print (string-intersperse (get-rowcol-names param1 param2 cadr) " "))) + ((import) (import-gnumeric-file param1 param2)) ;; fname targname + ((export) (refdb-export param1 param2)) + (else (print "Unrecognised command " action)(print help))))) + ((eq? num-params 4) + (case action + ((lookup) ;; path section row col + (let ((res (lookup (car param)(cadr param)(caddr param)(cadddr param)))) + (if res + (print res) + (begin + (print "") + (exit 1)))))))))) + +(define (main) + (let* ((args (argv)) + (prog (car args)) + (rema (cdr args))) + (cond + ((null? rema)(print help)) + ((eq? (length rema) 1) + (case (string->symbol (car rema)) + ((mtedit) ;; Edit a Megatest area + (megatest->refdb)))) + ((>= (length rema) 2) + (apply process-action (car rema)(cdr rema))) + (else (print help))))) + +;;====================================================================== +;; C R E A T E N E W D B S +;;====================================================================== + +(include "metadat.scm") + +;; Creates a new db at path with one sheet +(define (create-new-db path) + (extract-refdb minimal-sxml path)) + +;;====================================================================== +;; M E G A T E S T S U P P O R T +;;====================================================================== + +;; Construct a temporary refdb area from the files in a Megatest area +;; +;; .refdb +;; megatest.dat (from megatest.config) +;; runconfigs.dat (from runconfigs.config) +;; tests_test1.dat (from tests/test1/testconfig) +;; etc. +;; + +(define (make-sheet-meta-if-needed fname) + (if (not (file-exists? fname)) + (sxml->file sheet-meta fname))) + +(define (megatest->refdb) + (if (not (file-exists? "megatest.config")) ;; must be at top of Megatest area + (begin + (print "ERROR: Must be at top of Megatest area to edit") + (exit))) + (create-directory ".refdb/sxml" #t) + (if (not (file-exists? ".refdb/sxml/_workbook.sxml")) + (sxml->file workbook-meta ".refdb/sxml/_workbook.sxml")) + (file-copy "megatest.config" ".refdb/megatest.dat" #t) + (make-sheet-meta-if-needed ".refdb/sxml/megatest.sxml") + (file-copy "runconfigs.config" ".refdb/runconfigs.dat" #t) + (make-sheet-meta-if-needed ".refdb/sxml/runconfigs.sxml") + (let ((testnames '())) + (for-each (lambda (tdir) + (let* ((testname (pathname-strip-directory tdir)) + (tconfig (conc tdir "/testconfig")) + (metafile (conc ".refdb/sxml/" testname ".sxml"))) + (if (file-exists? tconfig) + (begin + (set! testnames (append testnames (list testname))) + (file-copy tconfig (conc ".refdb/" testname ".dat") #t) + (make-sheet-meta-if-needed metafile))))) + (glob "tests/*")) + (let ((sheet-names (append (list "megatest" "runconfigs") testnames))) + (if (not (file-exists? ".refdb/sxml/_sheets.sxml")) + (sxml->file (replace-sheet-name-index sheets-meta sheet-names) ".refdb/sxml/_sheets.sxml")) + (with-output-to-file ".refdb/sheet-names.cfg" + (lambda () + (map print sheet-names)))))) + +(let ((dotfile (conc (get-environment-variable "HOME") "/.txtdbrc"))) + (if (file-exists? dotfile) + (load dotfile))) + +(let ((debugcontrolf (conc (get-environment-variable "HOME") "/.refdbrc"))) + (if (file-exists? debugcontrolf) + (load debugcontrolf))) + +(main) + +#| + (define x (refdb:read-gnumeric-xml "testdata-stripped.xml")) + + + +;; Write out sxml +(with-output-to-file "testdata.sxml" (lambda()(pp x))) + ;; (serialize-sxml a output: "new.xml") +(with-output-to-file "testdata-stripped.xml" (lambda ()(print (sxml-serializer#serialize-sxml y)))) + +;; Read in sxml file +(with-input-from-file "testdata.sxml" (lambda ()(set! y (read)))) + +(find-section x 'http://www.gnumeric.org/v10.dtd:Workbook) + +(define sheets (find-section x 'http://www.gnumeric.org/v10.dtd:Sheets)) + +(define sheet1 (car sheets)) +(define cells-sheet1 (find-section sheet1 'http://www.gnumeric.org/v10.dtd:Cells)) +(map (lambda (c)(find-section c 'Row)) cells-sheet1) + +(for-each (lambda (cell) + (let* ((len (length cell)) + (row (car (find-section cell 'Row))) + (col (car (find-section cell 'Col))) + (val (let ((res (cdr (filter (lambda (x)(not (list? x))) cell)))) + (if (null? res) "" (car res))))) + (print "Row=" row " col=" col " val=" val))) + cells-sheet1) + + +(map (lambda (c)(filter (lambda (x)(not (list? x))) c)) cells-sheet1) +|# ADDED utils/Makefile.installall Index: utils/Makefile.installall ================================================================== --- /dev/null +++ utils/Makefile.installall @@ -0,0 +1,184 @@ + +# Copyright 2013, 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. + +help : + @echo You may need to do the following first: + @echo sudo apt-get install libreadline-dev + @echo sudo apt-get install libwebkitgtk-dev + @echo sudo apt-get install libmotif3 -OR- set KTYPE=26g4 + @echo KTYPE can be 26, 26g4, or 32 + @echo KTYPE=$KTYPE + @echo You are using PREFIX=$PREFIX + @echo You are using proxy="$(proxy)" + @echo If needed set proxy to host.dom:port + @echo + @echo "Set additional_libpath to help find gtk or other libraries, don't forget a leading :" + @echo ADDITIONAL_LIBPATH=$(ADDITIONAL_LIBPATH) + @echo + @echo To use previous IUP libraries set USEOLDIUP to yes + @echo USEOLDIUP=$(USEOLDIUP) + @echo + @echo To make all do: make all + +# Put the installation here +ifeq ($(PREFIX),) +PREFIX=$(PWD)/target +endif + +# Set this on the command line of your make call if needed: make PROXY=host.com:1234 +PROXY= + +# Select IUP library type +KTYPE=26g4 + +# Select version of chicken, sqlite3 etc +CHICKEN_VERSION=4.8.0 +SQLITE3_VERSION=3071401 + +# Eggs to install (straightforward ones) +EGGS=matchable readline apropos base64 regex-literals format regex-case test coops trace csv dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars + +# +# Derived variables +# + +ifeq ($(PROXY),) +PROX= +else +http_proxy=http://$(PROXY) +PROX="-proxy $(PROXY)" +endif + +BUILDHOME=$(PWD) +PATH:=$(PREFIX)/bin:$(PATH) +LIBPATH=$(PREFIX)/lib$(ADDITIONAL_LIBPATH) +LD_LIBRARY_PATH=$(LIBPATH) +CHICKEN_INSTALL=$(PREFIX)/bin/chicken-install +CHICKEN_EGG_DIR=$(PREFIX)/lib/chicken/6 + +VPATH=$(CHICKEN_EGG_DIR):$(PWD)/eggflags + +vpath %.so $(CHICKEN_EGG_DIR) +vpath %.flag eggflags + +EGGSOFILES=$(addprefix $(CHICKEN_EGG_DIR)/,$(addsuffix .so,$(EGGS))) +EGGFLAGS=$(addprefix eggflags/,$(addsuffix .flag,$(EGGS))) + +# Stuff needed for IUP +ISARCHX86_64=$(shell uname -a | grep x86_64) +ifeq ($(ISARCHX86_64),) +ARCHSIZE= +else +ARCHSIZE=64_ +endif + +IUPFILES=cd-5.5.1_Linux$(KTYPE)_$(ARCHSIZE)lib.tar.gz im-3.8_Linux$(KTYPE)_$(ARCHSIZE)lib.tar.gz iup-3.6_Linux$(KTYPE)_$(ARCHSIZE)lib.tar.gz +CSCLIBS=$(shell echo $(LD_LIBRARY_PATH) | sed 's/:/ -L/g') +CSC_OPTIONS=-I$(PREFIX)/include -L$(CSCLIBS) + +all : chkn eggs iup + +chkn : $(CHICKEN_INSTALL) + +eggs : $(EGGSOFILES) + +sqlite3 : $(CHICKEN_EGG_DIR)/sqlite3.so + +iup : $(PREFIX)/lib/libavcall.a $(CHICKEN_EGG_DIR)/iup.so $(CHICKEN_EGG_DIR)/canvas-draw.so + +# Silly rule to make installing eggs more makeish, I don't understand why I need the basename +$(CHICKEN_EGG_DIR)/%.so : %.flag + $(CHICKEN_INSTALL) $(PROX) $(shell basename $*) + +$(EGGFLAGS) : # $(CHICKEN_INSTALL) + mkdir -p eggflags + touch $(EGGFLAGS) + +# some setup stuff +# +setup-chicken4x.sh : $(EGGFLAGS) + (echo "export PATH=$(PATH)" > setup-chicken4x.sh) + (echo "export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH)" >> setup-chicken4x.sh) + mkdir -p $(PREFIX) + +# Download chicken source +chicken-$(CHICKEN_VERSION).tar.gz : + wget http://code.call-cc.org/releases/$(CHICKEN_VERSION)/chicken-$(CHICKEN_VERSION).tar.gz + +# NB// Must touch csi.scm since tar puts original date on it and deps are wrong then +chicken-$(CHICKEN_VERSION)/csi.scm : chicken-$(CHICKEN_VERSION).tar.gz + tar xfvz chicken-$(CHICKEN_VERSION).tar.gz + touch -c chicken-$(CHICKEN_VERSION)/csi.scm + +$(CHICKEN_INSTALL) : chicken-$(CHICKEN_VERSION)/csi.scm setup-chicken4x.sh + cd chicken-$(CHICKEN_VERSION);make PLATFORM=linux PREFIX=$(PREFIX) + cd chicken-$(CHICKEN_VERSION);make PLATFORM=linux PREFIX=$(PREFIX) install + +sqlite-autoconf-$(SQLITE3_VERSION).tar.gz : + wget http://www.sqlite.org/sqlite-autoconf-$(SQLITE3_VERSION).tar.gz + +sqlite-autoconf-$(SQLITE3_VERSION) : sqlite-autoconf-$(SQLITE3_VERSION).tar.gz + tar xfz sqlite-autoconf-$(SQLITE3_VERSION).tar.gz + +$(PREFIX)/bin/sqlite3 : sqlite-autoconf-$(SQLITE3_VERSION) + (cd sqlite-autoconf-$(SQLITE3_VERSION);./configure --prefix=$(PREFIX);make;make install) + +$(CHICKEN_EGG_DIR)/sqlite3.so : $(PREFIX)/bin/sqlite3 + CSC_OPTIONS="-I$(PREFIX)/include -L$(PREFIX)/lib" $(CHICKEN_INSTALL) $(PROX) sqlite3 + + +# Get and install my various utilities that haven't been eggified yet. +opensrc/margs/margs.scm opensrc/dbi/dbi.scm opensrc/qtree/qtree.scm : $(CHICKEN_INSTALL) $(CHICKEN_EGG_DIR)/sqlite3.so + mkdir -p opensrc + cd opensrc;if [ ! -e opensrc.fossil ]; then fossil clone http://www.kiatoa.com/fossils/opensrc opensrc.fossil; fi + cd opensrc;if [ -e dbi/dbi.scm ]; then fossil update; else fossil open opensrc.fossil; fi + +$(CHICKEN_EGG_DIR)/dbi.so : opensrc/dbi/dbi.scm + cd opensrc/dbi;chicken-install + +$(CHICKEN_EGG_DIR)/margs.so : opensrc/margs/margs.scm + cd opensrc/margs;chicken-install + +$(CHICKEN_EGG_DIR)/qtree.so : opensrc/qtree/qtree.scm + cd opensrc/qtree;chicken-install + +# $(CHICKEN_EGG_DIR)/dbi.so # Don't include as requires postgres +mattseggs : $(CHICKEN_EGG_DIR)/margs.so $(CHICKEN_EGG_DIR)/qtree.so + +# +# IUP +# + +ffcall.tar.gz : + wget http://www.kiatoa.com/matt/iup/ffcall.tar.gz + +ffcall/README : ffcall.tar.gz + tar xfvz ffcall.tar.gz + touch -c ffcall/README + +$(PREFIX)/lib/libavcall.a : ffcall/README + cd ffcall;./configure --prefix=$(PREFIX) --enable-shared && make && make install + +$(IUPFILES) : + wget http://www.kiatoa.com/matt/iup/$@ + cd $(PREFIX)/lib;tar xfvz $(BUILDHOME)/$@ + mv $(PREFIX)/lib/include/* $(PREFIX)/include + +$(PREFIX)/lib/libiup.so : $(IUPFILES) + touch -c $(PREFIX)/lib/libiup.so + +$(CHICKEN_EGG_DIR)/iup.so : $(PREFIX)/lib/libiup.so + $(CHICKEN_INSTALL) $(PROX) -D no-library-checks -feature disable-iup-web iup + +$(CHICKEN_EGG_DIR)/canvas-draw.so : $(PREFIX)/lib/libiup.so + $(CHICKEN_INSTALL) $(PROX) -D no-library-checks canvas-draw + +clean : + rm -rf chicken-4.8.0 eggflags ffcall sqlite-autoconf-$(SQLITE3_VERSION) Index: utils/installall.sh ================================================================== --- utils/installall.sh +++ utils/installall.sh @@ -19,10 +19,19 @@ echo KTYPE=$KTYPE echo You are using PREFIX=$PREFIX echo You are using proxy="$proxy" echo echo "Set additional_libpath to help find gtk or other libraries, don't forget a leading :" + +# NOTES: +# +# Centos with security setup may need to do commands such as following as root: +# +# NB// fix the paths first +# +# for a in /localdisk/chicken/4.8.0/lib/*.so;do chcon -t textrel_shlib_t $a; done + echo ADDITIONAL_LIBPATH=$ADDITIONAL_LIBPATH echo echo To use previous IUP libraries set USEOLDIUP to yes echo USEOLDIUP=$USEOLDIUP echo @@ -82,11 +91,11 @@ cd $BUILDHOME fi # Some eggs are quoted since they are reserved to Bash # for f in matchable readline apropos base64 regex-literals format "regex-case" "test" coops trace csv dot-locking posix-utils posix-extras directory-utils hostinfo tcp rpc csv-xml fmt json md5; do -$CHICKEN_INSTALL $PROX -keep-installed matchable readline apropos base64 regex-literals format "regex-case" "test" coops trace csv dot-locking posix-utils posix-extras directory-utils hostinfo tcp rpc csv-xml fmt json md5 awful http-client spiffy uri-common intarweb http-client spiffy-request-vars +$CHICKEN_INSTALL $PROX -keep-installed matchable readline apropos base64 regex-literals format "regex-case" "test" coops trace csv dot-locking posix-utils posix-extras directory-utils hostinfo tcp rpc csv-xml fmt json md5 awful http-client spiffy uri-common intarweb http-client spiffy-request-vars spiffy-directory-listing ssax sxml-serializer sxml-modifications logpro # if ! [[ -e $PREFIX/lib/chicken/6/$f.so ]];then # $CHICKEN_INSTALL $PROX $f # # $CHICKEN_INSTALL -deploy -prefix $DEPLOYTARG $PROX $f # else # echo Skipping install of egg $f as it is already installed @@ -324,5 +333,8 @@ # cd "Canvas Draw-$CD_REL/chicken" # CSC_OPTIONS="-I$PREFIX/include -L$LIBPATH" $CHICKEN_INSTALL $PROX -D no-library-checks echo You may need to add $LD_LIBRARY_PATH to your LD_LIBRARY_PATH variable, a setup-chicken4x.sh echo file can be found in the current directory which should work for setting up to run chicken4x + +echo Testing iup +$PREFIX/bin/csi -b -eval '(use iup)(print "Success")' Index: utils/mk_wrapper ================================================================== --- utils/mk_wrapper +++ utils/mk_wrapper @@ -9,8 +9,8 @@ echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH" else echo "INFO: LD_LIBRARY_PATH not set" >&2 fi -fullcmd="$prefix/bin/$cmd" +fullcmd="exec $prefix/bin/$cmd" echo "$fullcmd \"\$@\"" Index: utils/mt_ezstep ================================================================== --- utils/mt_ezstep +++ utils/mt_ezstep @@ -1,13 +1,17 @@ #!/bin/bash usage="mt_ezstep stepname prevstepname command [args ...]" if [ "$MT_CMDINFO" == "" ];then - echo "ERROR: $0 should be run within a megatest test environment" - echo "Usage: $usage" - exit + if [ -e megatest.sh ];then + source megatest.sh + else + echo "ERROR: $0 should be run within a megatest test environment" + echo "Usage: $usage" + exit + fi fi # Purpose: This is for the [ezsteps] secton in your testconfig file. # DO NOT USE IN YOUR SCRIPTS! # @@ -68,7 +72,7 @@ exitstatus=1 else exitstatus=0 fi -$MT_MEGATEST -env2file .ezsteps/${stepname} +# $MT_MEGATEST -env2file .ezsteps/${stepname} exit $exitstatus ADDED utils/mt_xterm Index: utils/mt_xterm ================================================================== --- /dev/null +++ utils/mt_xterm @@ -0,0 +1,14 @@ +#!/bin/bash + +MT_TMPDISPLAY=$DISPLAY +if [ -e megatest.sh ];then + source megatest.sh +fi +export DISPLAY=$MT_TMPDISPLAY + +if [ x"$MT_XTERM_CMD" == "x" ];then + exec xterm "$@" +else + exec $MT_XTERM_CMD +fi + ADDED utils/nbload Index: utils/nbload ================================================================== --- /dev/null +++ utils/nbload @@ -0,0 +1,24 @@ +#!/bin/bash + +# load=`uptime|awk '{print $10}'|cut -d, -f1` +load=`uptime|perl -pe 's/.*: (\d+.\d+),.*/$1/'` +if which cpucheck > /dev/null;then + numcpu=`cpucheck|tail -1|awk '{print $6}'` +else + numcpu=`lscpu|grep "CPU.s.:"|awk '{print $2}'` +fi + +lperc=`echo "100 * $load / $numcpu"|bc` +if [[ "x$MAX_ALLOWED_LOAD" == "x" ]]; then + max_load=50 +else + max_load=$MAX_ALLOWED_LOAD +fi +if [[ $lperc -lt $max_load ]];then + echo "$@" | at now + 0 minutes +elif [[ "x$NBLAUNCHER" == "x" ]];then + echo "nbfind $@" | at now + 2 minutes +else + $NBLAUNCHER "$@" +fi + ADDED utils/revtagfsl.scm Index: utils/revtagfsl.scm ================================================================== --- /dev/null +++ utils/revtagfsl.scm @@ -0,0 +1,78 @@ + +;; Copyright 2006-2013, 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. + +(use json regex posix) +(use srfi-69) + +;; Add tags with node nums: trunk(12) +(define fname #f) + +(let ((parms (argv))) + (if (> (length parms) 1) + (set! fname (cadr parms)))) + +(if (not (and fname (file-exists? fname))) + (begin + (print "Usage: revtagfsl /path/to/fossilfile.fossil") + (exit 1))) + +(define (revtag:get-timeline fslfname limit) + (let* ((cmd (if (file-exists? fslfname) + (conc "fossil json timeline checkin --limit " limit " -R " fslfname) + (conc "fossil json timeline checkin --limit " limit)))) + (with-input-from-pipe cmd json-read))) + + +(define mt (vector->list (revtag:get-timeline fname 10000))) +(define tl (map vector->list (cdr (assoc "timeline" (vector->list (cdr (assoc "payload" mt))))))) + +(define tagged (make-hash-table)) +(define usedtags (make-hash-table)) + +(for-each (lambda (node) + (let* ((uuid (cdr (assoc "uuid" node))) + (tags-dat (assoc "tags" node)) + (tags (if tags-dat (cdr tags-dat) '()))) + (for-each (lambda (tag) + (hash-table-set! usedtags tag #t)) + tags))) + tl) + +(define ord-tl (sort tl (lambda (a b)(let ((ta (cdr (assoc "timestamp" a)))(tb (cdr (assoc "timestamp" b))))(< ta tb))))) + +(define (make-tag branch) + (let* ((nextnum (+ 1 (hash-table-ref/default tagged branch 0)))) + (hash-table-set! tagged branch nextnum) + (conc branch "-r" nextnum))) + +(define (get-next-revtag branch) + (let loop ((tag (make-tag branch))) + (if (hash-table-ref/default usedtags tag #f) + (loop (make-tag branch)) + tag))) + +(print "branch, uuid, newtag") + +(let loop ((hed (car ord-tl)) + (tal (cdr ord-tl))) + (let* ((tags (let ((t (assoc "tags" hed))) + (if t (cdr t) '()))) + (uuid (cdr (assoc "uuid" hed))) + (branch (if (null? tags) "nobranch" (car tags))) + (tagpatt (regexp (conc "^" branch "-r\\d+$"))) + (currtag (filter (lambda (x)(string-match tagpatt x)) tags))) + (if (and (not (equal? branch "nobranch")) + (null? currtag)) + (let ((newtag (get-next-revtag branch))) + (print branch ", " uuid ", " newtag) + (system (conc "fossil tag add \"" newtag "\" " uuid " -R " fname)) ;; ?--raw? ?--propagate? TAGNAME CHECK-IN ?VALUE? + (hash-table-set! usedtags currtag #t))) + (if (not (null? tal)) + (loop (car tal)(cdr tal))))) Index: zmq-transport.scm ================================================================== --- zmq-transport.scm +++ zmq-transport.scm @@ -54,11 +54,11 @@ (define (zmq-transport:make-server-url hostport) (if (not hostport) #f (conc "tcp://" (car hostport) ":" (cadr hostport)))) -(define *server-loop-heart-beat* (current-seconds)) +(define *server-loop-heart-beat* (current-seconds)) (define *heartbeat-mutex* (make-mutex)) ;;====================================================================== ;; S E R V E R ;;======================================================================