Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -612,34 +612,63 @@ ;;====================================================================== ;; runspatt is a comma delimited list of run patterns ;; keypatt-alist must contain *all* keys with an associated pattern: '( ("KEY1" "%") .. ) (define (db:extract-ods-file db outputfile keypatt-alist runspatt) - (let ((keysstr (string-intersperse (map car keypatt-alist) ",")) - (keyqry (string-intersperse (map (lambda (p)(conc (car p) " like ? ")) keypatt-alist) " AND ")) - (results '()) - (test-ids '()) - (tempdir (conc "/tmp/" (current-user-name) "/" runspatt "_" (random 10000) "_" (current-process-id)))) + (let* ((keysstr (string-intersperse (map car keypatt-alist) ",")) + (keyqry (string-intersperse (map (lambda (p)(conc (car p) " like ? ")) keypatt-alist) " AND ")) + (test-ids '()) + (tempdir (conc "/tmp/" (current-user-name) "/" runspatt "_" (random 10000) "_" (current-process-id))) + (runsheader (append (list "Runname") + (map car keypatt-alist) + (list "Testname" + "Description" + "Item Path" + "State" + "Status" + "Final Log" + "Run Duration" + "When Run" + "Expected Value" + "Value Found" + "Tolerance" + "Error" + "Warn" + "Tags" + "Run Owner" + "Comment" + "Author" + "Test Owner" + "Reviewed" + "Iterated" + "Diskfree" + "Uname" + "Rundir" + "Host" + "Cpu Load" + "Run Id"))) + (results (list runsheader))) + (debug:print 2 "Using " tempdir " for constructing the ods file") (apply sqlite3:for-each-row (lambda (test-id . b) (set! test-ids (cons test-id test-ids)) (set! results (append results (list b)))) ;; note, drop the test-id db (conc "SELECT t.id,runname," keysstr ",t.testname,description, item_path,t.state,t.status, - attemptnum,final_logf,logdat,run_duration,r.comment, - t.event_time,expected_value,value,tol,tol_perc, - first_err,first_warn,tm.tags, - r.owner,t.comment, - author,tm.owner,reviewed,iterated,avg_runtime, - diskfree,uname,rundir,avg_disk,t.tags,run_id, - host,cpuload + final_logf,run_duration, + strftime('%m/%d/%Y %H:%M:%S',datetime(t.event_time,'unixepoch'),'localtime'),expected_value,value,tol, + first_err,first_warn,tm.tags,r.owner,t.comment, + author, + tm.owner,reviewed,iterated, + diskfree,uname,rundir, + host,cpuload,run_id FROM tests AS t INNER JOIN runs AS r ON t.run_id=r.id INNER JOIN test_meta AS tm ON tm.testname=t.testname WHERE runname LIKE ? AND " keyqry ";") runspatt (map cadr keypatt-alist)) - (set! results (list "Runs" results)) + (set! results (list (cons "Runs" results))) ;; now, for each test, collect the test_data info and add a new sheet (for-each (lambda (test-id) (let ((test-data '()) (curr-test-name #f)) @@ -646,20 +675,23 @@ (sqlite3:for-each-row (lambda (testname item_path category variable value comment) (set! curr-test-name testname) (set! test-data (append test-data (list (list testname item_path category variable value comment))))) db - "SELECT testname,item_path,category,variable,value,comment FROM test_data INNER JOIN tests ON tests.id=test_data.test_id WHERE test_id=?;" + "SELECT testname,item_path,category,variable,test_data.value AS value,test_data.comment AS comment FROM test_data INNER JOIN tests ON tests.id=test_data.test_id WHERE test_id=?;" test-id) - (set! results (append results (list (cons curr-test-name test-data)))) + (if curr-test-name + (set! results (append results (list (cons curr-test-name test-data))))) )) test-ids) (system (conc "mkdir -p " tempdir)) - (pp results) + ;; (pp results) (ods:list->ods tempdir - (if (string-match (regexp "^/") outputfile) ;; full path? + (if (string-match (regexp "^[/~]+.*") outputfile) ;; full path? outputfile - (conc (current-directory) "/" outputfile)) + (begin + (debug:print 0 "WARNING: path given, " outputfile " is relative, prefixing with current directory") + (conc (current-directory) "/" outputfile))) results))) ;; (db:extract-ods-file db "outputfile.ods" '(("sysname" "%")("fsname" "%")("datapath" "%")) "%") Index: keys.scm ================================================================== --- keys.scm +++ keys.scm @@ -85,22 +85,18 @@ ;; (debug:print 0 "WARNING: missing key " x ". Specified in database but not on command line, using \"unk\"") (set! val "default")) (if withkey (list x val) (list val)))) argkeys)))) -;; (define (keys->alist keys) -;; (let* ((keynames (map key:get-fieldname keys)) -;; (argkeys (map (lambda (k)(conc ":" k)) keynames)) -;; (withkey (not (null? withkey))) -;; (newremargs (args:get-args (cons "blah" remargs) argkeys '() args:arg-hash 0))) ;; the cons blah works around a bug in args -;; (debug:print 0 "remargs: " remargs " newremargs: " newremargs) -;; (apply append (map (lambda (x) -;; (let ((val (args:get-arg x))) -;; (if (not val) -;; (debug:print 0 "ERROR: Ignoring key " x " found in database but not on command line")) -;; (if withkey (list x val) (list val)))) -;; argkeys)))) +;; Given a list of keys (list of vectors) return an alist ((key argval) ...) +(define (keys->alist keys defaultval) + (let* ((keynames (map key:get-fieldname keys)) + (newremargs (args:get-args (cons "blah" remargs) (map (lambda (k)(conc ":" k)) keynames) '() args:arg-hash 0))) ;; the cons blah works around a bug in args + (map (lambda (key) + (let ((val (args:get-arg (conc ":" key)))) + (list key (if val val defaultval)))) + keynames))) (define (keystring->keys keystring) (map (lambda (x) (let ((xlst (string-split x ":"))) (list->vector (if (> (length xlst) 1) xlst (append (car xlst)(list "TEXT")))))) Index: megatest-version.scm ================================================================== --- megatest-version.scm +++ megatest-version.scm @@ -1,3 +1,3 @@ ;; Always use two digit decimal ;; 1.01, 1.02...1.10,1.11 ... 1.99,2.00.. -(define megatest-version 1.23) +(define megatest-version 1.24) Index: megatest.scm ================================================================== --- megatest.scm +++ megatest.scm @@ -72,10 +72,11 @@ -rebuild-db : bring the database schema up to date -rollup : fill run (set by :runname) with latest test(s) from prior runs with same keys -rename-run : rename run (set by :runname) to , requires keys -update-meta : update the tests metadata for all tests + -extract-ods : extract an open document spreadsheet from the database Helpers -runstep stepname ... : take remaining params as comand and execute as stepname log will be in stepname.log. Best to put command in quotes -logpro file : with -exec apply logpro file to stepname.log, creates @@ -117,10 +118,11 @@ ":value" ":expected_value" ":tol" ":units" ;; misc + "-extract-ods" "-debug" ;; for *verbosity* > 2 ) (list "-h" "-force" "-xterm" @@ -312,10 +314,24 @@ "rollup tests" (lambda (db keys keynames keyvallst) (let ((n (args:get-arg "-rollup"))) (runs:rollup-run db keys))))) +;;====================================================================== +;; Extract a spreadsheet from the runs database +;;====================================================================== + +(if (args:get-arg "-extract-ods") + (general-run-call + "-extract-ods" + "Make ods spreadsheet" + (lambda (db keys keynames keyvallst) + (let ((outputfile (args:get-arg "-extract-ods")) + (runspatt (args:get-arg ":runname")) + (keyvalalist (keys->alist keys "%"))) + (db:extract-ods-file db outputfile keyvalalist (if runspatt runspatt "%")))))) + ;;====================================================================== ;; run one test ;;====================================================================== ;; 1. find the config file Index: ods.scm ================================================================== --- ods.scm +++ ods.scm @@ -132,33 +132,38 @@ (define (ods:sheet sheetdat) (let ((name (car sheetdat)) (rows (cdr sheetdat))) (conc "\n" (conc (ods:column) - (apply conc (map ods:row rows))) + (string-join (map ods:row rows) "")) ""))) ;; seems to be called once at top of each sheet, i.e. a column of rows (define (ods:column) "\n") ;; cells is a list of ... (define (ods:row cells) - (apply conc - (cons "\n" - (append (map ods:cell cells) - (list "\n"))))) + (conc "\n" + (string-join (map ods:cell cells) "") + "\n")) ;; types are "string" or "float" (define (ods:cell value) - (let ((type (cond + (let* ((type (cond ((string? value) "string") ((symbol? value) "string") ((number? value) "float") - (else "string")))) - (conc "" "\n" - "" value "" "\n" + (else #f))) + (tmpval (if (symbol? value) + (symbol->string value) + (if type value ""))) ;; convert everything else to an empty string + (escval (if (string? tmpval)(string-substitute (regexp "<") "<" (string-substitute (regexp ">") ">" tmpval)) tmpval))) + (conc "\n" + "" escval "" "\n" "" "\n"))) ;; create the directories (define (ods:construct-dir path) (for-each @@ -203,7 +208,7 @@ (map display ods:content-header) ;; process each sheet (map print (map ods:sheet data)) (map display ods:content-footer))) - (system (conc "cd " path "; zip " fname " -n mimetype mimetype `find . |grep -v mimetype`"))))) + (system (conc "cd " path "; zip " fname " -n mimetype mimetype `find . |grep -v mimetype` > /dev/null")))))