Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -31,11 +31,11 @@ cgisetup/models/pgdb.scm # module source files # ftail.scm rmtmod.scm commonmod.scm removed MSRCFILES = ducttape-lib.scm pkts.scm stml2.scm cookie.scm mutils.scm \ - mtargs.scm commonmod.scm dbmod.scm + mtargs.scm commonmod.scm dbmod.scm adjutant.scm GUISRCF = dashboard-context-menu.scm dashboard-tests.scm \ dashboard-guimonitor.scm gutils.scm dcommon.scm tree.scm \ vg.scm @@ -61,25 +61,16 @@ ifeq ($(MTESTHASH),) $(error MTESTHASH is broken!) endif -CSIPATH=$(shell which csi) -CKPATH=$(shell dirname $(shell dirname $(CSIPATH))) ARCHSTR=$(shell if [[ -e /usr/bin/sw_vers ]]; then /usr/bin/sw_vers -productVersion; else lsb_release -sr; fi) -# ARCHSTR=$(shell bash -c "echo \$$MACHTYPE") - -# if have csi on path use that, else use default -CHICKEN_PREFIX=$(or $(CKPATH),$(PREFIX)/$(ARCHSTR)) PNGFILES = $(shell cd docs/manual;ls *png) all : $(PREFIX)/bin/.$(ARCHSTR) mtest dboard mtut tcmt -whatever : - @echo "CHICKEN_PREFIX=$(CHICKEN_PREFIX)" - mtest: $(OFILES) readline-fix.scm megatest.o $(MOFILES) $(MOIMPFILES) csc $(CSCOPTS) $(OFILES) $(MOFILES) $(MOIMPFILES) megatest.o -o mtest showmtesthash: @echo $(MTESTHASH) @@ -122,11 +113,12 @@ runs.o \ server.o \ tasks.o \ tdb.o \ tests.o \ - subrun.o + subrun.o \ + ezsteps.o # mofiles/commonmod.o \ tcmt : $(TCMTOBJS) tcmt.scm csc $(CSCOPTS) $(TCMTOBJS) $(MOFILES) $(MOIMPFILES) tcmt.scm -o tcmt @@ -178,10 +170,11 @@ mofiles/stml2.o : mofiles/cookie.o # special include based modules mofiles/pkts.o : pkts/pkts.scm +mofiles/stml2.o : cookie.o # mofiles/mtargs.o : mtargs/mtargs.scm # mofiles/mtconfigf.o : mtconfigf/mtconfigf.scm # mofiles/ulex.o : ulex/ulex.scm mofiles/mutils.o : mutils/mutils.scm mofiles/cookie.o : stml2/cookie.scm Index: TODO ================================================================== --- TODO +++ TODO @@ -1,6 +1,6 @@ -# Copyright 2006-2017, Matthew Welland. +# Copyright 2006-2020, Matthew Welland. # # This file is part of Megatest. # # Megatest is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,10 +17,61 @@ NOTE: This file gets copied occasionally into the wiki as "Roadmap". Do not make changes in the wiki, they will be lost! See the file "DONE" to see completed items. +FIXME +==== + +.dump +---------------- +WARNING: disk disk0 at path "/mfs/tmp/archive" is not a directory - ignoring it. + +Warning (#): in thread: unbound variable: block-id + + Call history: + + common.scm:693: hash-table-ref/default + common.scm:694: current-seconds + common.scm:697: hash-table-set! + common.scm:2232: debug:print + common_records.scm:140: debug:debug-mode + common_records.scm:141: with-output-to-port + common.scm:2245: directory? + common.scm:2246: common:low-noise-print + common.scm:692: g2022 + common.scm:692: g2022 + common.scm:692: string-intersperse + common.scm:693: hash-table-ref/default + common.scm:694: current-seconds + common.scm:2261: debug:print + common_records.scm:140: debug:debug-mode + archive.scm:125: debug:print <-- +INFO: (0) Estimating disk space usage for scriptinc/: 184 + +Error: uncaught exception: # + + Call history: + + common.scm:1299: ##sys#get-keyword + common.scm:1299: call-with-current-continuation + common.scm:1299: with-exception-handler + common.scm:1299: ##sys#call-with-values + common.scm:1304: thunk + common.scm:1310: file-exists? + common.scm:1299: k2554 + common.scm:1299: g2558 + runs.scm:2438: common:get-disk-space-used + common.scm:2128: conc + common.scm:2128: with-input-from-pipe + runs.scm:2438: debug:print-info + common_records.scm:235: debug:debug-mode + common_records.scm:236: port? + common_records.scm:236: with-output-to-port + runs.scm:2443: thread-join! <-- +Press any key to continue +---------------- TODO ==== WW15 ADDED adjutant.scm Index: adjutant.scm ================================================================== --- /dev/null +++ adjutant.scm @@ -0,0 +1,34 @@ +;;====================================================================== +;; Copyright 2017, Matthew Welland. +;; +;; This file is part of Megatest. +;; +;; Megatest is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; Megatest is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Megatest. If not, see . + +;;====================================================================== + +(declare (unit adjutant)) + +(module adjutant + * + +(import scheme chicken data-structures extras files) +(import (prefix sqlite3 sqlite3:) posix typed-records srfi-18 srfi-69 + md5 message-digest + regex srfi-1) + +(define (adjutant-run) + (print "Running the adjutant!")) + +) Index: chicken.makefile ================================================================== --- chicken.makefile +++ chicken.makefile @@ -19,10 +19,19 @@ #====================================================================== # Chicken build #====================================================================== +# CHICKEN_BIN_DIR=$(shell dirname $(shell which csi)) +# if have csi on path use that, else use default +# CSIPATH=$(shell which csi) +# CKPATH=$(shell dirname $(shell dirname $(CSIPATH))) +sCHICKEN_PREFIX=$(or $(CKPATH),$(PREFIX)/bin/.$(ARCHSTR)) + +whatever : + @echo "CHICKEN_PREFIX=$(CHICKEN_PREFIX)" + tgz-$(USER)/postgresql-9.6.4.tar.gz : mkdir -p tgz-$(USER) wget -c https://ftp.postgresql.org/pub/source/v9.6.4/postgresql-9.6.4.tar.gz mv postgresql-9.6.4.tar.gz tgz-$(USER)/ @@ -101,19 +110,18 @@ ALL_CKBIN=chicken chicken-bind chicken-bug chicken-dump \ chicken-install chicken-profile chicken-sqlite3 chicken-status \ chicken-uninstall csc csi feathers nanocat sqlite3 vacuumdb logpro \ refdb -# CHICKEN_BIN_DIR=$(shell dirname $(shell which csi)) CKBIN_WRAPPERS=$(addprefix $(PREFIX)/bin/,$(ALL_CKBIN)) $(PREFIX)/bin/% : $(CHICKEN_PREFIX)/bin/% $(CHICKEN_PREFIX)/bin/csi $(EGGSTARG2) utils/mk_wrapper_tool $(PREFIX) $* $(PREFIX)/bin/$* chmod a+x $(PREFIX)/bin/$* $(PREFIX)/bin : - mkdir -p $(PREFIX)/bin + mkdir -p $(PREFIX)/bin $(CHICKEN_PREFIX)/bin chicken : $(PREFIX)/bin $(CHICKEN_PREFIX)/bin/csi binwrappers @echo "Fake target to build prefix chicken" binwrappers : $(CKBIN_WRAPPERS) @@ -143,7 +151,7 @@ $(CHICKEN_PREFIX)/bin/chicken-install $* > $*.done build-$(USER)/eggs-installed/%.done : $(CHICKEN_PREFIX)/bin/csi $(EGGS) $(CHICKEN_PREFIX)/bin/chicken-install $* > build-$(USER)/eggs-installed/$*.done - - +build-clean : + rm -rf build-$(USER) bin Index: common.scm ================================================================== --- common.scm +++ common.scm @@ -2190,12 +2190,13 @@ ;; check space in dbdir and in megatest dir ;; returns: ok/not dbspace required-space ;; (define (common:check-db-dir-space) (let* ((required (string->number + ;; default is 1GB (or actually a billion bytes) This is the number of 1 kB blocks. (or (configf:lookup *configdat* "setup" "dbdir-space-required") - "100000"))) + "1000000"))) (dbdir (common:get-db-tmp-area)) ;; (db:get-dbdir)) (tdbspace (common:check-space-in-dir dbdir required)) (mdbspace (common:check-space-in-dir *toppath* required))) (sort (list tdbspace mdbspace) (lambda (a b) (< (cadr a)(cadr b)))))) @@ -2214,13 +2215,16 @@ (exit 1))))) ;; paths is list of lists ((name path) ... ) ;; (define (common:get-disk-with-most-free-space disks minsize) - (let ((best #f) + (let* ((best #f) (bestsize 0) - (min-inodes (or (string->number (if (configf:lookup *configdat* "setup" "min_inodes") (configf:lookup *configdat* "setup" "min_inodes") "0")) 0))) + (default-min-inodes-string "1000000") + (default-min-inodes (string->number default-min-inodes-string)) + (min-inodes (or (string->number (if (configf:lookup *configdat* "setup" "min_inodes") (configf:lookup *configdat* "setup" "min_inodes") default-min-inodes-string)) default-min-inodes))) + (for-each (lambda (disk-num) (let* ((dirpath (cadr (assoc disk-num disks))) (freespc (cond ((not (directory? dirpath)) @@ -2252,10 +2256,11 @@ -1) (else (get-free-inodes dirpath)))) ;;(free-inodes (get-free-inodes dirpath)) ) + (debug:print 2 *default-log-port* "INFO: disk " disk-num " path " dirpath " free space " freespc " free inodes " free-inodes) (if (and (> freespc bestsize)(> free-inodes min-inodes )) (begin (set! best (cons disk-num dirpath)) (set! bestsize freespc))) ;;(print "Processing: " disk-num " bestsize: " bestsize " best: " best " freespc: " freespc " min-inodes: " min-inodes " free-inodes: " free-inodes) Index: configure ================================================================== --- configure +++ configure @@ -16,10 +16,17 @@ # # You should have received a copy of the GNU General Public License # along with Megatest. If not, see . # Configure the build + +if [[ "$1"x == "x" ]];then + PREFIX=$PWD +else + PREFIX=$1 +fi + #====================================================================== # Configure stuff needed for eggs #====================================================================== @@ -58,15 +65,37 @@ #====================================================================== # Do we need Chicken? #====================================================================== +if [[ -e /usr/bin/sw_vers ]]; then + ARCHSTR=$(/usr/bin/sw_vers -productVersion) +else + ARCHSTR=$(lsb_release -sr) +fi + +echo "CHICKEN_PREFIX=$PREFIX/.$ARCHSTR" >> makefile.inc +CHICKEN_PREFIX=$PREFIX/bin/.$ARCHSTR + if [[ ! $(type csi) ]];then echo "Chicken build needed." echo "BUILD_CHICKEN=yes" >> makefile.inc configure_dependencies echo "include chicken.makefile" >> makefile.inc +else + echo "CSIPATH=$(which csi)" >> makefile.inc + CSIPATH=$(which csi) + echo "CKPATH=$(dirname $(dirname $CSIPATH))" >> makefile.inc fi -echo "All done creating makefile.inc, feel free to edit it!" +# Make setup scripts +echo "#!/bin/bash" > setup.sh +echo "export PATH=$CHICKEN_PREFIX/bin:\$PATH" >> setup.sh +echo "export LD_LIBRARY_PATH=$CHICKEN_PREFIX/lib" >> setup.sh +echo 'exec "$@"' >> setup.sh +chmod a+x setup.sh + +echo "setenv PATH $CHICKEN_PREFIX/bin:\$PATH" > setup.csh +echo "setenv LD_LIBRARY_PATH $CHICKEN_PREFIX/lib" >> setup.csh - +echo "All done creating makefile.inc, feel free to edit it!" +echo "run \"setup.sh bash\" or source setup.csh to get PATH and LD_LIBRARY_PATH adjusted" Index: dashboard.scm ================================================================== --- dashboard.scm +++ dashboard.scm @@ -1484,11 +1484,11 @@ (hash-table-set! tests-draw-state 'first-time #t) ;; (hash-table-set! tests-draw-state 'scalef 1) (tests:get-full-data test-names test-records '() all-tests-registry) (set! sorted-testnames (tests:sort-by-priority-and-waiton test-records)) - ;; refer to (dboard:tabcodat-keys tabdat), (dboard:tabdat-dbkeys tabdat) for keys + ;; refer to (dboard:tabdat-keys tabdat), (dboard:tabdat-dbkeys tabdat) for keys (let* ((result (iup:vbox (dcommon:command-execution-control tabdat) (iup:split #:orientation "VERTICAL" ;; "HORIZONTAL" @@ -2765,65 +2765,83 @@ (cell-width (dboard:tabdat-runs-cell-width runs-dat))) ;; controls (along bottom) ;; (set! controls (dboard:make-controls commondat runs-dat)) ;; create the left most column for the run key names and the test names - (set! lftlst (list (iup:hbox - (iup:label) ;; (iup:valuator) - (apply iup:vbox - (map (lambda (x) - (let ((res (iup:hbox #:expand "HORIZONTAL" - (iup:label x #:size (conc 40 btn-height) #:fontsize btn-fontsz #:expand "NO") ;; "HORIZONTAL") - (iup:textbox #:size (conc 35 btn-height) #:fontsize btn-fontsz #:value "%" #:expand "NO" ;; "HORIZONTAL" - #:action (lambda (obj unk val) - ;; each field (field name is "x" var) live updates - ;; the search filter as it is typed - (dboard:tabdat-target-set! runs-dat #f) ;; ensure the fields text boxes are used and not the info from the tree - (mark-for-update runs-dat) - (update-search commondat runs-dat x val)))))) - (set! i (+ i 1)) - res)) - keynames))))) + (set! lftlst + (list (iup:hbox + (iup:label) ;; (iup:valuator) + (apply iup:vbox + (map (lambda (x) + (let ((res (iup:hbox + #:expand "HORIZONTAL" + (iup:label x + #:size (conc 40 btn-height) + #:fontsize btn-fontsz + #:expand "NO") ;; "HORIZONTAL") + (iup:textbox + #:size (conc 35 btn-height) + #:fontsize btn-fontsz + #:value "%" + #:expand "NO" ;; "HORIZONTAL" + #:action (lambda (obj unk val) + ;; each field + ;; (field name is "x" var) live updates + ;; the search filter as it is typed + (dboard:tabdat-target-set! runs-dat #f) + ;; ensure fields text boxes are used + ;; and not the info from the tree + (mark-for-update runs-dat) + (update-search commondat runs-dat x val)))))) + (set! i (+ i 1)) + res)) + keynames))))) (let loop ((testnum 0) (res '())) (cond ((>= testnum ntests) ;; now lftlst will be an hbox with the test keys and the test name labels (set! lftlst - (append lftlst - (list (iup:hbox - #:expand "HORIZONTAL" - (iup:valuator - #:valuechanged_cb (lambda (obj) - (let ((val (string->number (iup:attribute obj "VALUE"))) - (oldmax (string->number (iup:attribute obj "MAX"))) - (newmax (* 10 (length (dboard:tabdat-all-test-names runs-dat))))) - (dboard:commondat-please-update-set! commondat #t) - (dboard:tabdat-start-test-offset-set! runs-dat (inexact->exact (round (/ val 10)))) - (debug:print 6 *default-log-port* "(dboard:tabdat-start-test-offset runs-dat) " - (dboard:tabdat-start-test-offset runs-dat) " val: " val - " newmax: " newmax " oldmax: " oldmax) - (if (< val 10) - (iup:attribute-set! obj "MAX" newmax)) - )) - #:expand "VERTICAL" - #:orientation "VERTICAL" - #:min 0 - #:step 0.01) - (apply iup:vbox (reverse res))))))) + (append + lftlst + (list + (iup:hbox + #:expand "HORIZONTAL" + (iup:valuator + #:valuechanged_cb + (lambda (obj) + (let ((val (string->number (iup:attribute obj "VALUE"))) + (oldmax (string->number (iup:attribute obj "MAX"))) + (newmax (* 10 (length (dboard:tabdat-all-test-names runs-dat))))) + (dboard:commondat-please-update-set! commondat #t) + (dboard:tabdat-start-test-offset-set! runs-dat + (inexact->exact (round (/ val 10)))) + (debug:print 6 *default-log-port* + "(dboard:tabdat-start-test-offset runs-dat) " + (dboard:tabdat-start-test-offset runs-dat) " val: " val + " newmax: " newmax " oldmax: " oldmax) + (if (< val 10) + (iup:attribute-set! obj "MAX" newmax)) + )) + #:expand "VERTICAL" + #:orientation "VERTICAL" + #:min 0 + #:step 0.01) + (apply iup:vbox (reverse res))))))) (else - (let ((labl (iup:button "" ;; the testname labels - #:flat "YES" - #:alignment "ALEFT" + (let ((labl (iup:button + "" ;; the testname labels + #:flat "YES" + #:alignment "ALEFT" ; #:image img1 ; #:impress img2 - #:size (conc cell-width btn-height) - #:expand "HORIZONTAL" - #:fontsize btn-fontsz - #:action (lambda (obj) - (mark-for-update runs-dat) - (toggle-hide testnum (dboard:commondat-uidat commondat)))))) ;; (iup:attribute obj "TITLE")))) + #:size (conc cell-width btn-height) + #:expand "HORIZONTAL" + #:fontsize btn-fontsz + #:action (lambda (obj) + (mark-for-update runs-dat) + (toggle-hide testnum (dboard:commondat-uidat commondat)))))) (vector-set! lftcol testnum labl) (loop (+ testnum 1)(cons labl res)))))) ;; These are the headers for each row (let loop ((runnum 0) (keynum 0) @@ -2921,11 +2939,11 @@ (dashboard:runs-horizontal-slider runs-dat)))) controls )) (views-cfgdat (common:load-views-config)) (additional-tabnames '()) - (tab-start-num 6) ;; DON'T FORGET TO UPDATE THIS WHEN CHANGING THE STANDARD TABS BELOW + (tab-start-num 5) ;; DON'T FORGET TO UPDATE THIS WHEN CHANGING THE STANDARD TABS BELOW ;; (data (dboard:tabdat-init (make-d:data))) (additional-views ;; process views-dat (let ((tab-num tab-start-num) (result '())) (for-each @@ -2964,24 +2982,22 @@ (dboard:commondat-please-update-set! commondat #t) (dboard:tabdat-layout-update-ok-set! tabdat #t))) "tabchangepos")) (dashboard:summary commondat stats-dat tab-num: 0) runs-view - (make-runs-view commondat runs2-dat 2) - (dashboard:runs-summary commondat onerun-dat tab-num: 3) - ;; (dashboard:new-view db data new-view-dat tab-num: 3) - (dashboard:run-controls commondat runcontrols-dat tab-num: 4) - (dashboard:run-times commondat runtimes-dat tab-num: 5) - ;; (dashboard:runs-summary commondat onerun-dat tab-num: 4) + ;; (make-runs-view commondat runs2-dat 2) + (dashboard:runs-summary commondat onerun-dat tab-num: 2) + (dashboard:run-controls commondat runcontrols-dat tab-num: 3) + (dashboard:run-times commondat runtimes-dat tab-num: 4) additional-views))) ;; (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" "Runs2") - (iup:attribute-set! tabs "TABTITLE3" "Run Summary") - (iup:attribute-set! tabs "TABTITLE4" "Run Control") - (iup:attribute-set! tabs "TABTITLE5" "Run Times") + ;; (iup:attribute-set! tabs "TABTITLE2" "Runs2") + (iup:attribute-set! tabs "TABTITLE2" "Run Summary") + (iup:attribute-set! tabs "TABTITLE3" "Run Control") + (iup:attribute-set! tabs "TABTITLE4" "Run Times") ;; (iup:attribute-set! tabs "TABTITLE3" "New View") ;; (iup:attribute-set! tabs "TABTITLE4" "Run Control") ;; set the tab names for user added tabs (for-each @@ -2993,14 +3009,14 @@ ;; make the iup tabs object available (for changing color for example) (dboard:commondat-hide-not-hide-tabs-set! commondat tabs) ;; now set up the tabdat lookup (dboard:common-set-tabdat! commondat 0 stats-dat) (dboard:common-set-tabdat! commondat 1 runs-dat) + ;;(dboard:common-set-tabdat! commondat 2 runs2-dat) (dboard:common-set-tabdat! commondat 2 onerun-dat) (dboard:common-set-tabdat! commondat 3 runcontrols-dat) - (dboard:common-set-tabdat! commondat 4 runs2-dat) - (dboard:common-set-tabdat! commondat 5 runtimes-dat) + (dboard:common-set-tabdat! commondat 4 runtimes-dat) (iup:vbox tabs ;; controls )))) Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -1251,28 +1251,28 @@ id INTEGER PRIMARY KEY, archive_area_name TEXT, disk_path TEXT, last_df INTEGER DEFAULT -1, last_df_time TIMESTAMP DEFAULT (strftime('%s','now')), - creation_time TIMESTAMP DEFAULT (strftime('%','now')));") + creation_time TIMESTAMP DEFAULT (strftime('%s','now')));") ;; individual bup (or tar) data chunks (sqlite3:execute db "CREATE TABLE IF NOT EXISTS archive_blocks ( id INTEGER PRIMARY KEY, archive_disk_id INTEGER, disk_path TEXT, last_du INTEGER DEFAULT -1, last_du_time TIMESTAMP DEFAULT (strftime('%s','now')), - creation_time TIMESTAMP DEFAULT (strftime('%','now')));") + creation_time TIMESTAMP DEFAULT (strftime('%s','now')));") ;; tests allocated to what chunks. reusing a chunk for a test/item_path is very efficient ;; NB// the per run/test recording of where the archive is stored is done in the test ;; record. (sqlite3:execute db "CREATE TABLE IF NOT EXISTS archive_allocations ( id INTEGER PRIMARY KEY, archive_block_id INTEGER, testname TEXT, item_path TEXT, - creation_time TIMESTAMP DEFAULT (strftime('%','now')));") + creation_time TIMESTAMP DEFAULT (strftime('%s','now')));") ;; move this clean up call somewhere else (sqlite3:execute db "DELETE FROM tasks_queue WHERE state='done' AND creation_time < ?;" (- (current-seconds)(* 24 60 60))) ;; remove older than 24 hrs (sqlite3:execute db (conc "CREATE INDEX IF NOT EXISTS runs_index ON runs (runname" (if havekeys "," "") keystr ");")) ;; (sqlite3:execute db "CREATE VIEW runs_tests AS SELECT * FROM runs INNER JOIN tests ON runs.id=tests.run_id;") (sqlite3:execute db "CREATE TABLE IF NOT EXISTS extradat (id INTEGER PRIMARY KEY, run_id INTEGER, key TEXT, val TEXT);") @@ -1747,11 +1747,12 @@ ) (begin (debug:print 0 *default-log-port* "INFO: test " test-id " final state/status is not COMPLETED/PASS. It is " result) (db:set-state-status-and-roll-up-items dbstruct run-id test-id 'foo "COMPLETED" "DEAD" "Test stopped responding while in RUNNING or REMOTEHOSTSTART; presumed dead.") ) - ) + ) ;;call end of eud of run detection for posthook + (launch:end-of-run-check run-id) ) ) all-ids) ) ) Index: dcommon.scm ================================================================== --- dcommon.scm +++ dcommon.scm @@ -616,70 +616,74 @@ ;; Megatest version (iup:attribute-set! general-matrix "2:0" "Version") (iup:attribute-set! general-matrix "2:1" (conc megatest-version "-" (substring megatest-fossil-hash 0 4))) general-matrix)) + +(define (dcommon:stats-updater commondat tabdat stats-matrix) + (if (and (iup:ihandle? stats-matrix) + (dashboard:database-changed? commondat tabdat context-key: 'run-stats)) + (let* ((changed #f) + (run-stats (rmt: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 (common:max (map cadr row-indices)))) + (max-col (if (null? col-indices) 1 + (common:max (map cadr col-indices)))) + (max-visible (max (- (dboard:tabdat-num-tests tabdat) 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-vis) + (iup:attribute-set! stats-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row)) + (print "row-indices: " row-indices " col-indices: " col-indices) + ;; Row labels + (for-each (lambda (ind) + (let* ((name (car ind)) + (num (cadr ind)) + (key (conc num ":0"))) + (if (not (equal? (iup:attribute stats-matrix key) name)) + (begin + (set! changed #t) + (iup:attribute-set! stats-matrix key name))))) + row-indices) + + ;; Col labels + (for-each (lambda (ind) + (let* ((name (car ind)) + (num (cadr ind)) + (key (conc "0:" num))) + (if (not (equal? (iup:attribute stats-matrix key) name)) + (begin + (set! changed #t) + (iup:attribute-set! stats-matrix key name))))) + col-indices) + + ;; Cell contents + (for-each (lambda (entry) + (let* ((row-name (car entry)) + (col-name (cadr entry)) + (value (caddr entry)) + (row-num (cadr (assoc row-name row-indices))) + (col-num (cadr (assoc col-name col-indices))) + (key (conc row-num ":" col-num))) + (if (not (equal? (iup:attribute stats-matrix key) value)) + (begin + (set! changed #t) + (iup:attribute-set! stats-matrix key value))))) + run-stats) + (if changed (iup:attribute-set! stats-matrix "REDRAW" "ALL"))))) + (define (dcommon:run-stats commondat tabdat #!key (tab-num #f)) (let* ((stats-matrix (iup:matrix expand: "YES")) - (changed #f) (stats-updater (lambda () - (if (dashboard:database-changed? commondat tabdat context-key: 'run-stats) - (let* ((run-stats (rmt: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 (common:max (map cadr row-indices)))) - (max-col (if (null? col-indices) 1 - (common:max (map cadr col-indices)))) - (max-visible (max (- (dboard:tabdat-num-tests tabdat) 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-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)) - (num (cadr ind)) - (key (conc num ":0"))) - (if (not (equal? (iup:attribute stats-matrix key) name)) - (begin - (set! changed #t) - (iup:attribute-set! stats-matrix key name))))) - row-indices) - - ;; Col labels - (for-each (lambda (ind) - (let* ((name (car ind)) - (num (cadr ind)) - (key (conc "0:" num))) - (if (not (equal? (iup:attribute stats-matrix key) name)) - (begin - (set! changed #t) - (iup:attribute-set! stats-matrix key name))))) - col-indices) - - ;; Cell contents - (for-each (lambda (entry) - (let* ((row-name (car entry)) - (col-name (cadr entry)) - (value (caddr entry)) - (row-num (cadr (assoc row-name row-indices))) - (col-num (cadr (assoc col-name col-indices))) - (key (conc row-num ":" col-num))) - (if (not (equal? (iup:attribute stats-matrix key) value)) - (begin - (set! changed #t) - (iup:attribute-set! stats-matrix key value))))) - run-stats) - (if changed (iup:attribute-set! stats-matrix "REDRAW" "ALL"))) - )))) + (dcommon:stats-updater commondat tabdat stats-matrix)))) ;; (dboard:commondat-please-update-set! commondat #t) ;; force redraw on first pass ;; (mark-for-update tabdat) ;; (stats-updater) (dboard:commondat-add-updater commondat stats-updater tab-num: tab-num) ;; (set! dashboard:update-summary-tab updater) Index: docs/manual/installation.txt ================================================================== --- docs/manual/installation.txt +++ docs/manual/installation.txt @@ -20,9 +20,32 @@ Dependencies ~~~~~~~~~~~~ Chicken scheme and a number of "eggs" are required for building -Megatest. See the script installall.sh in the utils directory of the -source distribution for an automated way to install everything -needed for building Megatest on Linux. +Megatest. In the v1.66 and beyond assistance to create the build +system is built into the Makefile. + +.Installation steps (overview) +------------------------------------- +./configure +make chicken +setup.sh make -j install +------------------------------------- + +Or install the needed build system manually: + +. Chicken scheme from http://call-cc.org +. IUP from http://webserver2.tecgraf.puc-rio.br/iup/ +. CD from http://webserver2.tecgraf.puc-rio.br/cd/ +. IM from https://webserver2.tecgraf.puc-rio.br/im/ +. ffcall from http://webserver2.tecgraf.puc-rio.br/iup/ +. Nanomsg from https://nanomsg.org/ (NOTE: Plan is to eliminate nanomsg dependency). +. Needed eggs (look at the eggs lists in the Makefile) + +Then follow these steps: +.Installation steps (self-built chicken scheme build system) +------------------------------------- +./configure +make -j install +------------------------------------- Index: docs/manual/megatest_manual.html ================================================================== --- docs/manual/megatest_manual.html +++ docs/manual/megatest_manual.html @@ -767,12 +767,12 @@ @@ -782,11 +782,11 @@

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

License
-
    Copyright 2006-2017, Matthew Welland.
+
    Copyright 2006-2020, Matthew Welland.
 
     This document is part of Megatest.
 
     Megatest is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -809,11 +809,11 @@
 

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. I thought a single open source tool, flexible enough to meet the needs -of any team doing continuous integrating and or running a complex +of any team doing continuous integration and or running a complex suite of tests for release qualification would solve some problems for me and for others.

-- Matt Welland, original author of the Megatest tool suite.
@@ -955,20 +955,552 @@ Static
+
+
+

TODO / Road Map

+
+

Note: This road-map is a wish list and not a formal plan. Items are in +rough priority but are subject to change. Development is driven by +user requests, developer "itch" and bug reports. Please contact +matt@kiatoa.com with requests or bug reports. Requests from inside +Intel generally take priority.

+

Dashboard and runs

+
    +
  1. +

    +Multi-area dashboard view +

    +
  2. +
+

Tests Support

+
    +
  1. +

    +Add variable $MT_RUNPATH = $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME +

    +
  2. +
  3. +

    +Improve [script], especially indent handling +

    +
  4. +
+

Scalability

+
    +
  1. +

    +Overflow database methodology - combine the best of the v1.63 + multi-db approach and the current db-in-tmp approach (currently + slowness can be seen when number of tests in a db goes over 50-100k, + with the overflow db it will be able to handle 1000’s of runs with + 50-100k tests per run). High priority - goal is to complete this by + 20Q3. +

    +
  2. +
+

Mtutils/CI

+
    +
  1. +

    +Enable mtutil calls from dashboard (for remote control) +

    +
  2. +
  3. +

    +Logs browser (esp. for surfacing mtutil related activities) +

    +
  4. +
  5. +

    +Embed ftfplan for distributed automation, completed activities trigger QA runs which trigger deployment etc. +

    +
  6. +
  7. +

    +Jenkins junit XML support [DONE] +

    +
  8. +
  9. +

    +Add output flushing in teamcity support +

    +
  10. +
+

Build system

+
    +
  1. +

    +./configure ⇒ ubuntu, sles11, sles12, rh7 [WIP] +

    +
  2. +
  3. +

    +Switch to using simple runs query everywhere +

    +
  4. +
  5. +

    +Add end_time to runs and add a rollup call that sets state, status and end_time +

    +
  6. +
+

Code refactoring/quality/performance

+
    +
  1. +

    +Switch to scsh-process pipeline management for job execution/control +

    +
  2. +
  3. +

    +Use call-with-environment-variables where possible. +

    +
  4. +
+

Migration to inmem db and or overflow db

+
    +
  1. +

    +Re-work the dbstruct data structure? +

    +
      +
    1. +

      +[ run-id.db inmemdb last-mod last-read last-sync inuse ] +

      +
    2. +
    +
  2. +
+

Some ideas for Megatest 2.0

+
    +
  1. +

    +Aggressive megatest.config and runconfig.config caching. +

    +
      +
    1. +

      +Cache the configs in $MT_RUNPATH +

      +
    2. +
    3. +

      +Following invocations of –run, -rerun* will calculate the new config but only overwrite the cached file IF changed +

      +
    4. +
    +
  2. +
  3. +

    +If the cached file changes ALL existing tests go from COMPLETED → STALE, I’m not sure what to do about RUNNING tests +

    +
  4. +
  5. +

    +!VARS in runconfigs are not exported to the environment. They are accessed via rget as if the ! was not there. +

    +
  6. +
  7. +

    +Per test copy commands (example is incomplete). +

    +
  8. +
+
+
+
[testcopy]
+%/iind% unison SRC DEST
+% cp –r SRC DEST
+
+

Add ability to move runs to other Areas (overlaps with overflow db system)

+
    +
  1. +

    +allow shrinking megatest.db data by moving runs to an alternate + Megatest area with same keys. +

    +
  2. +
  3. +

    +add param -destination [area|path]. when specified runs are copied to new + area and removed from local db. +

    +
  4. +
  5. +

    +the data move would involve these steps +

    +
      +
    1. +

      +copy the run data to destination area megatest.db +

      +
    2. +
    3. +

      +mark the run records as deleted, do not remove the run data on disk +

      +
    4. +
    +
  6. +
  7. +

    +accessing the data would be by running dashboard in the satellite area +

    +
  8. +
  9. +

    +future versions of Megatest dashboard should support displaying areas in a + merged way. +

    +
  10. +
  11. +

    +some new controls would be supported in the config +

    +
      +
    1. +

      +[setup] ⇒ allow-runs [no|yes] ⇐= used to disallow runs +

      +
    2. +
    3. +

      +[setup] ⇒ auto-migrate=[areaname|path] ⇐= used to automatically + migrate data to a satellite area. +

      +
    4. +
    +
  12. +
+

Eliminate ties to homehost (part of overflow db system)

+
    +
  1. +

    +Server creates captain pkt +

    +
  2. +
  3. +

    +Create a lock in the db +

    +
  4. +
  5. +

    +Relinquish db when done +

    +
  6. +
+

Tasks - better management of run manager processes etc.

+
    +
  1. +

    +adjutant queries tasks table for next action [Migrate into mtutil] +

    +
      +
    1. +

      +Task table used for tracking runner process [Replaced by mtutil] +

      +
    2. +
    3. +

      +Task table used for jobs to run [Replaced by mtutil] +

      +
    4. +
    5. +

      +Task table used for queueing runner actions (remove runs, + cleanRunExecute, etc) [Replaced by mtutil] +

      +
    6. +
    +
  2. +
  3. +

    +adjutant (server/task dispatch/execution manager) +

    +
  4. +
+

Stale propagation

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

Bin list

+
    +
  1. +

    +Rerun step and or subsequent steps from gui [DONE?] +

    +
  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. +
  15. +

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

    +
  16. +
  17. +

    +megatest.config setup entries for: +

    +
      +
    1. +

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

      +
    2. +
    3. +

      +browser "konqueror %FNAME% +

      +
    4. +
    +
  18. +
  19. +

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

    +
  20. +
  21. +

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

    +
  22. +
  23. +

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

    +
  24. +
  25. +

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

    +
  26. +
  27. +

    +Refactor Run Summary view, currently very clumsy +

    +
  28. +
  29. +

    +Add option to show steps in Run Summary view +

    +
  30. +
  31. +

    +Refactor guis for resizeablity +

    +
  32. +
  33. +

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

    +
  34. +
  35. +

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

    +
  36. +
  37. +

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

    +
  38. +
  39. +

    +Tool tips +

    +
  40. +
  41. +

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

    +
  42. +
  43. +

    +Built in log viewer (partially implemented) +

    +
  44. +
  45. +

    +Refactor the test control panel + Help and documentation +

    +
  46. +
  47. +

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

    +
  48. +
  49. +

    +Online help in the gui + Streamlined install +

    +
  50. +
  51. +

    +Deployed or static build +

    +
  52. +
  53. +

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

    +
  54. +
  55. +

    +Server side run launching +

    +
  56. +
  57. +

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

    +
  58. +
  59. +

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

    +
  60. +
  61. +

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

    +
  62. +
  63. +

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

    +
  64. +
  65. +

    +Windows version +

    +
  66. +
+

Installation

Dependencies

Chicken scheme and a number of "eggs" are required for building -Megatest. See the script installall.sh in the utils directory of the -source distribution for an automated way to install everything -needed for building Megatest on Linux.

+Megatest. In the v1.66 and beyond assistance to create the build +system is built into the Makefile.

+
+
Installation steps (overview)
+
+
./configure
+make chicken
+setup.sh make -j install
+
+

Or install the needed build system manually:

+
    +
  1. +

    +Chicken scheme from http://call-cc.org +

    +
  2. +
  3. +

    +IUP from http://webserver2.tecgraf.puc-rio.br/iup/ +

    +
  4. +
  5. +

    +CD from http://webserver2.tecgraf.puc-rio.br/cd/ +

    +
  6. +
  7. +

    +IM from https://webserver2.tecgraf.puc-rio.br/im/ +

    +
  8. +
  9. +

    +ffcall from http://webserver2.tecgraf.puc-rio.br/iup/ +

    +
  10. +
  11. +

    +Nanomsg from https://nanomsg.org/ (NOTE: Plan is to eliminate nanomsg dependency). +

    +
  12. +
  13. +

    +Needed eggs (look at the eggs lists in the Makefile) +

    +
  14. +
+

Then follow these steps:

+
+
Installation steps (self-built chicken scheme build system)
+
+
./configure
+make -j install
+

Getting Started

@@ -2374,13 +2906,19 @@ megatest.config. This can be used to allocate disks on a per-test or per item basis.

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)

+

If test is FAIL and previous test in run with same MT_TARGET is WAIVED +or if the test/itempath is listed under the matching target in the +waivers roll forward file (see below for file spec) 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
@@ -2395,10 +2933,36 @@
 # diff   diff %file1% %file2%
 
 # This builtin rule is applied if a <waivername>.logpro file exists
 # logpro diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html
+
+

Waiver roll-forward files

+

To transfer waivers from one Megatest area to another it is possible +to dump waivers into a file and reference that file in another area.

+
+
Dumping the waivers
+
+
megatest -list-waivers -runname %-a > mywaivers.dat
+
+
+
Referencing the saved waivers
+
+
# In megatest.config, all files listed will be loaded - recomended to use
+# variables to select directorys to minimize what gets loaded.
+[setup]
+waivers-dirs /path/to/waiver/files /another/path/to/waiver/files
+
+
+
Waiver files format
+
+
[the/target/here]
+# comments are fine
+testname1/itempath A comment about why it was waived
+testname2          A comment for a non-itemized test
+
+

Ezsteps

Example ezsteps with logpro rules
@@ -2837,364 +3401,10 @@
server.png
- -
-

Road Map

-
-

Note 1: This road-map continues to evolve and subject to change without notice.

-
-

Here is a smattering of ideas for Megatest 2.0

-
    -
  1. -

    -Add variable $MT_RUNPATH = $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME -

    -
  2. -
-
-
-
[db]
-api legacy|new
-
-
    -
  1. -

    -One big lesson from the 1.63-1.65 generation was that the main.db, 1.db … model was really good at scaling. I’d like to combine that model with the current also-very-good model. Obviously this is a disruptive change. I think making the old model the default and the new model an option for at least one generation would be fair. -

    -
  2. -
  3. -

    -Rigorous megatest.config and runconfig.config caching. -

    -
      -
    1. -

      -Cache the configs in $MT_RUNPATH -

      -
    2. -
    3. -

      -Following invocations of –run, -rerun* will calculate the new config but only overwrite the cached file IF changed -

      -
    4. -
    -
  4. -
  5. -

    -If the cached file changes ALL existing tests go from COMPLETED → STALE, I’m not sure what to do about RUNNING tests -

    -
  6. -
  7. -

    -!VARS in runconfigs are not exported to the environment. They are accessed via rget as if the ! was not there. -

    -
  8. -
  9. -

    -Per test copy commands (crude example below is not correct). -

    -
  10. -
-
-
-
[testcopy]
-%/iind% unison SRC DEST
-% cp –r SRC DEST
-
-
    -
  1. -

    -Test management via pkts (optional?) -

    -
      -
    1. -

      -Control pkt types: run, kill, rerunclean, clean, archive, status? -

      -
    2. -
    3. -

      -Status pkt types: ack, step, status_change -

      -
    4. -
    -
  2. -
  3. -

    -Add nanomsg as a transport option -. -

    -
  4. -
-
-
-

RFC M01: Add ability to move runs to other Areas

-

Purpose: allow shrinking megatest.db data by moving runs to an alternate - Megatest area with same keys.

-

Method: extend db sync to take a different megatest area as a destination.

-

Design:

-
    -
  1. -

    -add param -destination [area|path]. when specified runs are copied to new - area and removed from local db. -

    -
  2. -
  3. -

    -the data move would involve these steps -

    -
      -
    1. -

      -copy the run data to destination area megatest.db -

      -
    2. -
    3. -

      -mark the run records as deleted, do not remove the run data on disk -

      -
    4. -
    -
  4. -
  5. -

    -accessing the data would be by running dashboard in the satellite area -

    -
  6. -
  7. -

    -future versions of Megatest dashboard should support displaying areas in a - merged way. -

    -
  8. -
  9. -

    -some new controls would be supported in the config -

    -
      -
    1. -

      -[setup] ⇒ allow-runs [no|yes] ⇐= used to disallow runs -

      -
    2. -
    3. -

      -[setup] ⇒ auto-migrate=[areaname|path] ⇐= used to automatically - migrate data to a satellite area. -

      -
    4. -
    -
  10. -
-

Branch: This work is taking place on branch v1.65-reduce-records

-
-
-

RFC M02: Move data into completed-runs.db

-

Purpose: shrink megatest.db data to enable lower load and higher performance.

-

Method: add a completed-runs.db and automatically move runs data from megatest.db to that db

-

Design:

-
    -
  1. -

    -completed-runs.db is a full megatest database with complete schema -

    -
  2. -
  3. -

    -the data move would involve these steps -

    -
      -
    1. -

      -copy the run data to completed-runs.db -

      -
    2. -
    3. -

      -remove the run data, first from /tmp/…/megatest.db and /tmp/…/megatest_ref.db, followed by megatest.db -

      -
    4. -
    -
  4. -
  5. -

    -accessing the data would be unchanged for most operations. -

    -
  6. -
  7. -

    -a mode -full-db will be added which when specified would attach the completed-runs.db to megatest.db before doing the query -

    -
  8. -
  9. -

    -mechanisms for moving runs to/from the megatest.db would be added -

    -
      -
    1. -

      --reduce-records ⇒ move runs to completed-runs.db -

      -
    2. -
    3. -

      --restore-records ⇒ move runs from completed-runs.db to megatest.db -

      -
    4. -
    -
  10. -
-

Branch: This work is taking place on branch v1.65-reduce-records

-
-
-

RFC M03: Automatic homehost migrations

-

Purpose: Automatically migrate homehost.

-

Method: Check that there are no tests running, launched or remotehoststart in past ½ hour then if not on homehost migrate the db to current host

-

Design:

-
    -
  1. -

    -Check that the system is quiescent, i.e. that there are no runs in flight or recently run -

    -
  2. -
  3. -

    -Create a lock -

    -
  4. -
  5. -

    -Migrate the /tmp cache db to the current host -

    -
  6. -
  7. -

    -Update the .homehost file -

    -
  8. -
  9. -

    -Remove the lock -

    -
  10. -
-

Branch: This work not yet started

-
-
-

Architecture Refactor

-
-

Goals

-
    -
  1. -

    -Reduce load on the file system. Sqlite3 files on network filesystem can be - a burden. [DONE] -

    -
  2. -
  3. -

    -Reduce number of servers and frequency of start/stop. This is mostly an - issue of clutter but also a reduction in "moving parts". [DONE] -

    -
  4. -
  5. -

    -Coalesce activities to a single home host where possible. Give the user - feedback that they have started the dashboard on a host other than the - home host. [DONE] -

    -
  6. -
  7. -

    -Reduce number of processes involved in managing running tests. -

    -
  8. -
-
-
-

Changes Needed

-
    -
  1. -

    -ACID compliant db will be on /tmp and synced to megatest.db with a five - second max delay. [DONE] -

    -
  2. -
  3. -

    -Read/writes to db for processes on homehost will go direct to /tmp - megatest.db file. [DONE] -

    -
  4. -
  5. -

    -Read/wites fron non-homehost processes will go through one server. Bulk - reads (e.g. for dashboard or list-runs) will be cached on the current host - in /tmp and synced from the home megatest.db in the testsuite area. [DONE] -

    -
  6. -
  7. -

    -Db syncs rely on the target db file timestame minus some margin. [DONE] -

    -
  8. -
  9. -

    -Since bulk reads do not use the server we can switch to simple RPC for the - network transport. [DONE] -

    -
  10. -
  11. -

    -Test running manager process extended to manage multiple running tests. -

    -
  12. -
-
-
-
-

Current Items

-
-

ww05 - migrate to inmem-db

-
    -
  1. -

    -Switch to inmem db with fast sync to on disk db’s [DONE] -

    -
  2. -
  3. -

    -Server polls tasks table for next action -

    -
      -
    1. -

      -Task table used for tracking runner process [Replaced by mtutil] -

      -
    2. -
    3. -

      -Task table used for jobs to run [Replaced by mtutil] -

      -
    4. -
    5. -

      -Task table used for queueing runner actions (remove runs, - cleanRunExecute, etc) [Replaced by mtutil] -

      -
    6. -
    -
  4. -
-

shifting, note that the preceding blank line is needed.

-
-
-

Index

@@ -3201,12 +3411,12 @@

Index: docs/manual/megatest_manual.txt ================================================================== --- docs/manual/megatest_manual.txt +++ docs/manual/megatest_manual.txt @@ -1,9 +1,9 @@ The Megatest Users Manual ========================= Matt Welland -v1.0, April 2012 +v1.5, June 2020 :doctype: book [preface] Preface @@ -11,11 +11,11 @@ This book is organised as three sub-books; getting started, writing tests and reference. .License ---------------------------- - Copyright 2006-2017, Matthew Welland. + Copyright 2006-2020, Matthew Welland. This document is part of Megatest. Megatest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,11 +38,11 @@ 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. I thought a single open source tool, flexible enough to meet the needs -of any team doing continuous integrating and or running a complex +of any team doing continuous integration and or running a complex suite of tests for release qualification would solve some problems for me and for others. -- Matt Welland, original author of the Megatest tool suite. @@ -100,10 +100,12 @@ sqlite3 database. Megatest has been used with the Intel Netbatch and lsf (also known as openlava) batch systems and it should be straightforward to use it with other similar systems. include::overview.txt[] + +include::plan.txt[] include::installation.txt[] include::getting_started.txt[] @@ -110,26 +112,26 @@ include::study_plan.txt[] // :leveloffset: 0 include::writing_tests.txt[] + include::howto.txt[] include::reference.txt[] - Megatest Internals ------------------ ["graphviz", "server.png"] ---------------------------------------------------------------------- include::server.dot[] ---------------------------------------------------------------------- -include::plan.txt[] +// include::plan.txt[] // to allow the getting_started.txt to be a stand-alone document use level -shifting, note that the preceding blank line is needed. +// shifting, note that the preceding blank line is needed. // :leveloffset: 2 // [appendix] // Example Appendix Index: docs/manual/plan.txt ================================================================== --- docs/manual/plan.txt +++ docs/manual/plan.txt @@ -1,232 +1,163 @@ -Road Map --------- - -// This file is part of Megatest. -// -// Megatest is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Megatest is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Megatest. If not, see . - -// Copyright 2006-2012, Matthew Welland. - -Note 1: This road-map continues to evolve and subject to change without notice. - -Here is a smattering of ideas for Megatest 2.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -. Add variable $MT_RUNPATH = $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME ----------------- -[db] -api legacy|new ----------------- -. One big lesson from the 1.63-1.65 generation was that the main.db, 1.db … model was really good at scaling. I’d like to combine that model with the current also-very-good model. Obviously this is a disruptive change. I think making the old model the default and the new model an option for at least one generation would be fair. -. Rigorous megatest.config and runconfig.config caching. -.. Cache the configs in $MT_RUNPATH -.. Following invocations of –run, -rerun* will calculate the new config but only overwrite the cached file IF changed -. If the cached file changes ALL existing tests go from COMPLETED -> STALE, I’m not sure what to do about RUNNING tests -. !VARS in runconfigs are not exported to the environment. They are accessed via rget as if the ! was not there. -. Per test copy commands (crude example below is not correct). ----------------- -[testcopy] -%/iind% unison SRC DEST -% cp –r SRC DEST ----------------- -. Test management via pkts (optional?) -.. Control pkt types: run, kill, rerunclean, clean, archive, status? -.. Status pkt types: ack, step, status_change -. Add nanomsg as a transport option -. - -RFC M01: Add ability to move runs to other Areas -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -*Purpose*: allow shrinking megatest.db data by moving runs to an alternate - Megatest area with same keys. - -*Method*: extend db sync to take a different megatest area as a destination. - -*Design*: - -. add param -destination [area|path]. when specified runs are copied to new - area and removed from local db. -. the data move would involve these steps -.. copy the run data to destination area megatest.db -.. mark the run records as deleted, do not remove the run data on disk -. accessing the data would be by running dashboard in the satellite area -. future versions of Megatest dashboard should support displaying areas in a - merged way. -. some new controls would be supported in the config -.. [setup] => allow-runs [no|yes] <== used to disallow runs -.. [setup] => auto-migrate=[areaname|path] <== used to automatically - migrate data to a satellite area. - -*Branch*: This work is taking place on branch v1.65-reduce-records - -RFC M02: Move data into completed-runs.db -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -*Purpose*: shrink megatest.db data to enable lower load and higher performance. - -*Method*: add a completed-runs.db and automatically move runs data from megatest.db to that db - -*Design*: - -. completed-runs.db is a full megatest database with complete schema -. the data move would involve these steps -.. copy the run data to completed-runs.db -.. remove the run data, first from /tmp/…/megatest.db and /tmp/…/megatest_ref.db, followed by megatest.db -. accessing the data would be unchanged for most operations. -. a mode -full-db will be added which when specified would attach the completed-runs.db to megatest.db before doing the query -. mechanisms for moving runs to/from the megatest.db would be added -.. -reduce-records => move runs to completed-runs.db -.. -restore-records => move runs from completed-runs.db to megatest.db - -*Branch*: This work is taking place on branch v1.65-reduce-records - -RFC M03: Automatic homehost migrations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -*Purpose*: Automatically migrate homehost. - -*Method*: Check that there are no tests running, launched or remotehoststart in past ½ hour then if not on homehost migrate the db to current host - -*Design*: - -. Check that the system is quiescent, i.e. that there are no runs in flight or recently run -. Create a lock -. Migrate the /tmp cache db to the current host -. Update the .homehost file -. Remove the lock - -*Branch*: This work not yet started - -Architecture Refactor -~~~~~~~~~~~~~~~~~~~~~ - -Goals -^^^^^ - -. Reduce load on the file system. Sqlite3 files on network filesystem can be - a burden. [green]#[DONE]# -. Reduce number of servers and frequency of start/stop. This is mostly an - issue of clutter but also a reduction in "moving parts". [green]#[DONE]# -. Coalesce activities to a single home host where possible. Give the user - feedback that they have started the dashboard on a host other than the - home host. [green]#[DONE]# -. Reduce number of processes involved in managing running tests. - -Changes Needed -^^^^^^^^^^^^^^ - -. ACID compliant db will be on /tmp and synced to megatest.db with a five - second max delay. [green]#[DONE]# -. Read/writes to db for processes on homehost will go direct to /tmp - megatest.db file. [green]#[DONE]# -. Read/wites fron non-homehost processes will go through one server. Bulk - reads (e.g. for dashboard or list-runs) will be cached on the current host - in /tmp and synced from the home megatest.db in the testsuite area. [green]#[DONE]# -. Db syncs rely on the target db file timestame minus some margin. [green]#[DONE]# -. Since bulk reads do not use the server we can switch to simple RPC for the - network transport. [green]#[DONE]# -. Test running manager process extended to manage multiple running tests. - -Current Items -~~~~~~~~~~~~~ - -ww05 - migrate to inmem-db -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -. Switch to inmem db with fast sync to on disk db's [green]#[DONE]# -. Server polls tasks table for next action -.. Task table used for tracking runner process [red]#[Replaced by mtutil]# -.. Task table used for jobs to run [red]#[Replaced by mtutil]# -.. Task table used for queueing runner actions (remove runs, - cleanRunExecute, etc) [red]#[Replaced by mtutil#] - - -// 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 +// This file is part of Megatest. +// +// Megatest is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Megatest is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Megatest. If not, see . + +// Copyright 2006-2020, Matthew Welland. + +TODO / Road Map +--------------- + +Note: This road-map is a wish list and not a formal plan. Items are in +rough priority but are subject to change. Development is driven by +user requests, developer "itch" and bug reports. Please contact +matt@kiatoa.com with requests or bug reports. Requests from inside +Intel generally take priority. + +Dashboard and runs + +. Multi-area dashboard view + +Tests Support + +. Add variable $MT_RUNPATH = $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME +. Improve [script], especially indent handling + +Scalability + +. Overflow database methodology - combine the best of the v1.63 + multi-db approach and the current db-in-tmp approach (currently + slowness can be seen when number of tests in a db goes over 50-100k, + with the overflow db it will be able to handle 1000's of runs with + 50-100k tests per run). High priority - goal is to complete this by + 20Q3. + +Mtutils/CI + +. Enable mtutil calls from dashboard (for remote control) +. Logs browser (esp. for surfacing mtutil related activities) +. Embed ftfplan for distributed automation, completed activities trigger QA runs which trigger deployment etc. +. Jenkins junit XML support [DONE] +. Add output flushing in teamcity support + +Build system + +. ./configure => ubuntu, sles11, sles12, rh7 [WIP] +. Switch to using simple runs query everywhere +. Add end_time to runs and add a rollup call that sets state, status and end_time + +Code refactoring/quality/performance + +. Switch to scsh-process pipeline management for job execution/control +. Use call-with-environment-variables where possible. + +Migration to inmem db and or overflow db + +. Re-work the dbstruct data structure? +.. [ run-id.db inmemdb last-mod last-read last-sync inuse ] + +Some ideas for Megatest 2.0 + +. Aggressive megatest.config and runconfig.config caching. +.. Cache the configs in $MT_RUNPATH +.. Following invocations of –run, -rerun* will calculate the new config but only overwrite the cached file IF changed +. If the cached file changes ALL existing tests go from COMPLETED -> STALE, I’m not sure what to do about RUNNING tests +. !VARS in runconfigs are not exported to the environment. They are accessed via rget as if the ! was not there. +. Per test copy commands (example is incomplete). +---------------- +[testcopy] +%/iind% unison SRC DEST +% cp –r SRC DEST +---------------- + +Add ability to move runs to other Areas (overlaps with overflow db system) + +. allow shrinking megatest.db data by moving runs to an alternate + Megatest area with same keys. +. add param -destination [area|path]. when specified runs are copied to new + area and removed from local db. +. the data move would involve these steps +.. copy the run data to destination area megatest.db +.. mark the run records as deleted, do not remove the run data on disk +. accessing the data would be by running dashboard in the satellite area +. future versions of Megatest dashboard should support displaying areas in a + merged way. +. some new controls would be supported in the config +.. [setup] => allow-runs [no|yes] <== used to disallow runs +.. [setup] => auto-migrate=[areaname|path] <== used to automatically + migrate data to a satellite area. + +Eliminate ties to homehost (part of overflow db system) + +. Server creates captain pkt +. Create a lock in the db +. Relinquish db when done + +Tasks - better management of run manager processes etc. + +. adjutant queries tasks table for next action [red]#[Migrate into mtutil]# +.. Task table used for tracking runner process [red]#[Replaced by mtutil]# +.. Task table used for jobs to run [red]#[Replaced by mtutil]# +.. Task table used for queueing runner actions (remove runs, + cleanRunExecute, etc) [red]#[Replaced by mtutil#] +. adjutant (server/task dispatch/execution manager) + +Stale propagation + + . 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?) + +Bin list + + . Rerun step and or subsequent steps from gui [DONE?] + . 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 + + . rest 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% + + . 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 + . 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 + . 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 or static build + . Added option to compile IUP (needed for VMs) + . Server side run launching + . 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). + . Gui panels for editing megatest.config and runconfigs.config + . Fully isolated tests (no use of NFS to see regression area files) + . Windows version Index: docs/manual/reference.txt ================================================================== --- docs/manual/reference.txt +++ docs/manual/reference.txt @@ -627,14 +627,20 @@ basis. 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 +If test is FAIL and previous test in run with same MT_TARGET is WAIVED +or if the test/itempath is listed under the matching target in the +waivers roll forward file (see below for file spec) 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) +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 @@ -650,10 +656,37 @@ # This builtin rule is applied if a .logpro file exists # logpro diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html ----------------- +Waiver roll-forward files +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To transfer waivers from one Megatest area to another it is possible +to dump waivers into a file and reference that file in another area. + +.Dumping the waivers +--------------------------- +megatest -list-waivers -runname %-a > mywaivers.dat +--------------------------- + +.Referencing the saved waivers +--------------------------- +# In megatest.config, all files listed will be loaded - recomended to use +# variables to select directorys to minimize what gets loaded. +[setup] +waivers-dirs /path/to/waiver/files /another/path/to/waiver/files +--------------------------- + +.Waiver files format +--------------------------- +[the/target/here] +# comments are fine +testname1/itempath A comment about why it was waived +testname2 A comment for a non-itemized test +--------------------------- + Ezsteps ~~~~~~~ .Example ezsteps with logpro rules ----------------- Index: docs/manual/server.png ================================================================== --- docs/manual/server.png +++ docs/manual/server.png cannot compute difference between binary files ADDED docs/manual/subrun-opt-stuff.fig Index: docs/manual/subrun-opt-stuff.fig ================================================================== --- /dev/null +++ docs/manual/subrun-opt-stuff.fig @@ -0,0 +1,128 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 150 5475 1650 9675 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 150 5475 1650 5475 1650 9675 150 9675 150 5475 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 225 5550 1575 5550 1575 6075 225 6075 225 5550 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 225 6150 1575 6150 1575 6675 225 6675 225 6150 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 225 6750 1575 6750 1575 7275 225 7275 225 6750 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 225 7350 1575 7350 1575 7875 225 7875 225 7350 +-6 +6 3900 5550 5400 9750 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 3900 5550 5400 5550 5400 9750 3900 9750 3900 5550 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 3975 5625 5325 5625 5325 6150 3975 6150 3975 5625 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 3975 6225 5325 6225 5325 6750 3975 6750 3975 6225 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 3975 6825 5325 6825 5325 7350 3975 7350 3975 6825 +2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 3975 7425 5325 7425 5325 7950 3975 7950 3975 7425 +-6 +6 8325 5700 9525 9825 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8325 6000 9525 6000 9525 6825 8325 6825 8325 6000 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8325 6900 9525 6900 9525 7725 8325 7725 8325 6900 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8325 7800 9525 7800 9525 8625 8325 8625 8325 7800 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8325 8700 9525 8700 9525 9525 8325 9525 8325 8700 +4 0 0 50 -1 0 12 0.0000 4 120 405 8475 5850 tests\001 +4 0 0 50 -1 0 12 0.0000 4 165 600 8400 6375 startup\001 +4 0 0 50 -1 0 12 0.0000 4 195 375 8400 7275 opt1\001 +4 0 0 50 -1 0 12 0.0000 4 195 375 8400 8025 opt2\001 +4 0 0 50 -1 0 12 0.0000 4 195 585 8400 9075 opt1v2\001 +4 0 0 50 -1 0 12 0.0000 4 15 180 8775 9825 ...\001 +-6 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 4800 450 6000 450 6000 1275 4800 1275 4800 450 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1050 2100 2250 2100 2250 2925 1050 2925 1050 2100 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 2925 2100 4125 2100 4125 2925 2925 2925 2925 2100 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 4950 2100 6150 2100 6150 2925 4950 2925 4950 2100 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 7200 2100 8400 2100 8400 2925 7200 2925 7200 2100 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 9375 2100 10575 2100 10575 2925 9375 2925 9375 2100 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 2025 4050 3225 4050 3225 4875 2025 4875 2025 4050 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 6525 3975 7725 3975 7725 4800 6525 4800 6525 3975 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5400 1275 1500 2100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5325 1275 3525 2100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5325 1275 5475 2100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5250 1275 7800 2100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5325 1275 9900 2100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1650 2925 2550 4050 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3525 2925 2550 4050 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3525 2925 7050 3975 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5550 2925 6975 3975 +2 2 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 + 750 1650 10875 1650 10875 3450 750 3450 750 1650 +2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 1050 2700 450 2700 450 5550 +2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 4125 2700 4650 2700 4650 5550 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 2100 5475 3300 5475 3300 8700 2100 8700 2100 5475 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 2175 6000 3225 6000 3225 6525 2175 6525 2175 6000 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1500 6375 2325 6300 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4200 6525 3000 6225 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7800 2925 7050 3975 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 9975 2925 7125 3900 +4 0 0 50 -1 0 12 0.0000 4 165 600 4875 975 startup\001 +4 0 0 50 -1 0 12 0.0000 4 15 180 5325 2550 ...\001 +4 0 0 50 -1 0 12 0.0000 4 195 2100 900 675 p1278/2/cpdk_r0.5/none\001 +4 0 0 50 -1 0 12 0.0000 4 150 675 150 2475 subruns\001 +4 0 0 50 -1 0 12 0.0000 4 195 585 2175 4500 opt1v2\001 +4 0 0 50 -1 0 12 0.0000 4 195 375 1200 2625 opt1\001 +4 0 0 50 -1 0 12 0.0000 4 195 375 3150 2550 opt2\001 +4 0 0 50 -1 0 12 0.0000 4 150 2100 3075 150 SUBRUN for Multistack\001 +4 0 0 50 -1 0 12 0.0000 4 150 225 300 6375 ftc\001 +4 0 0 50 -1 0 12 0.0000 4 150 225 4050 6450 ftc\001 +4 0 0 50 -1 0 12 0.0000 4 195 2220 600 5250 p1278/2/cpdk_r0.5/x-opt1\001 +4 0 0 50 -1 0 12 0.0000 4 195 2220 4800 5325 p1278/2/cpdk_r0.5/y-opt2\001 ADDED example2/rx.v Index: example2/rx.v ================================================================== --- /dev/null +++ example2/rx.v @@ -0,0 +1,649 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: rxuartlite.v +// +// Project: wbuart32, a full featured UART with simulator +// +// Purpose: Receive and decode inputs from a single UART line. +// +// +// To interface with this module, connect it to your system clock, +// and a UART input. Set the parameter to the number of clocks per +// baud. When data becomes available, the o_wr line will be asserted +// for one clock cycle. +// +// This interface only handles 8N1 serial port communications. It does +// not handle the break, parity, or frame error conditions. +// +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015-2020, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory. Run make with no +// target there if the PDF file isn't present.) If not, see +// for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// +`define RXUL_BIT_ZERO 4'h0 +`define RXUL_BIT_ONE 4'h1 +`define RXUL_BIT_TWO 4'h2 +`define RXUL_BIT_THREE 4'h3 +`define RXUL_BIT_FOUR 4'h4 +`define RXUL_BIT_FIVE 4'h5 +`define RXUL_BIT_SIX 4'h6 +`define RXUL_BIT_SEVEN 4'h7 +`define RXUL_STOP 4'h8 +`define RXUL_WAIT 4'h9 +`define RXUL_IDLE 4'hf + +module rxuartlite(i_clk, i_uart_rx, o_wr, o_data); + parameter TIMER_BITS = 10; +`ifdef FORMAL + parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 16; // Necessary for formal proof +`else + parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 868; // 115200 MBaud at 100MHz +`endif + localparam TB = TIMER_BITS; + input wire i_clk; + input wire i_uart_rx; + output reg o_wr; + output reg [7:0] o_data; + + + wire [(TB-1):0] half_baud; + reg [3:0] state; + + assign half_baud = { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] }; + reg [(TB-1):0] baud_counter; + reg zero_baud_counter; + + + // Since this is an asynchronous receiver, we need to register our + // input a couple of clocks over to avoid any problems with + // metastability. We do that here, and then ignore all but the + // ck_uart wire. + reg q_uart, qq_uart, ck_uart; + initial q_uart = 1'b1; + initial qq_uart = 1'b1; + initial ck_uart = 1'b1; + always @(posedge i_clk) + { ck_uart, qq_uart, q_uart } <= { qq_uart, q_uart, i_uart_rx }; + + // Keep track of the number of clocks since the last change. + // + // This is used to determine if we are in either a break or an idle + // condition, as discussed further below. + reg [(TB-1):0] chg_counter; + initial chg_counter = {(TB){1'b1}}; + always @(posedge i_clk) + if (qq_uart != ck_uart) + chg_counter <= 0; + else if (chg_counter != { (TB){1'b1} }) + chg_counter <= chg_counter + 1; + + // Are we in the middle of a baud iterval? Specifically, are we + // in the middle of a start bit? Set this to high if so. We'll use + // this within our state machine to transition out of the IDLE + // state. + reg half_baud_time; + initial half_baud_time = 0; + always @(posedge i_clk) + half_baud_time <= (!ck_uart)&&(chg_counter >= half_baud-1'b1-1'b1); + + + initial state = `RXUL_IDLE; + always @(posedge i_clk) + if (state == `RXUL_IDLE) + begin // Idle state, independent of baud counter + // By default, just stay in the IDLE state + state <= `RXUL_IDLE; + if ((!ck_uart)&&(half_baud_time)) + // UNLESS: We are in the center of a valid + // start bit + state <= `RXUL_BIT_ZERO; + end else if ((state >= `RXUL_WAIT)&&(ck_uart)) + state <= `RXUL_IDLE; + else if (zero_baud_counter) + begin + if (state <= `RXUL_STOP) + // Data arrives least significant bit first. + // By the time this is clocked in, it's what + // you'll have. + state <= state + 1; + end + + // Data bit capture logic. + // + // This is drastically simplified from the state machine above, based + // upon: 1) it doesn't matter what it is until the end of a captured + // byte, and 2) the data register will flush itself of any invalid + // data in all other cases. Hence, let's keep it real simple. + reg [7:0] data_reg; + always @(posedge i_clk) + if ((zero_baud_counter)&&(state != `RXUL_STOP)) + data_reg <= { qq_uart, data_reg[7:1] }; + + // Our data bit logic doesn't need nearly the complexity of all that + // work above. Indeed, we only need to know if we are at the end of + // a stop bit, in which case we copy the data_reg into our output + // data register, o_data, and tell others (for one clock) that data is + // available. + // + initial o_wr = 1'b0; + initial o_data = 8'h00; + always @(posedge i_clk) + if ((zero_baud_counter)&&(state == `RXUL_STOP)&&(ck_uart)) + begin + o_wr <= 1'b1; + o_data <= data_reg; + end else + o_wr <= 1'b0; + + // The baud counter + // + // This is used as a "clock divider" if you will, but the clock needs + // to be reset before any byte can be decoded. In all other respects, + // we set ourselves up for CLOCKS_PER_BAUD counts between baud + // intervals. + initial baud_counter = 0; + always @(posedge i_clk) + if (((state==`RXUL_IDLE))&&(!ck_uart)&&(half_baud_time)) + baud_counter <= CLOCKS_PER_BAUD-1'b1; + else if (state == `RXUL_WAIT) + baud_counter <= 0; + else if ((zero_baud_counter)&&(state < `RXUL_STOP)) + baud_counter <= CLOCKS_PER_BAUD-1'b1; + else if (!zero_baud_counter) + baud_counter <= baud_counter-1'b1; + + // zero_baud_counter + // + // Rather than testing whether or not (baud_counter == 0) within our + // (already too complicated) state transition tables, we use + // zero_baud_counter to pre-charge that test on the clock + // before--cleaning up some otherwise difficult timing dependencies. + initial zero_baud_counter = 1'b1; + always @(posedge i_clk) + if ((state == `RXUL_IDLE)&&(!ck_uart)&&(half_baud_time)) + zero_baud_counter <= 1'b0; + else if (state == `RXUL_WAIT) + zero_baud_counter <= 1'b1; + else if ((zero_baud_counter)&&(state < `RXUL_STOP)) + zero_baud_counter <= 1'b0; + else if (baud_counter == 1) + zero_baud_counter <= 1'b1; + +`ifdef FORMAL +`define FORMAL_VERILATOR +`else +`ifdef VERILATOR +`define FORMAL_VERILATOR +`endif +`endif + +`ifdef FORMAL +`define ASSUME assume +`define ASSERT assert +`ifdef VERIFIC + (* gclk *) wire gbl_clk; + global clocking @(posedge gbl_clk); endclocking +`endif + + + localparam F_CKRES = 10; + + (* anyseq *) wire f_tx_start; + (* anyconst *) wire [(F_CKRES-1):0] f_tx_step; + reg f_tx_zclk; + reg [(TB-1):0] f_tx_timer; + wire [7:0] f_rx_newdata; + reg [(TB-1):0] f_tx_baud; + wire f_tx_zbaud; + + wire [(TB-1):0] f_max_baud_difference; + reg [(TB-1):0] f_baud_difference; + reg [(TB+3):0] f_tx_count, f_rx_count; + (* anyseq *) wire [7:0] f_tx_data; + + + + wire f_txclk; + reg [1:0] f_rx_clock; + reg [(F_CKRES-1):0] f_tx_clock; + reg f_past_valid, f_past_valid_tx; + + initial f_past_valid = 1'b0; + always @(posedge i_clk) + f_past_valid <= 1'b1; + + initial f_rx_clock = 3'h0; + always @($global_clock) + f_rx_clock <= f_rx_clock + 1'b1; + + always @(*) + assume(i_clk == f_rx_clock[1]); + /////////////////////////////////////////////////////////// + // + // + // Generate a transmitted signal + // + // + /////////////////////////////////////////////////////////// + // First, calculate the transmit clock + localparam [(F_CKRES-1):0] F_MIDSTEP = { 2'b01, {(F_CKRES-2){1'b0}} }; + // + // Need to allow us to slip by half a baud clock over 10 baud intervals + // + // (F_STEP / (2^F_CKRES)) * (CLOCKS_PER_BAUD)*10 < CLOCKS_PER_BAUD/2 + // F_STEP * 2 * 10 < 2^F_CKRES + localparam [(F_CKRES-1):0] F_HALFSTEP= F_MIDSTEP/32; + localparam [(F_CKRES-1):0] F_MINSTEP = F_MIDSTEP - F_HALFSTEP + 1; + localparam [(F_CKRES-1):0] F_MAXSTEP = F_MIDSTEP + F_HALFSTEP - 1; + initial assert(F_MINSTEP <= F_MIDSTEP); + initial assert(F_MIDSTEP <= F_MAXSTEP); + // assume((f_tx_step >= F_MINSTEP)&&(f_tx_step <= F_MAXSTEP)); + // + // + always @(*) assume((f_tx_step == F_MINSTEP) + ||(f_tx_step == F_MIDSTEP) + ||(f_tx_step == F_MAXSTEP)); + always @($global_clock) + f_tx_clock <= f_tx_clock + f_tx_step; + assign f_txclk = f_tx_clock[F_CKRES-1]; + // + initial f_past_valid_tx = 1'b0; + always @(posedge f_txclk) + f_past_valid_tx <= 1'b1; + initial assume(i_uart_rx); + ////////////////////////////////////////////// + // + // + // Build a simulated transmitter + // + // + ////////////////////////////////////////////// + // + // First, the simulated timing generator + // parameter TIMER_BITS = 10; + // parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 868; + // localparam TB = TIMER_BITS; + always @(*) + if (f_tx_busy) + assume(!f_tx_start); + initial f_tx_baud = 0; + always @(posedge f_txclk) + if ((f_tx_zbaud)&&((f_tx_busy)||(f_tx_start))) + f_tx_baud <= CLOCKS_PER_BAUD-1'b1; + else if (!f_tx_zbaud) + f_tx_baud <= f_tx_baud - 1'b1; + always @(*) + `ASSERT(f_tx_baud < CLOCKS_PER_BAUD); + always @(*) + if (!f_tx_busy) + `ASSERT(f_tx_baud == 0); + assign f_tx_zbaud = (f_tx_baud == 0); + // But only if we aren't busy + initial assume(f_tx_data == 0); + always @(posedge f_txclk) + if ((!f_tx_zbaud)||(f_tx_busy)||(!f_tx_start)) + assume(f_tx_data == $past(f_tx_data)); + // Force the data to change on a clock only + always @($global_clock) + if ((f_past_valid)&&(!$rose(f_txclk))) + assume($stable(f_tx_data)); + else if (f_tx_busy) + assume($stable(f_tx_data)); + // + always @($global_clock) + if ((!f_past_valid)||(!$rose(f_txclk))) + begin + assume($stable(f_tx_start)); + assume($stable(f_tx_data)); + end + // + // + // + reg [9:0] f_tx_reg; + reg f_tx_busy; + // Here's the transmitter itself (roughly) + initial f_tx_busy = 1'b0; + initial f_tx_reg = 0; + always @(posedge f_txclk) + if (!f_tx_zbaud) + begin + `ASSERT(f_tx_busy); + end else begin + f_tx_reg <= { 1'b0, f_tx_reg[9:1] }; + if (f_tx_start) + f_tx_reg <= { 1'b1, f_tx_data, 1'b0 }; + end + // Create a busy flag that we'll use + always @(*) + if (!f_tx_zbaud) + f_tx_busy <= 1'b1; + else if (|f_tx_reg) + f_tx_busy <= 1'b1; + else + f_tx_busy <= 1'b0; + // + // Tie the TX register to the TX data + always @(posedge f_txclk) + if (f_tx_reg[9]) + `ASSERT(f_tx_reg[8:0] == { f_tx_data, 1'b0 }); + else if (f_tx_reg[8]) + `ASSERT(f_tx_reg[7:0] == f_tx_data[7:0] ); + else if (f_tx_reg[7]) + `ASSERT(f_tx_reg[6:0] == f_tx_data[7:1] ); + else if (f_tx_reg[6]) + `ASSERT(f_tx_reg[5:0] == f_tx_data[7:2] ); + else if (f_tx_reg[5]) + `ASSERT(f_tx_reg[4:0] == f_tx_data[7:3] ); + else if (f_tx_reg[4]) + `ASSERT(f_tx_reg[3:0] == f_tx_data[7:4] ); + else if (f_tx_reg[3]) + `ASSERT(f_tx_reg[2:0] == f_tx_data[7:5] ); + else if (f_tx_reg[2]) + `ASSERT(f_tx_reg[1:0] == f_tx_data[7:6] ); + else if (f_tx_reg[1]) + `ASSERT(f_tx_reg[0] == f_tx_data[7]); + // Our counter since we start + initial f_tx_count = 0; + always @(posedge f_txclk) + if (!f_tx_busy) + f_tx_count <= 0; + else + f_tx_count <= f_tx_count + 1'b1; + always @(*) + if (f_tx_reg == 10'h0) + assume(i_uart_rx); + else + assume(i_uart_rx == f_tx_reg[0]); + // + // Make sure the absolute transmit clock timer matches our state + // + always @(posedge f_txclk) + if (!f_tx_busy) + begin + if ((!f_past_valid_tx)||(!$past(f_tx_busy))) + `ASSERT(f_tx_count == 0); + end else if (f_tx_reg[9]) + `ASSERT(f_tx_count == + CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[8]) + `ASSERT(f_tx_count == + 2 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[7]) + `ASSERT(f_tx_count == + 3 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[6]) + `ASSERT(f_tx_count == + 4 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[5]) + `ASSERT(f_tx_count == + 5 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[4]) + `ASSERT(f_tx_count == + 6 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[3]) + `ASSERT(f_tx_count == + 7 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[2]) + `ASSERT(f_tx_count == + 8 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[1]) + `ASSERT(f_tx_count == + 9 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else if (f_tx_reg[0]) + `ASSERT(f_tx_count == + 10 * CLOCKS_PER_BAUD -1 -f_tx_baud); + else + `ASSERT(f_tx_count == + 11 * CLOCKS_PER_BAUD -1 -f_tx_baud); + /////////////////////////////////////// + // + // Receiver + // + /////////////////////////////////////// + // + // Count RX clocks since the start of the first stop bit, measured in + // rx clocks + initial f_rx_count = 0; + always @(posedge i_clk) + if (state == `RXUL_IDLE) + f_rx_count = (!ck_uart) ? (chg_counter+2) : 0; + else + f_rx_count <= f_rx_count + 1'b1; + always @(posedge i_clk) + if (state == 0) + `ASSERT(f_rx_count + == half_baud + (CLOCKS_PER_BAUD-baud_counter)); + else if (state == 1) + `ASSERT(f_rx_count == half_baud + 2 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 2) + `ASSERT(f_rx_count == half_baud + 3 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 3) + `ASSERT(f_rx_count == half_baud + 4 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 4) + `ASSERT(f_rx_count == half_baud + 5 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 5) + `ASSERT(f_rx_count == half_baud + 6 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 6) + `ASSERT(f_rx_count == half_baud + 7 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 7) + `ASSERT(f_rx_count == half_baud + 8 * CLOCKS_PER_BAUD + - baud_counter); + else if (state == 8) + `ASSERT((f_rx_count == half_baud + 9 * CLOCKS_PER_BAUD + - baud_counter) + ||(f_rx_count == half_baud + 10 * CLOCKS_PER_BAUD + - baud_counter)); + always @(*) + `ASSERT( ((!zero_baud_counter) + &&(state == `RXUL_IDLE) + &&(baud_counter == 0)) + ||((zero_baud_counter)&&(baud_counter == 0)) + ||((!zero_baud_counter)&&(baud_counter != 0))); + always @(posedge i_clk) + if (!f_past_valid) + `ASSERT((state == `RXUL_IDLE)&&(baud_counter == 0) + &&(zero_baud_counter)); + always @(*) + begin + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h2); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h4); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h5); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h6); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h9); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'ha); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'hb); + `ASSERT({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'hd); + end + always @(posedge i_clk) + if ((f_past_valid)&&($past(state) >= `RXUL_WAIT)&&($past(ck_uart))) + `ASSERT(state == `RXUL_IDLE); + always @(posedge i_clk) + if ((f_past_valid)&&($past(state) >= `RXUL_WAIT) + &&(($past(state) != `RXUL_IDLE)||(state == `RXUL_IDLE))) + `ASSERT(zero_baud_counter); + // Calculate an absolute value of the difference between the two baud + // clocks + always @(posedge i_clk) + if ((f_past_valid)&&($past(state)==`RXUL_IDLE)&&(state == `RXUL_IDLE)) + begin + `ASSERT(($past(ck_uart)) + ||(chg_counter <= + { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] })); + end + always @(posedge f_txclk) + if (!f_past_valid_tx) + `ASSERT((state == `RXUL_IDLE)&&(baud_counter == 0) + &&(zero_baud_counter)&&(!f_tx_busy)); + wire [(TB+3):0] f_tx_count_two_clocks_ago; + assign f_tx_count_two_clocks_ago = f_tx_count - 2; + always @(*) + if (f_tx_count >= f_rx_count + 2) + f_baud_difference = f_tx_count_two_clocks_ago - f_rx_count; + else + f_baud_difference = f_rx_count - f_tx_count_two_clocks_ago; + localparam F_SYNC_DLY = 8; + reg [(TB+4+F_CKRES-1):0] f_sub_baud_difference; + reg [F_CKRES-1:0] ck_tx_clock; + reg [((F_SYNC_DLY-1)*F_CKRES)-1:0] q_tx_clock; + reg [TB+3:0] ck_tx_count; + reg [(F_SYNC_DLY-1)*(TB+4)-1:0] q_tx_count; + initial q_tx_count = 0; + initial ck_tx_count = 0; + initial q_tx_clock = 0; + initial ck_tx_clock = 0; + always @($global_clock) + { ck_tx_clock, q_tx_clock } <= { q_tx_clock, f_tx_clock }; + always @($global_clock) + { ck_tx_count, q_tx_count } <= { q_tx_count, f_tx_count }; + reg [TB+4+F_CKRES-1:0] f_ck_tx_time, f_rx_time; + always @(*) + f_ck_tx_time = { ck_tx_count, !ck_tx_clock[F_CKRES-1], + ck_tx_clock[F_CKRES-2:0] }; + always @(*) + f_rx_time = { f_rx_count, !f_rx_clock[1], f_rx_clock[0], + {(F_CKRES-2){1'b0}} }; + reg [TB+4+F_CKRES-1:0] f_signed_difference; + always @(*) + f_signed_difference = f_ck_tx_time - f_rx_time; + always @(*) + if (f_signed_difference[TB+4+F_CKRES-1]) + f_sub_baud_difference = -f_signed_difference; + else + f_sub_baud_difference = f_signed_difference; + always @($global_clock) + if (state == `RXUL_WAIT) + `ASSERT((!f_tx_busy)||(f_tx_reg[9:1] == 0)); + always @($global_clock) + if (state == `RXUL_IDLE) + begin + `ASSERT((!f_tx_busy)||(f_tx_reg[9])||(f_tx_reg[9:1]==0)); + if (!ck_uart) + ;//`PHASE_TWO_ASSERT((f_rx_count < 4)||(f_sub_baud_difference <= ((CLOCKS_PER_BAUD< 6)) + // assert(i_uart_rx == ck_uart); + // Make sure the data register matches + always @(posedge i_clk) + // if ((f_past_valid)&&(state != $past(state))) + begin + if (state == 4'h0) + `ASSERT(!data_reg[7]); + if (state == 4'h1) + `ASSERT((data_reg[7] + == $past(f_tx_data[0]))&&(!data_reg[6])); + if (state == 4'h2) + `ASSERT(data_reg[7:6] + == $past(f_tx_data[1:0])); + if (state == 4'h3) + `ASSERT(data_reg[7:5] == $past(f_tx_data[2:0])); + if (state == 4'h4) + `ASSERT(data_reg[7:4] == $past(f_tx_data[3:0])); + if (state == 4'h5) + `ASSERT(data_reg[7:3] == $past(f_tx_data[4:0])); + if (state == 4'h6) + `ASSERT(data_reg[7:2] == $past(f_tx_data[5:0])); + if (state == 4'h7) + `ASSERT(data_reg[7:1] == $past(f_tx_data[6:0])); + if (state == 4'h8) + `ASSERT(data_reg[7:0] == $past(f_tx_data[7:0])); + end + //////////////////////////////////////////////////////////////////////// + // + // Cover properties + // + //////////////////////////////////////////////////////////////////////// + // + always @(posedge i_clk) + cover(o_wr); // Step 626, takes about 20mins + always @(posedge i_clk) + begin + cover(!ck_uart); + cover((f_past_valid)&&($rose(ck_uart))); // 82 + cover((zero_baud_counter)&&(state == `RXUL_BIT_ZERO)); // 110 + cover((zero_baud_counter)&&(state == `RXUL_BIT_ONE)); // 174 + cover((zero_baud_counter)&&(state == `RXUL_BIT_TWO)); // 238 + cover((zero_baud_counter)&&(state == `RXUL_BIT_THREE));// 302 + cover((zero_baud_counter)&&(state == `RXUL_BIT_FOUR)); // 366 + cover((zero_baud_counter)&&(state == `RXUL_BIT_FIVE)); // 430 + cover((zero_baud_counter)&&(state == `RXUL_BIT_SIX)); // 494 + cover((zero_baud_counter)&&(state == `RXUL_BIT_SEVEN));// 558 + cover((zero_baud_counter)&&(state == `RXUL_STOP)); // 622 + cover((zero_baud_counter)&&(state == `RXUL_WAIT)); // 626 + end +`endif +`ifdef FORMAL_VERILATOR + // FORMAL properties which can be tested via Verilator as well as + // Yosys FORMAL + always @(*) + assert((state == 4'hf)||(state <= `RXUL_WAIT)); + always @(*) + assert(zero_baud_counter == (baud_counter == 0)? 1'b1:1'b0); + always @(*) + assert(baud_counter <= CLOCKS_PER_BAUD-1'b1); +`endif +endmodule ADDED example2/tx.v Index: example2/tx.v ================================================================== --- /dev/null +++ example2/tx.v @@ -0,0 +1,434 @@ + +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: txuartlite.v +// +// Project: wbuart32, a full featured UART with simulator +// +// Purpose: Transmit outputs over a single UART line. This particular UART +// implementation has been extremely simplified: it does not handle +// generating break conditions, nor does it handle anything other than the +// 8N1 (8 data bits, no parity, 1 stop bit) UART sub-protocol. +// +// To interface with this module, connect it to your system clock, and +// pass it the byte of data you wish to transmit. Strobe the i_wr line +// high for one cycle, and your data will be off. Wait until the 'o_busy' +// line is low before strobing the i_wr line again--this implementation +// has NO BUFFER, so strobing i_wr while the core is busy will just +// get ignored. The output will be placed on the o_txuart output line. +// +// (I often set both data and strobe on the same clock, and then just leave +// them set until the busy line is low. Then I move on to the next piece +// of data.) +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015-2020, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory. Run make with no +// target there if the PDF file isn't present.) If not, see +// for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// +`define TXUL_BIT_ZERO 4'h0 +`define TXUL_BIT_ONE 4'h1 +`define TXUL_BIT_TWO 4'h2 +`define TXUL_BIT_THREE 4'h3 +`define TXUL_BIT_FOUR 4'h4 +`define TXUL_BIT_FIVE 4'h5 +`define TXUL_BIT_SIX 4'h6 +`define TXUL_BIT_SEVEN 4'h7 +`define TXUL_STOP 4'h8 +`define TXUL_IDLE 4'hf +// +// +module txuartlite(i_clk, i_wr, i_data, o_uart_tx, o_busy); + parameter [4:0] TIMING_BITS = 5'd24; + localparam TB = TIMING_BITS; + parameter [(TB-1):0] CLOCKS_PER_BAUD = 8; // 24'd868; + input wire i_clk; + input wire i_wr; + input wire [7:0] i_data; + // And the UART input line itself + output reg o_uart_tx; + // A line to tell others when we are ready to accept data. If + // (i_wr)&&(!o_busy) is ever true, then the core has accepted a byte + // for transmission. + output wire o_busy; + + reg [(TB-1):0] baud_counter; + reg [3:0] state; + reg [7:0] lcl_data; + reg r_busy, zero_baud_counter; + + // Big state machine controlling: r_busy, state + // {{{ + // + initial r_busy = 1'b1; + initial state = `TXUL_IDLE; + always @(posedge i_clk) + begin + if (!zero_baud_counter) + // r_busy needs to be set coming into here + r_busy <= 1'b1; + else if (state > `TXUL_STOP) // STATE_IDLE + begin + state <= `TXUL_IDLE; + r_busy <= 1'b0; + if ((i_wr)&&(!r_busy)) + begin // Immediately start us off with a start bit + r_busy <= 1'b1; + state <= `TXUL_BIT_ZERO; + end + end else begin + // One clock tick in each of these states ... + r_busy <= 1'b1; + if (state <=`TXUL_STOP) // start bit, 8-d bits, stop-b + state <= state + 1'b1; + else + state <= `TXUL_IDLE; + end + end + // }}} + + // o_busy + // {{{ + // + // This is a wire, designed to be true is we are ever busy above. + // originally, this was going to be true if we were ever not in the + // idle state. The logic has since become more complex, hence we have + // a register dedicated to this and just copy out that registers value. + assign o_busy = (r_busy); + // }}} + + + // lcl_data + // {{{ + // + // This is our working copy of the i_data register which we use + // when transmitting. It is only of interest during transmit, and is + // allowed to be whatever at any other time. Hence, if r_busy isn't + // true, we can always set it. On the one clock where r_busy isn't + // true and i_wr is, we set it and r_busy is true thereafter. + // Then, on any zero_baud_counter (i.e. change between baud intervals) + // we simple logically shift the register right to grab the next bit. + initial lcl_data = 8'hff; + always @(posedge i_clk) + if ((i_wr)&&(!r_busy)) + lcl_data <= i_data; + else if (zero_baud_counter) + lcl_data <= { 1'b1, lcl_data[7:1] }; + // }}} + + // o_uart_tx + // {{{ + // + // This is the final result/output desired of this core. It's all + // centered about o_uart_tx. This is what finally needs to follow + // the UART protocol. + // + initial o_uart_tx = 1'b1; + always @(posedge i_clk) + if ((i_wr)&&(!r_busy)) + o_uart_tx <= 1'b0; // Set the start bit on writes + else if (zero_baud_counter) // Set the data bit. + o_uart_tx <= lcl_data[0]; + // }}} + + // Baud counter + // {{{ + // All of the above logic is driven by the baud counter. Bits must last + // CLOCKS_PER_BAUD in length, and this baud counter is what we use to + // make certain of that. + // + // The basic logic is this: at the beginning of a bit interval, start + // the baud counter and set it to count CLOCKS_PER_BAUD. When it gets + // to zero, restart it. + // + // However, comparing a 28'bit number to zero can be rather complex-- + // especially if we wish to do anything else on that same clock. For + // that reason, we create "zero_baud_counter". zero_baud_counter is + // nothing more than a flag that is true anytime baud_counter is zero. + // It's true when the logic (above) needs to step to the next bit. + // Simple enough? + // + // I wish we could stop there, but there are some other (ugly) + // conditions to deal with that offer exceptions to this basic logic. + // + // 1. When the user has commanded a BREAK across the line, we need to + // wait several baud intervals following the break before we start + // transmitting, to give any receiver a chance to recognize that we are + // out of the break condition, and to know that the next bit will be + // a stop bit. + // + // 2. A reset is similar to a break condition--on both we wait several + // baud intervals before allowing a start bit. + // + // 3. In the idle state, we stop our counter--so that upon a request + // to transmit when idle we can start transmitting immediately, rather + // than waiting for the end of the next (fictitious and arbitrary) baud + // interval. + // + // When (i_wr)&&(!r_busy)&&(state == `TXUL_IDLE) then we're not only in + // the idle state, but we also just accepted a command to start writing + // the next word. At this point, the baud counter needs to be reset + // to the number of CLOCKS_PER_BAUD, and zero_baud_counter set to zero. + // + // The logic is a bit twisted here, in that it will only check for the + // above condition when zero_baud_counter is false--so as to make + // certain the STOP bit is complete. + initial zero_baud_counter = 1'b1; + initial baud_counter = 0; + always @(posedge i_clk) + begin + zero_baud_counter <= (baud_counter == 1); + if (state == `TXUL_IDLE) + begin + baud_counter <= 0; + zero_baud_counter <= 1'b1; + if ((i_wr)&&(!r_busy)) + begin + baud_counter <= CLOCKS_PER_BAUD - 1'b1; + zero_baud_counter <= 1'b0; + end + end else if ((zero_baud_counter)&&(state == 4'h9)) + begin + baud_counter <= 0; + zero_baud_counter <= 1'b1; + end else if (!zero_baud_counter) + baud_counter <= baud_counter - 1'b1; + else + baud_counter <= CLOCKS_PER_BAUD - 1'b1; + end + // }}} +// +// +// FORMAL METHODS +// +// +// +`ifdef FORMAL + +`ifdef TXUARTLITE +`define ASSUME assume +`else +`define ASSUME assert +`endif + + // Setup + // {{{ + reg f_past_valid, f_last_clk; + + initial f_past_valid = 1'b0; + always @(posedge i_clk) + f_past_valid <= 1'b1; + + initial `ASSUME(!i_wr); + always @(posedge i_clk) + if ((f_past_valid)&&($past(i_wr))&&($past(o_busy))) + begin + `ASSUME(i_wr == $past(i_wr)); + `ASSUME(i_data == $past(i_data)); + end + // }}} + + // Check the baud counter + // {{{ + always @(posedge i_clk) + assert(zero_baud_counter == (baud_counter == 0)); + + always @(posedge i_clk) + if ((f_past_valid)&&($past(baud_counter != 0))&&($past(state != `TXUL_IDLE))) + assert(baud_counter == $past(baud_counter - 1'b1)); + + always @(posedge i_clk) + if ((f_past_valid)&&(!$past(zero_baud_counter))&&($past(state != `TXUL_IDLE))) + assert($stable(o_uart_tx)); + + reg [(TB-1):0] f_baud_count; + initial f_baud_count = 1'b0; + always @(posedge i_clk) + if (zero_baud_counter) + f_baud_count <= 0; + else + f_baud_count <= f_baud_count + 1'b1; + + always @(posedge i_clk) + assert(f_baud_count < CLOCKS_PER_BAUD); + + always @(posedge i_clk) + if (baud_counter != 0) + assert(o_busy); + // }}} + + reg [9:0] f_txbits; + // {{{ + initial f_txbits = 0; + always @(posedge i_clk) + if (zero_baud_counter) + f_txbits <= { o_uart_tx, f_txbits[9:1] }; + + always @(posedge i_clk) + if ((f_past_valid)&&(!$past(zero_baud_counter)) + &&(!$past(state==`TXUL_IDLE))) + assert(state == $past(state)); + + reg [3:0] f_bitcount; + initial f_bitcount = 0; + always @(posedge i_clk) + if ((!f_past_valid)||(!$past(f_past_valid))) + f_bitcount <= 0; + else if ((state == `TXUL_IDLE)&&(zero_baud_counter)) + f_bitcount <= 0; + else if (zero_baud_counter) + f_bitcount <= f_bitcount + 1'b1; + + always @(posedge i_clk) + assert(f_bitcount <= 4'ha); + + reg [7:0] f_request_tx_data; + always @(posedge i_clk) + if ((i_wr)&&(!o_busy)) + f_request_tx_data <= i_data; + + wire [3:0] subcount; + assign subcount = 10-f_bitcount; + always @(posedge i_clk) + if (f_bitcount > 0) + assert(!f_txbits[subcount]); + + always @(posedge i_clk) + if (f_bitcount == 4'ha) + begin + assert(f_txbits[8:1] == f_request_tx_data); + assert( f_txbits[9]); + end + + always @(posedge i_clk) + assert((state <= `TXUL_STOP + 1'b1)||(state == `TXUL_IDLE)); + + always @(posedge i_clk) + if ((f_past_valid)&&($past(f_past_valid))&&($past(o_busy))) + cover(!o_busy); + // }}} + +`endif // FORMAL +`ifdef VERIFIC_SVA + reg [7:0] fsv_data; + + // + // Grab a copy of the data any time we are sent a new byte to transmit + // We'll use this in a moment to compare the item transmitted against + // what is supposed to be transmitted + // + always @(posedge i_clk) + if ((i_wr)&&(!o_busy)) + fsv_data <= i_data; + + // + // One baud interval + // {{{ + // + // 1. The UART output is constant at DAT + // 2. The internal state remains constant at ST + // 3. CKS = the number of clocks per bit. + // + // Everything stays constant during the CKS clocks with the exception + // of (zero_baud_counter), which is *only* raised on the last clock + // interval + sequence BAUD_INTERVAL(CKS, DAT, SR, ST); + ((o_uart_tx == DAT)&&(state == ST) + &&(lcl_data == SR) + &&(!zero_baud_counter))[*(CKS-1)] + ##1 (o_uart_tx == DAT)&&(state == ST) + &&(lcl_data == SR) + &&(zero_baud_counter); + endsequence + // }}} + + // + // One byte transmitted + // {{{ + // + // DATA = the byte that is sent + // CKS = the number of clocks per bit + // + sequence SEND(CKS, DATA); + BAUD_INTERVAL(CKS, 1'b0, DATA, 4'h0) + ##1 BAUD_INTERVAL(CKS, DATA[0], {{(1){1'b1}},DATA[7:1]}, 4'h1) + ##1 BAUD_INTERVAL(CKS, DATA[1], {{(2){1'b1}},DATA[7:2]}, 4'h2) + ##1 BAUD_INTERVAL(CKS, DATA[2], {{(3){1'b1}},DATA[7:3]}, 4'h3) + ##1 BAUD_INTERVAL(CKS, DATA[3], {{(4){1'b1}},DATA[7:4]}, 4'h4) + ##1 BAUD_INTERVAL(CKS, DATA[4], {{(5){1'b1}},DATA[7:5]}, 4'h5) + ##1 BAUD_INTERVAL(CKS, DATA[5], {{(6){1'b1}},DATA[7:6]}, 4'h6) + ##1 BAUD_INTERVAL(CKS, DATA[6], {{(7){1'b1}},DATA[7:7]}, 4'h7) + ##1 BAUD_INTERVAL(CKS, DATA[7], 8'hff, 4'h8) + ##1 BAUD_INTERVAL(CKS, 1'b1, 8'hff, 4'h9); + endsequence + // }}} + + // + // Transmit one byte + // {{{ + // Once the byte is transmitted, make certain we return to + // idle + // + assert property ( + @(posedge i_clk) + (i_wr)&&(!o_busy) + |=> ((o_busy) throughout SEND(CLOCKS_PER_BAUD,fsv_data)) + ##1 (!o_busy)&&(o_uart_tx)&&(zero_baud_counter)); + // }}} + + // {{{ + assume property ( + @(posedge i_clk) + (i_wr)&&(o_busy) |=> + (i_wr)&&(o_busy)&&($stable(i_data))); + + // + // Make certain that o_busy is true any time zero_baud_counter is + // non-zero + // + always @(*) + assert((o_busy)||(zero_baud_counter) ); + + // If and only if zero_baud_counter is true, baud_counter must be zero + // Insist on that relationship here. + always @(*) + assert(zero_baud_counter == (baud_counter == 0)); + + // To make certain baud_counter stays below CLOCKS_PER_BAUD + always @(*) + assert(baud_counter < CLOCKS_PER_BAUD); + + // + // Insist that we are only ever in a valid state + always @(*) + assert((state <= `TXUL_STOP+1'b1)||(state == `TXUL_IDLE)); + // }}} + +`endif // Verific SVA +endmodule Index: ezsteps.scm ================================================================== --- ezsteps.scm +++ ezsteps.scm @@ -17,11 +17,12 @@ ;; along with Megatest. If not, see . ;; ;; strftime('%m/%d/%Y %H:%M:%S','now','localtime') -(use srfi-1 posix regex srfi-69 directory-utils) +(use srfi-1 posix regex srfi-69 directory-utils call-with-environment-variables posix-extras + z3 csv typed-records pathname-expand matchable) (declare (unit ezsteps)) (declare (uses db)) (declare (uses common)) (declare (uses items)) @@ -35,11 +36,201 @@ (include "run_records.scm") ;;(rmt:get-test-info-by-id run-id test-id) -> testdat +;; TODO: deprecate me in favor of ezsteps.scm +;; +(define (launch:runstep ezstep run-id test-id exit-info m tal testconfig all-steps-dat) + (let* ((stepname (car ezstep)) ;; do stuff to run the step + (stepinfo (cadr ezstep)) + ;; (let ((info (cadr ezstep))) + ;; (if (proc? info) "" info))) + ;; (stepproc (let ((info (cadr ezstep))) + ;; (if (proc? info) info #f))) + (stepparts (string-match (regexp "^(\\{([^\\}\\{]*)\\}\\s*|)(.*)$") stepinfo)) + (stepparams (if (and (list? stepparts) + (> (length stepparts) 1)) + (list-ref stepparts 2) + #f)) ;; for future use, {VAR=1,2,3}, run step for each + (paramparts (if (string? stepparams) + (map (lambda (x)(string-split x "=")) (string-split-fields "[^;]*=[^;]*" stepparams)) + '())) + (subrun (alist-ref "subrun" paramparts equal?)) + (stepcmd (if (and (list? stepparts) + (> (length stepparts) 2)) + (list-ref stepparts 3) + (conc "# error, no command for step "stepname))) + (script "") ; "#!/bin/bash\n") ;; yep, we depend on bin/bash FIXME!!!\ + (logpro-file (conc stepname ".logpro")) + (html-file (conc stepname ".html")) + (dat-file (conc stepname ".dat")) + (tconfig-logpro (configf:lookup testconfig "logpro" stepname)) + (logpro-used (common:file-exists? logpro-file))) + (setenv "MT_STEP_NAME" stepname) + (hash-table-set! all-steps-dat stepname `((params . ,paramparts))) + (debug:print 0 *default-log-port* "stepparts: " stepparts ", stepparams: " stepparams + ", paramparts: " paramparts ", subrun: " subrun ", stepcmd: " stepcmd) + + (if (and tconfig-logpro + (not logpro-used)) ;; no logpro file found but have a defn in the testconfig + (begin + (with-output-to-file logpro-file + (lambda () + (print ";; logpro file extracted from testconfig\n" + ";;") + (print tconfig-logpro))) + (set! logpro-used #t))) + + ;; NB// can safely assume we are in test-area directory + (debug:print 4 *default-log-port* "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts + " stepparams: " stepparams " stepcmd: " stepcmd) + + ;; ;; first source the previous environment + ;; (let ((prev-env (conc ".ezsteps/" prevstep (if (string-search (regexp "csh") + ;; (get-environment-variable "SHELL")) ".csh" ".sh")))) + ;; (if (and prevstep (common:file-exists? prev-env)) + ;; (set! script (conc script "source " prev-env)))) + + ;; call the command using mt_ezstep + ;; (set! script (conc "mt_ezstep " stepname " " (if prevstep prevstep "x") " " stepcmd)) + + (debug:print 4 *default-log-port* "script: " script) + (rmt:teststep-set-status! run-id test-id stepname "start" "-" #f #f) + ;; now launch the actual process + (call-with-environment-variables + (list (cons "PATH" (conc (get-environment-variable "PATH") ":."))) + (lambda () ;; (process-run "/bin/bash" "-c" "exec ls -l /tmp/foobar > /tmp/delme-more.log 2>&1") + (let* ((cmd (conc stepcmd " > " stepname ".log 2>&1")) ;; >outfile 2>&1 + (pid #f)) + (let ((proc (lambda () + (set! pid (process-run "/bin/bash" (list "-c" cmd)))))) + (if subrun + (begin + (debug:print-info 0 *default-log-port* "Running without MT_.* environment variables.") + (common:without-vars proc "^MT_.*")) + (proc))) + + (with-output-to-file "Makefile.ezsteps" + (lambda () + (print stepname ".log :") + (print "\t" cmd) + (if (common:file-exists? (conc stepname ".logpro")) + (print "\tlogpro " stepname ".logpro " stepname ".html < " stepname ".log")) + (print) + (print stepname " : " stepname ".log") + (print)) + #:append) + (rmt:test-set-top-process-pid run-id test-id pid) + (let processloop ((i 0)) + (let-values (((pid-val exit-status exit-code)(process-wait pid #t))) + (mutex-lock! m) + (launch:einf-pid-set! exit-info pid) ;; (vector-set! exit-info 0 pid) + (launch:einf-exit-status-set! exit-info exit-status) ;; (vector-set! exit-info 1 exit-status) + (launch:einf-exit-code-set! exit-info exit-code) ;; (vector-set! exit-info 2 exit-code) + (mutex-unlock! m) + (if (eq? pid-val 0) + (begin + (thread-sleep! 2) + (processloop (+ i 1)))) + ))))) + (debug:print-info 0 *default-log-port* "step " stepname " completed with exit code " (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2)) + ;; now run logpro if needed + (if logpro-used + (let* ((logpro-exe (or (getenv "LOGPRO_EXE") "logpro")) + (pid (process-run (conc "/bin/sh -c '"logpro-exe" "logpro-file " " (conc stepname ".html") " < " stepname ".log > /dev/null'")))) + (let processloop ((i 0)) + (let-values (((pid-val exit-status exit-code)(process-wait pid #t))) + (mutex-lock! m) + ;; (make-launch:einf pid: pid exit-status: exit-status exit-code: exit-code) + (launch:einf-pid-set! exit-info pid) ;; (vector-set! exit-info 0 pid) + (launch:einf-exit-status-set! exit-info exit-status) ;; (vector-set! exit-info 1 exit-status) + (launch:einf-exit-code-set! exit-info exit-code) ;; (vector-set! exit-info 2 exit-code) + (mutex-unlock! m) + (if (eq? pid-val 0) + (begin + (thread-sleep! 2) + (processloop (+ i 1))))) + (debug:print-info 0 *default-log-port* "logpro for step " stepname " exited with code " (launch:einf-exit-code exit-info))))) ;; (vector-ref exit-info 2))))) + + (let ((exinfo (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2)) + (logfna (if logpro-used (conc stepname ".html") "")) + (comment #f)) + (if logpro-used + (let ((datfile (conc stepname ".dat"))) + ;; load the .dat file into the test_data table if it exists + (if (common:file-exists? datfile) + (set! comment (launch:load-logpro-dat run-id test-id stepname))) + (rmt:test-set-log! run-id test-id (conc stepname ".html")))) + (rmt:teststep-set-status! run-id test-id stepname "end" exinfo comment logfna)) + ;; set the test final status + (let* ((process-exit-status (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2)) + (this-step-status (cond + ((and (eq? process-exit-status 2) logpro-used) 'warn) ;; logpro 2 = warnings + ((and (eq? process-exit-status 3) logpro-used) 'check) ;; logpro 3 = check + ((and (eq? process-exit-status 4) logpro-used) 'waived) ;; logpro 4 = waived + ((and (eq? process-exit-status 5) logpro-used) 'abort) ;; logpro 5 = abort + ((and (eq? process-exit-status 6) logpro-used) 'skip) ;; logpro 6 = skip + ((eq? process-exit-status 0) 'pass) ;; logpro 0 = pass + (else 'fail))) + (overall-status (cond + ((eq? (launch:einf-rollup-status exit-info) 2) 'warn) ;; rollup-status (vector-ref exit-info 3) + ((eq? (launch:einf-rollup-status exit-info) 0) 'pass) ;; (vector-ref exit-info 3) + (else 'fail))) + (next-status (cond + ((eq? overall-status 'pass) this-step-status) + ((eq? overall-status 'warn) + (if (eq? this-step-status 'fail) 'fail 'warn)) + ((eq? overall-status 'abort) 'abort) + (else 'fail))) + (next-state ;; "RUNNING") ;; WHY WAS THIS CHANGED TO NOT USE (null? tal) ?? + (cond + ((null? tal) ;; more to run? + "COMPLETED") + (else "RUNNING")))) + (debug:print 4 *default-log-port* "Exit value received: " (launch:einf-exit-code exit-info) " logpro-used: " logpro-used + " this-step-status: " this-step-status " overall-status: " overall-status + " next-status: " next-status " rollup-status: " (launch:einf-rollup-status exit-info)) ;; (vector-ref exit-info 3)) + (case next-status + ((warn) + (launch:einf-rollup-status-set! exit-info 2) ;; (vector-set! exit-info 3 2) ;; rollup-status + ;; NB// test-set-status! does rdb calls under the hood + (tests:test-set-status! run-id test-id next-state "WARN" + (if (eq? this-step-status 'warn) "Logpro warning found" #f) + #f)) + ((check) + (launch:einf-rollup-status-set! exit-info 3) ;; (vector-set! exit-info 3 3) ;; rollup-status + ;; NB// test-set-status! does rdb calls under the hood + (tests:test-set-status! run-id test-id next-state "CHECK" + (if (eq? this-step-status 'check) "Logpro check found" #f) + #f)) + ((waived) + (launch:einf-rollup-status-set! exit-info 4) ;; (vector-set! exit-info 3 3) ;; rollup-status + ;; NB// test-set-status! does rdb calls under the hood + (tests:test-set-status! run-id test-id next-state "WAIVED" + (if (eq? this-step-status 'check) "Logpro waived found" #f) + #f)) + ((abort) + (launch:einf-rollup-status-set! exit-info 5) ;; (vector-set! exit-info 3 4) ;; rollup-status + ;; NB// test-set-status! does rdb calls under the hood + (tests:test-set-status! run-id test-id next-state "ABORT" + (if (eq? this-step-status 'abort) "Logpro abort found" #f) + #f)) + ((skip) + (launch:einf-rollup-status-set! exit-info 6) ;; (vector-set! exit-info 3 4) ;; rollup-status + ;; NB// test-set-status! does rdb calls under the hood + (tests:test-set-status! run-id test-id next-state "SKIP" + (if (eq? this-step-status 'skip) "Logpro skip found" #f) + #f)) + ((pass) + (tests:test-set-status! run-id test-id next-state "PASS" #f #f)) + (else ;; 'fail + (launch:einf-rollup-status-set! exit-info 1) ;; (vector-set! exit-info 3 1) ;; force fail, this used to be next-state but that doesn't make sense. should always be "COMPLETED" + (tests:test-set-status! run-id test-id "COMPLETED" "FAIL" (conc "Failed at step " stepname) #f) + ))) + logpro-used)) (define (ezsteps:run-from testdat start-step-name run-one) ;;# TODO - recapture item variables, debug repeated step eval; regen logpro from test (let* ((do-update-test-state-status #f) (test-run-dir ;; (filedb:get-path *fdb* @@ -54,11 +245,12 @@ (test-id (db:test-get-id testdat)) (run-id (db:test-get-run_id testdat)) (test-name (db:test-get-testname testdat)) (orig-test-state (db:test-get-state testdat)) (orig-test-status (db:test-get-status testdat)) - (kill-job #f)) ;; for future use (on re-factoring with launch.scm code + (kill-job #f) ;; for future use (on re-factoring with launch.scm code + (the-step-params '())) ;; not exactly "functional" ;; keep trying till NFS deigns to populate test run dir on this host (let loop ((count 5)) (if (not (common:file-exists? test-run-dir)) ;;(push-directory test-run-dir) @@ -78,12 +270,14 @@ (let loop ((ezstep (car ezstepslst)) (tal (cdr ezstepslst)) (status-sym-so-far 'pass) ;;(runflag #f) (saw-start-step-name #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 + (if (or (vector-ref exit-info 1) + (equal? (alist-ref 'keep-going prev-step-params) 'yes)) + (let* ((prev-step-params the-step-params) ;; need to snag this now + (stepname (car ezstep)) ;; do stuff to run the step (logpro-used (common:file-exists? (conc test-run-dir "/" stepname ".logpro"))) (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)) @@ -94,10 +288,12 @@ (equal? stepname start-step-name) (and saw-start-step-name (not run-one)) saw-start-step-name-next (and start-step-name (equal? stepname start-step-name)))) ) + (debug:print 0 *default-log-port* "NOTE: stepparms=" stepparms) + (set! prev-step-params stepparms) (set! do-update-test-state-status (and proceed-with-this-step (null? tal))) ;;(BB> "stepname="stepname" proceed-with-this-step="proceed-with-this-step " do-update-test-state-status="do-update-test-state-status " orig-test-state="orig-test-state" orig-test-status="orig-test-status) (cond ((and (not proceed-with-this-step) (null? tal)) 'done) ADDED fossil-utils/Makefile Index: fossil-utils/Makefile ================================================================== --- /dev/null +++ fossil-utils/Makefile @@ -0,0 +1,14 @@ + + +all : run.sh + +go : run.sh + bash run.sh + +fossilrebase : fossilrebase.scm + csc fossilrebase.scm + +run.sh : fossilrebase justtesting/*.dat + ./fossilrebase dumpcmds justtesting > run.sh + + ADDED fossil-utils/fossilrebase.scm Index: fossil-utils/fossilrebase.scm ================================================================== --- /dev/null +++ fossil-utils/fossilrebase.scm @@ -0,0 +1,262 @@ +(use yaml matchable srfi-1 sqlite3 regex) + +(define (get-timeline) + (let* ((inp (open-input-pipe "fossil json timeline checkin -n 0")) + (res (yaml-load inp))) + (close-input-pipe inp) + res)) + +(define (get-val data key) + (alist-ref key data equal?)) + +(define (any->string val) + (if (string? val) + val + (conc val))) + +(define (branch-match branches tags) + (if (list? tags) + (any (lambda (x) + (member x branches)) + tags) + (member tags branches))) + +(define (refdb-set-value dbname sheetname row col value) + (let ((pid (process-run "refdb" `("set" ,dbname ,sheetname ,row ,col ,value)))) + (let-values (((a b c)(process-wait pid))) + b))) + +(define (seconds->std-time-str sec) + (time->string + (seconds->local-time sec) + "%Y-%m-%d %H:%M:%S")) + +(define (gen-refdb dbname branches) + (if (not (file-exists? (conc dbname "/sheet-names.cfg"))) + (begin + (print "ERROR: You must precreate the refdb with \"refdb edit \"") + (exit 1))) + (print "Getting data from timeline...") + (let* ((data (get-timeline)) + (branches (string-split branches ","))) + (print "Got data from timeline...") + (let* ((timeline (get-val (get-val data "payload") "timeline"))) + (print "Got " (length timeline) " timeline records. Filling refdb...") + (for-each + (lambda (rec) + (let ((uuid (get-val rec "uuid"))) + (if (branch-match branches (get-val rec "tags")) + (let ((tagnum 0) + (tags (get-val rec "tags"))) + (print "uuid: " uuid " tags: " (get-val rec "tags")) + ;; First the tags so they are visible to left + (for-each + (lambda (tagv) + (refdb-set-value dbname "timeline" uuid (conc "tag" tagnum) tagv) + (set! tagnum (+ tagnum 1))) + (if (list? tags) + tags + (list tags))) + (for-each + (lambda (key) + (refdb-set-value dbname "timeline" uuid key (any->string (get-val rec key)))) + '("user" "comment")) + (refdb-set-value dbname "extra" uuid "parents" (string-intersperse (get-val rec "parents") ",")) + (refdb-set-value dbname "timeline" uuid "timestamp" (seconds->std-time-str (get-val rec "timestamp"))) + (refdb-set-value dbname "timeline" uuid "timestamp_sec" (any->string (get-val rec "timestamp"))) + )))) + timeline)))) + +(define (escape-string-for-bash str) + (string-substitute "'" "''" str #t)) + +;; tag0 tag1 tag2 cherrypick backout hide usedate recomment user +;; comment timestamp timestamp_sec +;; +(define (get-node-details db node-id) + (let* ((result #f) + (count 0)) + (for-each-row + (lambda (rowkey tag0 cmdnum cherrypick do-commit backout hide usedate recomment user comment timestamp timestamp_sec) + (set! result `((uuid . ,rowkey) + (tag0 . ,tag0) + (cmdnum . ,cmdnum) + (cherrypick . ,cherrypick) + (do-commit . ,do-commit) + (backout . ,backout) + (hide . ,hide) + (usedate . ,usedate) + (recomment . ,recomment) + (user . ,user) + (comment . ,comment) + (timestamp . ,timestamp) + (timestamp_sec . ,timestamp_sec))) + (set! count (+ count 1))) + db + "SELECT rowkey,tag0,cmdnum,cherrypick,do_commit,backout,hide,usedate,recomment,user,comment,timestamp,timestamp_sec FROM timeline WHERE rowkey LIKE ?;" + node-id) + (if (> count 1) + (print "WARNING: more than one node matches " node-id ", found " count " nodes")) + result)) + +;; get branches to create +;; +(define (get-new-branches db) + (let* ((res '())) + (for-each-row + (lambda (rowkey node mode) + (set! res (cons `((branch . ,rowkey) + (node . ,node) + (mode . ,mode)) + res))) + db + "SELECT rowkey,node,mode FROM branches;") + res)) + +;; get cherrypicks +;; +(define (get-cherry-picks db) + (let* ((res '())) + (for-each-row + (lambda (rowkey tag0 cherrypick firstmerge do-commit usedate comment recomment) + (set! res (cons `((uuid . ,rowkey) + (tag0 . ,tag0) + (cherrypick . ,cherrypick) + (firstmerge . ,firstmerge) + (do-commit . ,do-commit) + (usedate . ,usedate) + (comment . ,comment) + (recomment . ,recomment)) + res))) + db ;; sort desc and the cons puts it back in correct order + "SELECT rowkey,tag0,cherrypick,firstmerge,do_commit,usedate,comment,recomment FROM timeline WHERE cherrypick != '' AND cherrypick NOT NULL ORDER BY timestamp_sec DESC;") + res)) + +;; always private and same time as parent node + 1 second +;; +;; fossil branch new BRANCH-NAME BASIS ?OPTIONS? +;; +;; Create a new branch BRANCH-NAME off of check-in BASIS. +;; Supported options for this subcommand include: +;; --private branch is private (i.e., remains local) +;; --bgcolor COLOR use COLOR instead of automatic background +;; --nosign do not sign contents on this branch +;; --date-override DATE DATE to use instead of 'now' +;; --user-override USER USER to use instead of the current default +;; +;; DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in +;; year-month-day form, it may be truncated, the "T" may be +;; replaced by a space, and it may also name a timezone offset +;; from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward). +;; Either no timezone suffix or "Z" means UTC. +;; +(define (create-branch db branch-name parent-node) + (let* ((parent-info (get-node-details db (conc parent-node "%")))) + (if (not parent-info) + (print "ERROR: no info found for node " parent-node) + (let* ((parent-date (alist-ref 'timestamp parent-info)) + (parent-user (alist-ref 'user parent-info))) + (print "fossil branch new " branch-name " " parent-node " --private --date-override '" parent-date "'") + ;; (print "Creating private branch " branch-name " from node " parent-node) + ;; (pp parent-info) + ;; (print "") + )))) + +(define (do-cherrypick db cherrypick dbfname) + (let* ((tag0 (alist-ref 'tag0 cherrypick)) + (uuid (alist-ref 'uuid cherrypick)) + (nodeinf (get-node-details db uuid)) + (nodedate (alist-ref 'timestamp nodeinf)) + (user (alist-ref 'user nodeinf)) + (targ (alist-ref 'cherrypick cherrypick)) ;; do fossil up to this node + (firstmerge (alist-ref 'firstmerge cherrypick)) + (do-commit (alist-ref 'do-commit cherrypick)) ;; if yes do a commit + (usedate (alist-ref 'usedate cherrypick)) ;; if no use current time + (comment (alist-ref 'comment cherrypick)) + (recomment (alist-ref 'recomment cherrypick))) + (print "#======= Start of cherrypick for " uuid "=======") + (print "fossil checkout " targ) + ;; first - do we have a firstmerge? + (if (and (string? firstmerge) + (> (string-length firstmerge) 0)) + (print "fossil merge " firstmerge)) + + (print "fossil merge --cherrypick " uuid) + (if #t ;;(member do-commit '("x" "yes")) + (print "fossil commit -m '" (escape-string-for-bash comment) "' " + (if (equal? usedate "no") + "" + (conc " --date-override '" nodedate "'")) + " --user-override " user + )) + (print "if [[ $(fossil status | grep CONFLICT | wc -l) -gt 0 ]];then") + (print " echo \"\nHAVE CONFLICT - STOPPING\n\"") + (print " echo \"cherry pick of " uuid " into " targ " resulted in conflicts\"") + (print " exit 1") + (print "else") + (print " echo GOOD, marking node " uuid " as DONE") + (print " refdb set " dbfname " timeline " uuid " status DONE") + (print "fi") + (print "#======= end of cherrypick for " uuid "=======") + (print "") + )) + +;; +(define (gen-rebase-commands dbname) + (let* ((sqldbname (conc "/tmp/" (current-user-name) "-" dbname ".db")) + (dbfname (conc (current-directory) "/" dbname))) ;; want the fully qualified path so we can call the generated script from anywhere + (print "# Create sqlite db " sqldbname "...") + (system (conc "refdb dump2sqlite3 " dbname " " sqldbname)) + (let* ((db (open-database sqldbname)) + (branches (get-new-branches db)) + (cherrypicks (get-cherry-picks db))) + ;; create the setup + (dump-setup db) + + ;; create the branches + (for-each + (lambda (branchdat) + (create-branch db + (alist-ref 'branch branchdat) + (alist-ref 'node branchdat))) + branches) + + ;; create the cherrypicks + (for-each + (lambda (cherrypick) + (do-cherrypick db cherrypick dbfname)) + cherrypicks) + ))) + +(define (dump-setup db) + (for-each-row + (lambda (cmd) + (print cmd)) + db + "SELECT command FROM 'setup' ORDER BY rowkey ASC;")) + +(define help +"fossilrebase - register commits in a refdb, edit them by hand then execute them + +WARNING: It is highly recommended you do this on a disconnected copy of your fossil database!! + +Usage: fossilrebase cmd [params ...] + where cmd is one of: + genrefdb fname b1,b2... : generate a refdb of all the commits for branches matching patterns listed, edit with \"refdb edit fname\" + dumpcmds fname : from refdb fname dump fossil commands to implement the rebase you want to do. +") + +(define (main) + (if (< (length (command-line-arguments)) 1) + (begin + (print help) + (exit 1)) + (match (command-line-arguments) + (("genrefdb" fname branches) (gen-refdb fname branches)) + (("dumpcmds" fname) (gen-rebase-commands fname)) + (else + (print "Sorry, didn't know what to do with \"" (string-intersperse (command-line-arguments) " ") "\"") + (exit 1))))) + + +(main) ADDED fossil-utils/justtesting/branches.dat Index: fossil-utils/justtesting/branches.dat ================================================================== --- /dev/null +++ fossil-utils/justtesting/branches.dat @@ -0,0 +1,6 @@ +[node] +v1.65-broken-fixes 367ffc5bdf +nobranch 367ffc5bdf +[mode] +v1.65-broken-fixes private +nobranch private ADDED fossil-utils/justtesting/extra.dat Index: fossil-utils/justtesting/extra.dat ================================================================== --- /dev/null +++ fossil-utils/justtesting/extra.dat @@ -0,0 +1,723 @@ +[parents] +e7b6428a2533b1901a3bb12411a4095ce23a4d35 e5c65818cc818ef14c94682202fac7bf40375ec1 +e5c65818cc818ef14c94682202fac7bf40375ec1 9fc475313fb461746f4de5df8343ddf15f6b345d,f6dc7607a8ecb7df68b5e50455a97f17eaefa348 +9fc475313fb461746f4de5df8343ddf15f6b345d e9153fe95b68ac1ab72d38b5cbe22b1f1237f8cc +e9153fe95b68ac1ab72d38b5cbe22b1f1237f8cc 3bd95bc26bb7491d5ab89f264232159d7c188e1b +c7baa27145762eab04802b34d95818386df2e3f7 1b0d4f257e6d9740397662ede6dc01bf0f5fcec7 +1b0d4f257e6d9740397662ede6dc01bf0f5fcec7 c13726326ce034fbedb36a634179fc1f685ef076 +c13726326ce034fbedb36a634179fc1f685ef076 ad2000389bacbff6847a9920ec8cc44363ff9682 +ad2000389bacbff6847a9920ec8cc44363ff9682 473d6eaf82c96fb6db9905da82b1ef1419852a93 +473d6eaf82c96fb6db9905da82b1ef1419852a93 367ffc5bdf35456922c1d3ceebbe633b65a65bcf +f6dc39b0f7277ade8986ad06aa9a5f043c3fba2c 2ded3e4899f49656d06b26c1a35ff730ed9768be +2ded3e4899f49656d06b26c1a35ff730ed9768be 39ec01ec3bb664aa2293ed35dc6f131e00b1d4db +39ec01ec3bb664aa2293ed35dc6f131e00b1d4db 7f1e84d10d19cd8fa9a639fd60c5102aa6c3fdf5 +7f1e84d10d19cd8fa9a639fd60c5102aa6c3fdf5 7f0801084261f8dec9f4eaa05707897c239bd577 +7f0801084261f8dec9f4eaa05707897c239bd577 901de8992f8a31ef8ddfe47edfb31c251044de61 +901de8992f8a31ef8ddfe47edfb31c251044de61 6118471b3384fcc3ae99fd9400d2193b05ceb0f7 +6118471b3384fcc3ae99fd9400d2193b05ceb0f7 73dfd99fe60a44fc519d78117e3bfb0791268fa1 +73dfd99fe60a44fc519d78117e3bfb0791268fa1 2f7d94848b24bab8702d82654351d25711cc89b6 +2f7d94848b24bab8702d82654351d25711cc89b6 875a0b48c6fa9e2eb37094a0b53f80fa316f1189 +875a0b48c6fa9e2eb37094a0b53f80fa316f1189 66d6fd1aaf5dee5b79fbf7f47a3e7325851b7d6d +66d6fd1aaf5dee5b79fbf7f47a3e7325851b7d6d 268055792a6b6210a6d53f3bce9555a6b2de7075,e7b6428a2533b1901a3bb12411a4095ce23a4d35 +f6dc7607a8ecb7df68b5e50455a97f17eaefa348 3bd95bc26bb7491d5ab89f264232159d7c188e1b +f13cb3f1bc36ede7b967ea347fa9cad59d680c88 bd18bd00ac2955b4864a543b19522525434dfe80 +3bd95bc26bb7491d5ab89f264232159d7c188e1b 522b48d828c3295920e0dbd15480dae21426a74b +522b48d828c3295920e0dbd15480dae21426a74b 5dc1573e7d958fae8fb3711663a07f7f5a0670f3 +5dc1573e7d958fae8fb3711663a07f7f5a0670f3 c5bd5112a83452b0cbae5dddc852d47c76ab9ff4 +c5bd5112a83452b0cbae5dddc852d47c76ab9ff4 9d1cc54fe17184885380c438aaa3a2f172d3c275 +9d1cc54fe17184885380c438aaa3a2f172d3c275 da2b09089751193627241c81260e7cafa10657bc +da2b09089751193627241c81260e7cafa10657bc 7fc5b1bdcc47a6f43723efd27f2edcf63bc564b1 +7fc5b1bdcc47a6f43723efd27f2edcf63bc564b1 bb4c7dd6b98dbe9924182e9e5010f8846d702525 +bb4c7dd6b98dbe9924182e9e5010f8846d702525 071ebc34ba460be1bdead4ec1a3c261e6bcd2bc4 +071ebc34ba460be1bdead4ec1a3c261e6bcd2bc4 64aa9347d5e5af8d43fdcfbf64891596022cebe9 +64aa9347d5e5af8d43fdcfbf64891596022cebe9 50237f6e1f5f369b5e1022774427028c4dba7d6b +50237f6e1f5f369b5e1022774427028c4dba7d6b e28be4def5c32dd0a16a6059db1fac22b2aa3653 +e28be4def5c32dd0a16a6059db1fac22b2aa3653 b487e8f3c5ee74eeeaa6edabd92e2548a33210f7 +b487e8f3c5ee74eeeaa6edabd92e2548a33210f7 63e558983a2101551ea0fa140888a5e6fd4322ae +63e558983a2101551ea0fa140888a5e6fd4322ae 19f75192e22ab76c4de3eacbf57416d192617b48 +19f75192e22ab76c4de3eacbf57416d192617b48 8fd408420ba2b46d851b409832a4b0eb55f33a19 +8fd408420ba2b46d851b409832a4b0eb55f33a19 2e3a570e3e8896f290135b2dfc012b0f69c3516d +268055792a6b6210a6d53f3bce9555a6b2de7075 aa29985039a593ff4c56ddc64870c8e205999184 +2e3a570e3e8896f290135b2dfc012b0f69c3516d e5bf9db624e5904b1efb29df7d7ed14f7fc23bc0 +e5bf9db624e5904b1efb29df7d7ed14f7fc23bc0 0a7ddadc4dece2446166d8156ecd1de168115649 +0a7ddadc4dece2446166d8156ecd1de168115649 aa29985039a593ff4c56ddc64870c8e205999184 +bd18bd00ac2955b4864a543b19522525434dfe80 0cb77d7f74edafa41a5d9ac28467c532b679325d +aa29985039a593ff4c56ddc64870c8e205999184 0a9e690b28f0ef4ee710dab3af7b3c45a0e4a38d +3d9c1de6339fcecbd59eb7cbec2be5680f0f914d 6625f3bc6a98d3f05f57ab42d329391613bbe008 +6625f3bc6a98d3f05f57ab42d329391613bbe008 3ccc64251fcfc210fe7ba1998fa90a96d3bf2fa3 +3ccc64251fcfc210fe7ba1998fa90a96d3bf2fa3 0a9e690b28f0ef4ee710dab3af7b3c45a0e4a38d +0a9e690b28f0ef4ee710dab3af7b3c45a0e4a38d 18da8b6a613e8ee42c2b82fd00fedcf38c153433 +18da8b6a613e8ee42c2b82fd00fedcf38c153433 7ff937a8a2df1a3e473a760363b85e98aa01bbc4 +7ff937a8a2df1a3e473a760363b85e98aa01bbc4 5b7f0c6aa302ede19e96946ad2e33a7fa97e4fbb +5b7f0c6aa302ede19e96946ad2e33a7fa97e4fbb ea8c3e52e9f9c216ed88a2707722d4c61e246522 +ea8c3e52e9f9c216ed88a2707722d4c61e246522 a374d9084bb19e0715a3981a05f81b259a7500fc +a374d9084bb19e0715a3981a05f81b259a7500fc 07ff7dca1e64439988168406443a703b0ad929fa +07ff7dca1e64439988168406443a703b0ad929fa 15b59cfa429cb21c7ea1dbe8cdc3d8074d3617b6 +0cb77d7f74edafa41a5d9ac28467c532b679325d d825e32743716501b8fe878f973898a5caa0c450 +15b59cfa429cb21c7ea1dbe8cdc3d8074d3617b6 0364beb9c92e54e3e658cdf1876d7c75b2d68e15,d825e32743716501b8fe878f973898a5caa0c450 +0364beb9c92e54e3e658cdf1876d7c75b2d68e15 0645166f9cdc9cbb2e922e7a3b0094fbf78e9c8c +0645166f9cdc9cbb2e922e7a3b0094fbf78e9c8c 5de2fd17b5348d5283f874e7ec9bf2c53cad12a0 +d825e32743716501b8fe878f973898a5caa0c450 220b14a861c4883ff947e46ea39af32c046aaa99 +220b14a861c4883ff947e46ea39af32c046aaa99 8724301727841358def98a48e191a0e344ddbf68 +8724301727841358def98a48e191a0e344ddbf68 cdd5e92143e616f56b8b4ba90f6bc2114de0dee1 +5de2fd17b5348d5283f874e7ec9bf2c53cad12a0 2a858c5054f56588fefe6039621ebaefc5344d29 +2a858c5054f56588fefe6039621ebaefc5344d29 0495fb12176784b1907c243c54898c23f2afc140 +0495fb12176784b1907c243c54898c23f2afc140 3b86fd8d4c9f097a04885021f902a69cfc375eeb +3b86fd8d4c9f097a04885021f902a69cfc375eeb 367ffc5bdf35456922c1d3ceebbe633b65a65bcf,cdd5e92143e616f56b8b4ba90f6bc2114de0dee1 +cdd5e92143e616f56b8b4ba90f6bc2114de0dee1 c7d9089a6f8e857878fcdfda8b46b9034379dcf9 +c7d9089a6f8e857878fcdfda8b46b9034379dcf9 c7977972a11df8cb1ea188cf6cf7a30e71d4292f +c7977972a11df8cb1ea188cf6cf7a30e71d4292f ccab6e04aff4406711aecbfa9b41ea0a6349fb43 +ccab6e04aff4406711aecbfa9b41ea0a6349fb43 eeb358089d89aee9f2b1804a4c630ef42a231ee2 +eeb358089d89aee9f2b1804a4c630ef42a231ee2 e9a528680b234a33522c1b4f6d1719d95dda5b7e +e9a528680b234a33522c1b4f6d1719d95dda5b7e caed2ecdc2c88e2ee1572137ec4cc6fe38e632bd +caed2ecdc2c88e2ee1572137ec4cc6fe38e632bd b82fdf714f1b169991340004c60d758e09ba0fbf +b82fdf714f1b169991340004c60d758e09ba0fbf 2c22506f667e6c675af6256a6bcc5bf3519f68c3 +2c22506f667e6c675af6256a6bcc5bf3519f68c3 03755c29bfeaf4f4b6d00c21048eb5dd798e5cba +03755c29bfeaf4f4b6d00c21048eb5dd798e5cba 55a9a872eed80f88b6a2e2dd82da8d2822ae3fe6 +55a9a872eed80f88b6a2e2dd82da8d2822ae3fe6 f02d97f2923801d99f3dd769654032cb12ce7266 +f02d97f2923801d99f3dd769654032cb12ce7266 4c2b15c948deb5ac11fbd034872081dd93b029aa +4c2b15c948deb5ac11fbd034872081dd93b029aa 6fef3e6460425a7627a787fee924c8077ceae6b6 +6fef3e6460425a7627a787fee924c8077ceae6b6 03921a66f9001e8fbc4252a2c355763aef6b2198 +03921a66f9001e8fbc4252a2c355763aef6b2198 db55d34798110efd902302e670128e5860e4e820 +db55d34798110efd902302e670128e5860e4e820 c9f20f12f36bad0d76d71faaac64f7d1a45a610e,367ffc5bdf35456922c1d3ceebbe633b65a65bcf +c9f20f12f36bad0d76d71faaac64f7d1a45a610e 3d4fba2e820c1e62f2bc2822311388172aeece58 +3d4fba2e820c1e62f2bc2822311388172aeece58 681523dd88dc59a656b458bad144821ec5ac1411 +681523dd88dc59a656b458bad144821ec5ac1411 23a58a862f09874f9977dc7e56866c9537b25b3b +23a58a862f09874f9977dc7e56866c9537b25b3b 156279118f7b88026768cec53312a037e6361062 +156279118f7b88026768cec53312a037e6361062 8b3c7571c1376d5d6bf49935e2ecdb37ab18a82f +367ffc5bdf35456922c1d3ceebbe633b65a65bcf e1e57863eaf85b8ab3f383491a1ead12a9b46b79,e24a447e399223972ac25a520705a99221429b82 +e1e57863eaf85b8ab3f383491a1ead12a9b46b79 0193399945554a426feec8595486cbc212259970 +e24a447e399223972ac25a520705a99221429b82 0193399945554a426feec8595486cbc212259970 +0193399945554a426feec8595486cbc212259970 37d16ef457b144b699e5d0456a8110e697b0e892 +8b3c7571c1376d5d6bf49935e2ecdb37ab18a82f c3f58e0a36a34fc63b39a0e8b6dd714452a81b38 +c3f58e0a36a34fc63b39a0e8b6dd714452a81b38 462317ce59bff2956b603255c533579cd960e2c1 +462317ce59bff2956b603255c533579cd960e2c1 9d160839b2b6ef2f1f4ec697a4bb58595b9749ed,37d16ef457b144b699e5d0456a8110e697b0e892 +37d16ef457b144b699e5d0456a8110e697b0e892 9529e99c78d2bf1ffb1b0fd6d53f8e80c73eba17 +9d160839b2b6ef2f1f4ec697a4bb58595b9749ed 879965196f0456b5d09c387f51ad1aa8bc517b7e +879965196f0456b5d09c387f51ad1aa8bc517b7e 074a5dfda2c9ce4d5d98e092edef0214a15e1243 +074a5dfda2c9ce4d5d98e092edef0214a15e1243 a6e3ff583a14d4a5ca8d660859a00e7501a9a4bd +a6e3ff583a14d4a5ca8d660859a00e7501a9a4bd 6ba016ecfeaf3ae2aa56e66040cc96270b94b147,d0c812fcf1a7463a75a4b0821aad7b53a698ae94 +6ba016ecfeaf3ae2aa56e66040cc96270b94b147 51bf826840a8c9ae4cad2e8b5ef6d52183ede70f,9529e99c78d2bf1ffb1b0fd6d53f8e80c73eba17 +d0c812fcf1a7463a75a4b0821aad7b53a698ae94 51bf826840a8c9ae4cad2e8b5ef6d52183ede70f +9529e99c78d2bf1ffb1b0fd6d53f8e80c73eba17 164020026e3a719738a3bb388ed211c757b66327 +164020026e3a719738a3bb388ed211c757b66327 79f23e4a0a71efe4bcfd5d12194b5be8116b3d95 +79f23e4a0a71efe4bcfd5d12194b5be8116b3d95 7dbdcbf5a0b70e2610cc6a033d855cf49277c14b +51bf826840a8c9ae4cad2e8b5ef6d52183ede70f c9f5ad314ed551d772f67971e2bf31c41c86c692 +c9f5ad314ed551d772f67971e2bf31c41c86c692 cd0ae03e77f5e6b40577d94b4cad95beb0024205 +7dbdcbf5a0b70e2610cc6a033d855cf49277c14b 4021551b199416dec89ccf166f168aef66cf4607 +cd0ae03e77f5e6b40577d94b4cad95beb0024205 34c17b3528a056aa806b966b8fe2c875dcdfcf0f +34c17b3528a056aa806b966b8fe2c875dcdfcf0f 28423d419711ab263d31dffd54765ac939b04ed8 +28423d419711ab263d31dffd54765ac939b04ed8 4021551b199416dec89ccf166f168aef66cf4607 +4021551b199416dec89ccf166f168aef66cf4607 99e278145e3f48aa41d9eec257ed0e9682d80449 +99e278145e3f48aa41d9eec257ed0e9682d80449 a0e6c2fdcb7cc5b53a65c204e6aacd6a41980d60 +a0e6c2fdcb7cc5b53a65c204e6aacd6a41980d60 4e53ed2041f4640f0f9bd87af471042a56d55539 +4e53ed2041f4640f0f9bd87af471042a56d55539 f7368a81a94f513114cb2cc1fed5f0b72269356e +f7368a81a94f513114cb2cc1fed5f0b72269356e 1aa2709b5fa6242898d01a2c7a65dac7478a65f0 +1aa2709b5fa6242898d01a2c7a65dac7478a65f0 7458dc962f7de10c581e01d58ed10a190e725a95 +7458dc962f7de10c581e01d58ed10a190e725a95 7c99ac42bb0d578a369f60222222878bb4bb2cea +7c99ac42bb0d578a369f60222222878bb4bb2cea 5df054d940f33812707b7c4db2ecbabb88c007f9 +5df054d940f33812707b7c4db2ecbabb88c007f9 e37d51cfa5b7019e32b59051293ac069a7eb3c76 +e37d51cfa5b7019e32b59051293ac069a7eb3c76 36d5ae8d9f42524366b6f3e0766235258888f879 +36d5ae8d9f42524366b6f3e0766235258888f879 7e2466117d4b0a7b8d3c096d65254c3a72deaf4d +7e2466117d4b0a7b8d3c096d65254c3a72deaf4d 9fa5ffffd985c6c6835789649594f4c3eabe3e58 +9fa5ffffd985c6c6835789649594f4c3eabe3e58 070a358879597c688719a64957b27b06c6ae3470 +070a358879597c688719a64957b27b06c6ae3470 c7af076fb5441a6521944c470fcc7eb7e2379d1a +c7af076fb5441a6521944c470fcc7eb7e2379d1a fca9c83d5196974ec2583dc568cd6d4d13373700 +fca9c83d5196974ec2583dc568cd6d4d13373700 00f6f2a2c39c22d21672f6c7d906c690d0df8df4 +00f6f2a2c39c22d21672f6c7d906c690d0df8df4 2d41b2e87dc70ee208e16fb5dbdbddb807635f4d +2d41b2e87dc70ee208e16fb5dbdbddb807635f4d 844ff4c128bf32c32a02735411dbf058e5a1ed6b +844ff4c128bf32c32a02735411dbf058e5a1ed6b 224048bd1995aca9704c0bd8e3702b3da8d89b13 +224048bd1995aca9704c0bd8e3702b3da8d89b13 578c1ae2425620886ec2a98b800bdfc5a75fedd6 +578c1ae2425620886ec2a98b800bdfc5a75fedd6 201844bfafadb8adbb2f8e8b66d024d0798561c0 +201844bfafadb8adbb2f8e8b66d024d0798561c0 9b45090ffbfdaa2b89d848b421a48b2df083977e +9b45090ffbfdaa2b89d848b421a48b2df083977e e313d518c57ab333d2f81356e52ca3cf884672f0 +e313d518c57ab333d2f81356e52ca3cf884672f0 6f67e195394c055bd1f81e09f12dcd12b7b00594 +6f67e195394c055bd1f81e09f12dcd12b7b00594 e94599755425765da97442e9b266d93f465df718 +e94599755425765da97442e9b266d93f465df718 16da8558ede201d82667e5df765977aa99888f7b +16da8558ede201d82667e5df765977aa99888f7b 02787730a2e6787aeb1dc8cbd2d20e43925b9272 +6fa2e78406096d30186b3237e119aa7d40206316 9ab2add492901a823f238b673f091a011a259f95 +9ab2add492901a823f238b673f091a011a259f95 77cd1aff880b9ae014d9495bfc358095c1007049 +77cd1aff880b9ae014d9495bfc358095c1007049 a7636bcfcc51032fb33630218d9761b01c219465 +a7636bcfcc51032fb33630218d9761b01c219465 dde06b663fd358e1704ecf43df3465204be6a92e +dde06b663fd358e1704ecf43df3465204be6a92e 7e32aa8d9e0889efc2f30250e52aa82a832272a3 +7e32aa8d9e0889efc2f30250e52aa82a832272a3 69d1d314cd31b774f4336fa2c8906e4387696013 +69d1d314cd31b774f4336fa2c8906e4387696013 7ed5a5de192f37b2b56057b1d227d870c55eb769 +02787730a2e6787aeb1dc8cbd2d20e43925b9272 bce20f2af9049caf12c4cab893672a0c7db2f76a +7ed5a5de192f37b2b56057b1d227d870c55eb769 bf33407036998851ea0546470d52a8954d3df5b2 +bf33407036998851ea0546470d52a8954d3df5b2 841c3f498e72b482c6dc66631427ab1292cef062 +841c3f498e72b482c6dc66631427ab1292cef062 27e03ab10c5de7b1c9479842a274873824d726f0 +27e03ab10c5de7b1c9479842a274873824d726f0 b433734ae4d1cd0014708b7172d9cb16303105b9 +b433734ae4d1cd0014708b7172d9cb16303105b9 f7cdc16245d3f850767e0c1e4b4ec954d0fa0be4 +bce20f2af9049caf12c4cab893672a0c7db2f76a c5229569095ff3749bf58ea164ae082ef65a6937 +f7cdc16245d3f850767e0c1e4b4ec954d0fa0be4 830231e6626606438e35d7d4320cd5a449db60ad +830231e6626606438e35d7d4320cd5a449db60ad 88ef67d3eeb590a2f45277fa236264eeda6677f5 +88ef67d3eeb590a2f45277fa236264eeda6677f5 600378be441be44b2ec38356993736c374d604cf +c5229569095ff3749bf58ea164ae082ef65a6937 a7f72a923ae16e361ae18fc8473754ea2de4b1da +a7f72a923ae16e361ae18fc8473754ea2de4b1da 80a94ea109520c8cc719f9f7fb83e78f670a2c06 +80a94ea109520c8cc719f9f7fb83e78f670a2c06 c8e58c2956d3ae8924cea61bbfc83fd3f0914b6f +600378be441be44b2ec38356993736c374d604cf f27cf9f446e2c0181415ed25d55c5047200c63ef +c8e58c2956d3ae8924cea61bbfc83fd3f0914b6f e22603e687c8a3c0e025a432e8082431420c3d66 +e22603e687c8a3c0e025a432e8082431420c3d66 2454028ce7b5efdf6e1c7c467846d322c9b6e8c7 +f27cf9f446e2c0181415ed25d55c5047200c63ef 2daae45b51f3454a8f74d876ab6adf98e9fdf836 +2daae45b51f3454a8f74d876ab6adf98e9fdf836 27df8e8106135e2cd38975f36f07fdb4d944d484 +27df8e8106135e2cd38975f36f07fdb4d944d484 04fc782eae164945d7eca8c85d44ea51c525d547 +04fc782eae164945d7eca8c85d44ea51c525d547 577bbbab0b399075da217ec94d0521ae897185b3 +2454028ce7b5efdf6e1c7c467846d322c9b6e8c7 c165b411100e84002dded53504d2151a5fda47d5 +577bbbab0b399075da217ec94d0521ae897185b3 03fc95cacb87025a409d7dda22687770234e461f +03fc95cacb87025a409d7dda22687770234e461f dfa5ecc8d17d379e8e2961297d116b7d818c9075 +dfa5ecc8d17d379e8e2961297d116b7d818c9075 2415804df98278e66a8f2a3837ec93f4c7ca1823 +c165b411100e84002dded53504d2151a5fda47d5 64fa416b34d4225a42ca988820b6cd356dc0419b +64fa416b34d4225a42ca988820b6cd356dc0419b 8ec43965a7e5f43a9090442d36674c16595b9641 +8ec43965a7e5f43a9090442d36674c16595b9641 78105f5bdbb89ab66f1f2aa409e58d9c9a5cd59f +78105f5bdbb89ab66f1f2aa409e58d9c9a5cd59f 8a260ddbc7f6c72167041280ae17c74934db579b +2415804df98278e66a8f2a3837ec93f4c7ca1823 e057f70f5187dd2e058d15950be4eac0cd49e4ad +e057f70f5187dd2e058d15950be4eac0cd49e4ad c54ed87ce367cf35aaf0916a9d3bf7108a52477c +c54ed87ce367cf35aaf0916a9d3bf7108a52477c 3decad145bdb968c13959f6f2d7e6b85ca2079b7 +3decad145bdb968c13959f6f2d7e6b85ca2079b7 2c1a4adb23ced0b1be1e6b237573f08c48806cdf +2c1a4adb23ced0b1be1e6b237573f08c48806cdf 5c9f3ec17a904eb05e916b3bca595db7ffd12a0e +5c9f3ec17a904eb05e916b3bca595db7ffd12a0e 339aab0882a72b280c84f94b39d94e6f1b101b32 +339aab0882a72b280c84f94b39d94e6f1b101b32 740d248cf846ed8128931483a12247ed3a179813 +740d248cf846ed8128931483a12247ed3a179813 76caa1268409ae81c086266f91a1904711e90cc1 +76caa1268409ae81c086266f91a1904711e90cc1 b7a9734bdf60928400cdc3785c6c0e47ed4ca7fd +8a260ddbc7f6c72167041280ae17c74934db579b 368d761da8fa62ab3fed5bad2aa03bd156d4fd4d,33694be5f862fb551556bc292347983d3629009b +368d761da8fa62ab3fed5bad2aa03bd156d4fd4d 634c52d06c7fd44853ffba7bf5dce34256570a7f +634c52d06c7fd44853ffba7bf5dce34256570a7f b3fbd7024b3f06a8d4dd4bda1cad1c8614367514 +b7a9734bdf60928400cdc3785c6c0e47ed4ca7fd 7a5eb536d0e29f04d7927150d3e8bfa43150191f +33694be5f862fb551556bc292347983d3629009b e6e04b8c79af9dba388b2d7bdaaef52e4b46d1ee +e6e04b8c79af9dba388b2d7bdaaef52e4b46d1ee dc43b3418e799d4a28a530781b89111b32fea18f +dc43b3418e799d4a28a530781b89111b32fea18f b3fbd7024b3f06a8d4dd4bda1cad1c8614367514 +7a5eb536d0e29f04d7927150d3e8bfa43150191f 159145e9c371ad7bcab6f91856a06ad57afd509f +159145e9c371ad7bcab6f91856a06ad57afd509f 7f499ea08bb1f3f491aac185a980444ddb694d54 +7f499ea08bb1f3f491aac185a980444ddb694d54 b056a2ef6454c89441a49ff127e73ea1d3a5e4bc +b056a2ef6454c89441a49ff127e73ea1d3a5e4bc 8fb98dda5f358dfeca48c1d054fe474521ed8c45 +8fb98dda5f358dfeca48c1d054fe474521ed8c45 5f97e5ae8d8d44f424886e7dce0224698a157516 +5f97e5ae8d8d44f424886e7dce0224698a157516 566a3b0cf88b86bb0c2da1fea2ad970004d12d47 +566a3b0cf88b86bb0c2da1fea2ad970004d12d47 d6f3b7c58c9ec886897422a482ca25123ea92ccb +d6f3b7c58c9ec886897422a482ca25123ea92ccb 016c7dba29c59cccea17fb2a1bcc93a839cb38d9 +016c7dba29c59cccea17fb2a1bcc93a839cb38d9 792cf5fe01f5cf08c1c69bcc242b5ff0fa6e970d +792cf5fe01f5cf08c1c69bcc242b5ff0fa6e970d cfaa83fc7069a9cd0ee9d930b7d2c97042f517a0 +cfaa83fc7069a9cd0ee9d930b7d2c97042f517a0 3405d7b2dbfe7eb8f4bb9ce55fb4aa4298d820c4 +3405d7b2dbfe7eb8f4bb9ce55fb4aa4298d820c4 d22d4fa40848bafb724a0624c3d6d45da92f7982 +d22d4fa40848bafb724a0624c3d6d45da92f7982 074c36575043c530d29db1f9029aa9aecfc2df78 +074c36575043c530d29db1f9029aa9aecfc2df78 1773996e332e9fe68035384e4ea956345e5349aa +1773996e332e9fe68035384e4ea956345e5349aa 93858377ad386a94ea9d93b82725bcd351222921 +93858377ad386a94ea9d93b82725bcd351222921 23f8fa562020b18153f44fe614bfb6e10576c723 +23f8fa562020b18153f44fe614bfb6e10576c723 036b7a9d4e9ad3bc6ec6c8a009b7104708bf2ea4 +036b7a9d4e9ad3bc6ec6c8a009b7104708bf2ea4 6afd2e723ab6072f128b66ebdae01d4f84fdaf3c +6afd2e723ab6072f128b66ebdae01d4f84fdaf3c fde3cd0ad14f2e195c1dfd46a5ad3abf3bfd8f6d +fde3cd0ad14f2e195c1dfd46a5ad3abf3bfd8f6d 932f8e97c02dd4a1a6a905862ade47d5a33ecefc +932f8e97c02dd4a1a6a905862ade47d5a33ecefc 813b6b2b305151df1a237a4e3f9f3b3e2ca77efb +813b6b2b305151df1a237a4e3f9f3b3e2ca77efb b564e3a921293af1df4c6425823045d083ea7abc +b564e3a921293af1df4c6425823045d083ea7abc d684bd81f12e96d65885c9d23936bf313fdac673 +d684bd81f12e96d65885c9d23936bf313fdac673 9f0b57c507c1c8f7eff359e8ebd0047084138ff2 +9f0b57c507c1c8f7eff359e8ebd0047084138ff2 6b93274918649a6b61050d37c9aa787bb99b1db0 +6b93274918649a6b61050d37c9aa787bb99b1db0 5751790037c9a2a99b68388d884c2b514179d44a +5751790037c9a2a99b68388d884c2b514179d44a d64b4b4760be2163a0b5e0321248fd1635dc8277 +d64b4b4760be2163a0b5e0321248fd1635dc8277 ebaba5e3733c35203175a40998d9b6f11ade5217 +ebaba5e3733c35203175a40998d9b6f11ade5217 a8e82ae9f4bd20bea816b3be31549e58fb7a70e6 +a8e82ae9f4bd20bea816b3be31549e58fb7a70e6 232c8ec0e8f142e78bad8f775bd65054b4a6997b +232c8ec0e8f142e78bad8f775bd65054b4a6997b 01be4cf099557c79896956dcf4d0575cd97b71fd +01be4cf099557c79896956dcf4d0575cd97b71fd f83553313cf13c83e8bc13cf8d4c2f071e7a7145 +f83553313cf13c83e8bc13cf8d4c2f071e7a7145 22eaf9c6fa040e13c652928b8bd56797ca3c6ae5 +22eaf9c6fa040e13c652928b8bd56797ca3c6ae5 f22dab86da656a98303cfa4839907922ed3fbe52 +f22dab86da656a98303cfa4839907922ed3fbe52 082ff62d8007aee4c47867bc92261c623d536e83 +082ff62d8007aee4c47867bc92261c623d536e83 0df1257922823f33bc48f8d468825ac205477c7c +0df1257922823f33bc48f8d468825ac205477c7c 093e8bc8c2728655b17aeba753a25665ce1c4535 +093e8bc8c2728655b17aeba753a25665ce1c4535 d636d628b5a0f41bff89d72b66f374764f85fc69 +b3fbd7024b3f06a8d4dd4bda1cad1c8614367514 3eaa18cb5bd478a6d2dc747bef1073b29113abe8 +d636d628b5a0f41bff89d72b66f374764f85fc69 28468fe546a2cc9fd6650cac6a4064b70d0ebbe2 +28468fe546a2cc9fd6650cac6a4064b70d0ebbe2 07e5f0959111e1144339881645dd599bf793c9ca +07e5f0959111e1144339881645dd599bf793c9ca 6871dc0b7945ef34afd2eadd67f4d32e9a1f4105 +3eaa18cb5bd478a6d2dc747bef1073b29113abe8 8a70b57bea4d1e5312f8826ffa5f16417531bbae +6871dc0b7945ef34afd2eadd67f4d32e9a1f4105 b7b562b7b3af9671b0c986dcfdd98972607216a3 +b7b562b7b3af9671b0c986dcfdd98972607216a3 028f0d8c40e871fdf6ce62f08a8e5805d513c6a9 +028f0d8c40e871fdf6ce62f08a8e5805d513c6a9 77149209be527afd33c4f67b37e55cb5d64b982b +77149209be527afd33c4f67b37e55cb5d64b982b fc8c642fb9b81ae9bcbc73cf5e0036231e09f15b +fc8c642fb9b81ae9bcbc73cf5e0036231e09f15b 129edccbd5f34d3128bbb177bd104bad684d7eb4 +129edccbd5f34d3128bbb177bd104bad684d7eb4 a1f5573562dd58df7106703a41665b233bf82753 +a1f5573562dd58df7106703a41665b233bf82753 78799c8e556b479804fcf4b9cd8e487a405e90b5 +78799c8e556b479804fcf4b9cd8e487a405e90b5 1d3928260aa5e7503ca7ccdf71236c9849e51cff +1d3928260aa5e7503ca7ccdf71236c9849e51cff f6d852ea5423899a904625e7ffb4afbdf2dd3045 +3dee8c9dd39b25a661cb50f7ed4e9b5533de0489 9b6c3193e6f492c668c89846b83b3a6b0a8f0a7a +f6d852ea5423899a904625e7ffb4afbdf2dd3045 9b6c3193e6f492c668c89846b83b3a6b0a8f0a7a +9b6c3193e6f492c668c89846b83b3a6b0a8f0a7a 99551309fa5760491b267e1754c2ee79a9c31c6f +99551309fa5760491b267e1754c2ee79a9c31c6f dc7ab217fe2743658babab5613b2451356e448ed +dc7ab217fe2743658babab5613b2451356e448ed 0869d10a938cbcba1b028d87fd7a6cc843303683 +0869d10a938cbcba1b028d87fd7a6cc843303683 71a141e42eef4f86e4e1ce50b9aebbf5bf80b0ef +71a141e42eef4f86e4e1ce50b9aebbf5bf80b0ef 386b7b1848ab5f0babbbc73fa424b2514472e359 +386b7b1848ab5f0babbbc73fa424b2514472e359 2d1ae5e50841133cb6e39e5e60eb89c368b42ff0 +2d1ae5e50841133cb6e39e5e60eb89c368b42ff0 0ffb3c1a2bc275dd5482538586860091b97e9b5f +0ffb3c1a2bc275dd5482538586860091b97e9b5f 634d2c37e0e30b768fcf211d9ae70a6f4860cdf2 +634d2c37e0e30b768fcf211d9ae70a6f4860cdf2 a114850abbcb083dc50de6e75cadaeb9ba3ea54c +a114850abbcb083dc50de6e75cadaeb9ba3ea54c 54f26c491b0d2dd73fc2c9e7823e3aca72a9f5a2,8a70b57bea4d1e5312f8826ffa5f16417531bbae +8a70b57bea4d1e5312f8826ffa5f16417531bbae 65e88e7bdc2bf7140c941bb20d46cb5875ee35d9 +65e88e7bdc2bf7140c941bb20d46cb5875ee35d9 92c72d977c5f448716b94425e030b6f759d89ba3,78c9e0e0c54cab356975604dd664f0df46404580 +92c72d977c5f448716b94425e030b6f759d89ba3 a7fef27f05f019b017d6c204aabf432f42b9b40e +a7fef27f05f019b017d6c204aabf432f42b9b40e 61dc513a05232d6f7bb36636190b31cda11feace +61dc513a05232d6f7bb36636190b31cda11feace 57d0d68288770282c430fa37afeb360fd9425c8c +57d0d68288770282c430fa37afeb360fd9425c8c 84f39d59fbcb3bc49fa4c856d7126f1adc2f5d4a +84f39d59fbcb3bc49fa4c856d7126f1adc2f5d4a ffb3fa86c6fd6939f728d06b404414cfd9ef55d5 +54f26c491b0d2dd73fc2c9e7823e3aca72a9f5a2 5b4dacbff273c38e8706c3aa60a2121d18b3f7d3 +5b4dacbff273c38e8706c3aa60a2121d18b3f7d3 fcf5650f1fe9f9a54858beab9087c62539873b93 +fcf5650f1fe9f9a54858beab9087c62539873b93 b767764b1adf9413412a3572d33a40a548d30bf9 +b767764b1adf9413412a3572d33a40a548d30bf9 e300afb35f20d9867341f92c250e911729cc8453,ffb3fa86c6fd6939f728d06b404414cfd9ef55d5 +ffb3fa86c6fd6939f728d06b404414cfd9ef55d5 0d84db9635a9271fa8b4009346c38a35b266b914 +e300afb35f20d9867341f92c250e911729cc8453 38212a804adc593bc4386c7445e5932b618605a9 +38212a804adc593bc4386c7445e5932b618605a9 0d84db9635a9271fa8b4009346c38a35b266b914 +0d84db9635a9271fa8b4009346c38a35b266b914 ad4a6187780e93ca8e49892b4c9b787fc18ab4cb,3e30a989772d3d1931bbe7a7065a905be61385c8 +ad4a6187780e93ca8e49892b4c9b787fc18ab4cb 1153bc2fbaf02086ad2b989accba68e6a9cb5ab5 +1153bc2fbaf02086ad2b989accba68e6a9cb5ab5 8f2462ead6441802a313373831c049a10465ba73 +8f2462ead6441802a313373831c049a10465ba73 7c04317658e9e33cc13113d833b0dff1c92c134e +3e30a989772d3d1931bbe7a7065a905be61385c8 16ede37af50bf397cb08a4b83766a7c7465857d9,7c04317658e9e33cc13113d833b0dff1c92c134e +7c04317658e9e33cc13113d833b0dff1c92c134e 20a8d29b9b4732f0aaa19129e9fa35cb95404edc +20a8d29b9b4732f0aaa19129e9fa35cb95404edc 931244e94b062bb1a9d7af0078fc55465079d14c +16ede37af50bf397cb08a4b83766a7c7465857d9 c4b5049ef650faded2af059d1e2dd2357f917a77,641de07eb28ec9fc09db6a32cf9c82908a8f8fdd +c4b5049ef650faded2af059d1e2dd2357f917a77 741ee4b6a72d021b97712a303f6b3dfd5e91e379,e9444e85d37ef71fae8264684e627d14ccdb0e34,931244e94b062bb1a9d7af0078fc55465079d14c +931244e94b062bb1a9d7af0078fc55465079d14c 769eada4588c4c14812c10d8bfcec36e169b46c5 +741ee4b6a72d021b97712a303f6b3dfd5e91e379 769eada4588c4c14812c10d8bfcec36e169b46c5,1fe765631fd96ed6e04304818a102c7a232d106e +769eada4588c4c14812c10d8bfcec36e169b46c5 702e56f5a226458ce02fba6c18902b0b7bef2926 +702e56f5a226458ce02fba6c18902b0b7bef2926 b2688e276938c63f0e83343755c96e4ee87dcc8d +b2688e276938c63f0e83343755c96e4ee87dcc8d e45a9670135d682a6a5f2af660950a6b8b2f589c +e45a9670135d682a6a5f2af660950a6b8b2f589c f20587918bc5e1886f910058e5189d33ca07e2bb +f20587918bc5e1886f910058e5189d33ca07e2bb ae80d00cc7e94dbfbe164d9a63022f16c61082b2 +ae80d00cc7e94dbfbe164d9a63022f16c61082b2 eb90f6fe980d47e0aeec5e24b106ff77ee4373bf +eb90f6fe980d47e0aeec5e24b106ff77ee4373bf 2e84f80306de8d059a99affe97a6566244630b50 +2e84f80306de8d059a99affe97a6566244630b50 ffaeb9b69270c01c528394cb080e2ba815b0413b +ffaeb9b69270c01c528394cb080e2ba815b0413b ec5345e6ecc7783dee188df0d4eae343912d9eac +ec5345e6ecc7783dee188df0d4eae343912d9eac 731033a46a8632934c70c4a5aa1d354e91e2619f +731033a46a8632934c70c4a5aa1d354e91e2619f 37a2da3f610d19d28099467f73fabe68713dd44b +37a2da3f610d19d28099467f73fabe68713dd44b f08db11c36260ef555311695aef4290b4e6a22ee +f08db11c36260ef555311695aef4290b4e6a22ee af3a660dfbb6065dafea4b91677da02ef8398f7a +af3a660dfbb6065dafea4b91677da02ef8398f7a 19f2bc121f642d42ac3ccfab583566cc567bf0b0 +19f2bc121f642d42ac3ccfab583566cc567bf0b0 a36cdd0820c18f70ccc19e284c4b81dd1b8be2a1 +a36cdd0820c18f70ccc19e284c4b81dd1b8be2a1 00665c494078299dd945b4c438f8d7644cd04608 +00665c494078299dd945b4c438f8d7644cd04608 965c3fa0774eee49c5d8a6b128cf820a41f95fb6,f66fad5ea749f3df400e17e58c347b99e380a2dc +965c3fa0774eee49c5d8a6b128cf820a41f95fb6 059415e777ed0967b88997c5e11f10e417024926,f7a5f0b8f14cda009733dc89a69c97a60a7ee4fe +059415e777ed0967b88997c5e11f10e417024926 d3caf011b4c7ec0b40cadc97bd5d619654e5d03b,f66fad5ea749f3df400e17e58c347b99e380a2dc +d3caf011b4c7ec0b40cadc97bd5d619654e5d03b 2c08c1f7c0493877c114715633c59bc2381a1113 +f7a5f0b8f14cda009733dc89a69c97a60a7ee4fe b129805ac85708a12a222c298b9c361f6ccf116d +2c08c1f7c0493877c114715633c59bc2381a1113 49469ad16e121ddc47ac2cb268a71f5fe4e84e2f +49469ad16e121ddc47ac2cb268a71f5fe4e84e2f 1aaf1064c64285d7466f05f2521d0a3554ea5fb0 +1aaf1064c64285d7466f05f2521d0a3554ea5fb0 eecf6b993e5deb874410fa317bb020d3b68b76e1 +eecf6b993e5deb874410fa317bb020d3b68b76e1 57d7865ae2c1a2a34822f253dcf9655e2e65de5c +57d7865ae2c1a2a34822f253dcf9655e2e65de5c 0be89c389a4609197fe89dcda300528fc8c35c5a +0be89c389a4609197fe89dcda300528fc8c35c5a b129805ac85708a12a222c298b9c361f6ccf116d +b129805ac85708a12a222c298b9c361f6ccf116d f3be772e6ca62c38a11429c4c833cb038efe88e4 +f3be772e6ca62c38a11429c4c833cb038efe88e4 2cf2b7b1449efe706e802779e083fe6b358450b5,234608b6ff336c17a62e728fa8940e81393ef2d9 +2cf2b7b1449efe706e802779e083fe6b358450b5 44b91abd1f8477a45c7e257a51f5053e1fa207e1 +44b91abd1f8477a45c7e257a51f5053e1fa207e1 ca9da88e3e855c589ccb1d55c6661c76724b5279,1b5d412efbfb5634ce7799a505afe4925825df0f +ca9da88e3e855c589ccb1d55c6661c76724b5279 e03d5c75f8af0be58e38b630f20de226de34a355 +e03d5c75f8af0be58e38b630f20de226de34a355 231a14dc2dd954ba25edc51a72e662daa53a192e +231a14dc2dd954ba25edc51a72e662daa53a192e ec43e24ac438d698688e9afdd1a8e5edac65d67d +ec43e24ac438d698688e9afdd1a8e5edac65d67d 351fd3ff4fd7df647baa430e6ed5a131824d655d +351fd3ff4fd7df647baa430e6ed5a131824d655d ac8a516285c3fc79a272f935794a42e06621b46f +ac8a516285c3fc79a272f935794a42e06621b46f 3a76f000c0bfa520b3b8d28b68d118caf37ef60d +3a76f000c0bfa520b3b8d28b68d118caf37ef60d b7dfc5691b1deb29ddc0ff2d0d8417914960581f +b7dfc5691b1deb29ddc0ff2d0d8417914960581f ab579cdb7a3bc9bca352591376aa7ac11ffe871b +ab579cdb7a3bc9bca352591376aa7ac11ffe871b db1d22eadb8a586d7fc580a3d82029bdf7443d3c,8e9712a5d398a9fe5f8934af787d5d5d95a49a15 +db1d22eadb8a586d7fc580a3d82029bdf7443d3c f61052be3c1cb795806f4c8895add22d6d1c9bf8,1550ea7ddf75b4478f9cf8719b00fc1cafa26a1e +f61052be3c1cb795806f4c8895add22d6d1c9bf8 8293650fcd428a498d500053f6d145e51b6ca526,2ea9ce81b49510a06465aa57e03fa9f5846abed7 +8293650fcd428a498d500053f6d145e51b6ca526 6fbc0a6bcf00bdf91d1ad9d133b34a29751ae9df +6fbc0a6bcf00bdf91d1ad9d133b34a29751ae9df 2be9e621916f2895bc52f74d45a2c65b0d10f91c +2be9e621916f2895bc52f74d45a2c65b0d10f91c c038aff905aa4ecad62a1da3d559d4bbd7ed2204,fe83540f6ad304de3f03fda268112557485781de +c038aff905aa4ecad62a1da3d559d4bbd7ed2204 28de54b8dbfb3b2e5038fb59ab43ecf869733e70 +28de54b8dbfb3b2e5038fb59ab43ecf869733e70 61b1af2634de8b4dd1da756c3c7a57620b517aa6 +61b1af2634de8b4dd1da756c3c7a57620b517aa6 54a615c4aafa3617e6a60b911277ed87d163a162 +54a615c4aafa3617e6a60b911277ed87d163a162 16e5e51d776f635f0aeec080a5e4c26645cf83f6 +16e5e51d776f635f0aeec080a5e4c26645cf83f6 4b37eea7d09d818497b7fdaca5f139d64823e288 +4b37eea7d09d818497b7fdaca5f139d64823e288 002d037cb3d0cbab979b4e2e14b09e16ab2c76ee +002d037cb3d0cbab979b4e2e14b09e16ab2c76ee 183f89d3457c45a95e5a70bd77943526eb59e45f +183f89d3457c45a95e5a70bd77943526eb59e45f fa5f74982be4138bda1124183612e353bfe37503 +fa5f74982be4138bda1124183612e353bfe37503 3a179173299d7fdbd0cdeb64095bdd889ae3994f +3a179173299d7fdbd0cdeb64095bdd889ae3994f d9ba150235432800ddbd88b1c1d36ec2d1fb3169 +d9ba150235432800ddbd88b1c1d36ec2d1fb3169 7ef81d8632ba5534eba2e00152396bf19fae1066,589e316b300ba53abd4c61730283ec7a3026de79 +7ef81d8632ba5534eba2e00152396bf19fae1066 7b1e0451690771f00400b797fbda41496c3941b0 +7b1e0451690771f00400b797fbda41496c3941b0 73cb4bf58e99c6154baa6981ca3e144c4bcbd03c,1d106be1728ca9ca36f72f9c60f0238bdba094e7 +73cb4bf58e99c6154baa6981ca3e144c4bcbd03c 2aaccbd409e28b08e66b8271cce18279d363d982,1b4e30d106adb0ba869c736335aede5e1fd7359d +2aaccbd409e28b08e66b8271cce18279d363d982 31c8ca7f7868fc612e50a40a8b336abfe59947c2,ef2ec4a2aa8bbc0c3f805b815729f8b3430ac207 +adbeb66c05311ae7dd12044e50ffe30a7bac4d5c e52f8b2513cf17879f6a00d912aa445b35a45d76 +31c8ca7f7868fc612e50a40a8b336abfe59947c2 081ae45cc81c7d9bbcf14dbf11e947868786f4ca +081ae45cc81c7d9bbcf14dbf11e947868786f4ca 8fe99604383456d3e09bf637076453d9c103690f +8fe99604383456d3e09bf637076453d9c103690f 29f35f475c1ed2287f876308834d179cd39611ca +e52f8b2513cf17879f6a00d912aa445b35a45d76 0c8e6ec6fdc3c7fbab8ca602f6aeb6cf430add71 +0c8e6ec6fdc3c7fbab8ca602f6aeb6cf430add71 bea6ae9a16fa70b27d1b341e7c280af1e97e31c0 +bea6ae9a16fa70b27d1b341e7c280af1e97e31c0 13061daea933c0ca8871abf3aa7d09a75b224706 +13061daea933c0ca8871abf3aa7d09a75b224706 e69f5bdf52f9b9757fc8db839951fa114296d6b4 +e69f5bdf52f9b9757fc8db839951fa114296d6b4 e7f856437160ec8916590616ec6f4b3fd17ce57d +29f35f475c1ed2287f876308834d179cd39611ca 55bfa73d283ae904ae5cea04b8b27e6c3a75eb3a +e7f856437160ec8916590616ec6f4b3fd17ce57d 977b907588e312b9feb26c3c49f168aaec0ac0e1 +977b907588e312b9feb26c3c49f168aaec0ac0e1 e0622d9f3d96c83e832c2e833c3d619e1ce765dd +e0622d9f3d96c83e832c2e833c3d619e1ce765dd b28d552c97adc2d965ab7babf7c890e56e4eb4ce +b28d552c97adc2d965ab7babf7c890e56e4eb4ce 366547935e9b654834b37a1cf05cf02a8bf1bbb0 +366547935e9b654834b37a1cf05cf02a8bf1bbb0 86a0fe717f7d121df52f81d3b4447c6d89d68c63 +86a0fe717f7d121df52f81d3b4447c6d89d68c63 20ab92b6e4a54fbc9f880852cbea28dc4a880f08 +20ab92b6e4a54fbc9f880852cbea28dc4a880f08 439caadb720f77df4157a7622ec441c6a01c6890 +439caadb720f77df4157a7622ec441c6a01c6890 82da6b65d8f801579b16415c2d2bc937694dbabd +82da6b65d8f801579b16415c2d2bc937694dbabd e660d445bedeea6fc21810ef805b072b12056719 +e660d445bedeea6fc21810ef805b072b12056719 f8012076472f9a344abd6e7bafe3fd87c8714c47 +f8012076472f9a344abd6e7bafe3fd87c8714c47 959864784f3e7cf5452de90a774c7772eb3f7e51 +959864784f3e7cf5452de90a774c7772eb3f7e51 6899c9d176819ece27b00273876bea0647978d87 +6899c9d176819ece27b00273876bea0647978d87 723893d25c365adf9a50c309bd86458bad42e854 +723893d25c365adf9a50c309bd86458bad42e854 3484aad0053fc732860b110832ad11b445a45a20 +1d106be1728ca9ca36f72f9c60f0238bdba094e7 b5a0ecc65a1717a86364171529faf7352cd06bff,55bfa73d283ae904ae5cea04b8b27e6c3a75eb3a +3484aad0053fc732860b110832ad11b445a45a20 da6d7b66552aac978cb586e2851fb56dfd167326,55bfa73d283ae904ae5cea04b8b27e6c3a75eb3a +da6d7b66552aac978cb586e2851fb56dfd167326 b0a3cd70ab279e18883552db4a58982f84247294 +b0a3cd70ab279e18883552db4a58982f84247294 60b0f467ffc8670113b608b2ddbf88278a8a4ecf +60b0f467ffc8670113b608b2ddbf88278a8a4ecf b5a0ecc65a1717a86364171529faf7352cd06bff +55bfa73d283ae904ae5cea04b8b27e6c3a75eb3a 582b7fa0fbd2cecebceaa05b153860a49174d68f +582b7fa0fbd2cecebceaa05b153860a49174d68f 7566f2bf71d40b4db4e7c42a4ed5b9604f5cc01c +7566f2bf71d40b4db4e7c42a4ed5b9604f5cc01c c7a72a621149e788759cc375d5edf021a4eb35b5,06d1c273aab289fb1085e2d470c892222ca9086b +c7a72a621149e788759cc375d5edf021a4eb35b5 4952641dd93462e7fde19779ba307e3e8e970816 +4952641dd93462e7fde19779ba307e3e8e970816 3c893a4210512daa70e7c955633e824f84d32d30,017981efcd5dbe3b7a59e19a0b8b1b3345a3deb9 +017981efcd5dbe3b7a59e19a0b8b1b3345a3deb9 900b334740ad45bcbcfc7421e0703a51890f05c5 +900b334740ad45bcbcfc7421e0703a51890f05c5 d9e675ce754550947c6e46586afc9705499a27fb +d9e675ce754550947c6e46586afc9705499a27fb 3c893a4210512daa70e7c955633e824f84d32d30 +b5a0ecc65a1717a86364171529faf7352cd06bff 1254c88236907d47f7445c3f21ddb2606a3ea264 +1254c88236907d47f7445c3f21ddb2606a3ea264 542b91337514945425da3d5722a87c0564d068c8,3c893a4210512daa70e7c955633e824f84d32d30 +3c893a4210512daa70e7c955633e824f84d32d30 d26d705d6d4ae7234ee0a81b5ade3861e21abf15 +542b91337514945425da3d5722a87c0564d068c8 50ea23ff376618ba330117cf27c0d105f4e4e35b +50ea23ff376618ba330117cf27c0d105f4e4e35b d26d705d6d4ae7234ee0a81b5ade3861e21abf15 +d26d705d6d4ae7234ee0a81b5ade3861e21abf15 ac0148ceafdaced62f5dfa03eaabb657185608de +ac0148ceafdaced62f5dfa03eaabb657185608de 430f66247caec1a031a28b997f05a6f84155adda +430f66247caec1a031a28b997f05a6f84155adda 1f6bb250f849ccfceb3ca03d383913896c7ca04b +1f6bb250f849ccfceb3ca03d383913896c7ca04b 6d8663e1519c3c38126b6b35a7dc51d10692b558 +ed59d297988963292cb5f31798edb2c095027d2c c6ecb4ee03f6726df71fd4c74448315bdd31c285 +6d8663e1519c3c38126b6b35a7dc51d10692b558 32331b404a5e8fd77f7f83a15ef6e0dad4556959,85039c3ea470a14df0c2ce193ed4bc101b0ba761 +85039c3ea470a14df0c2ce193ed4bc101b0ba761 32331b404a5e8fd77f7f83a15ef6e0dad4556959 +c6ecb4ee03f6726df71fd4c74448315bdd31c285 32331b404a5e8fd77f7f83a15ef6e0dad4556959 +32331b404a5e8fd77f7f83a15ef6e0dad4556959 16c73ccb256348cf2de008746ea8d8a61c164173 +16c73ccb256348cf2de008746ea8d8a61c164173 8fddfd8f37adc66bdca13e41909e34bfe95ca285 +8fddfd8f37adc66bdca13e41909e34bfe95ca285 c066b7977151553d9ec37f5db8eb3776ee1d8c88 +c066b7977151553d9ec37f5db8eb3776ee1d8c88 738e6abeed9a984f31700812d084cd6ec40fe47d +738e6abeed9a984f31700812d084cd6ec40fe47d 59a626c53fe61faf9fd4a1565814c0087d38e8b0 +aefba9d5f100edcf3c42a787563a2c231f7d27a6 99dec402d5e4207653a81fb914c06cfb50359d7c +99dec402d5e4207653a81fb914c06cfb50359d7c 86beaad7468f163c3efd9f7f224e29768bfbbf0e +86beaad7468f163c3efd9f7f224e29768bfbbf0e 386832d44235c0915bd0c59098ed39eeadc5d789 +386832d44235c0915bd0c59098ed39eeadc5d789 adb0f2f99cc50f48d0c1be93f04c78f2ed71f9e3 +adb0f2f99cc50f48d0c1be93f04c78f2ed71f9e3 f2aaee910053f7f2803ae67858011d7aaa50a1bd +f2aaee910053f7f2803ae67858011d7aaa50a1bd 884a77869d8281d66058ef769c4f880fb6f51865 +884a77869d8281d66058ef769c4f880fb6f51865 8a363f876e77ab3e144a67ef3120384b6b1b513c +8a363f876e77ab3e144a67ef3120384b6b1b513c 59a626c53fe61faf9fd4a1565814c0087d38e8b0 +59a626c53fe61faf9fd4a1565814c0087d38e8b0 4c0b5593dd64f4f03ea32ee9d1853347fa022db8 +4c0b5593dd64f4f03ea32ee9d1853347fa022db8 a5596b73e4822e25faf10acd35abf01b9b111b07 +a5596b73e4822e25faf10acd35abf01b9b111b07 5834a7acc8eaf3139a43dac4f56bb59a9c4679e8 +5834a7acc8eaf3139a43dac4f56bb59a9c4679e8 74324f583bc9dd7317a7c31cc6a3fd754693a903 +74324f583bc9dd7317a7c31cc6a3fd754693a903 eb63661bd1476f9156c6cf61534644f5b2d7b6bc,71d89918c0e5efb435591a5e25dd67b157540146 +71d89918c0e5efb435591a5e25dd67b157540146 934132ed7c6b885d00911062f5e0d2cad1032f8b +934132ed7c6b885d00911062f5e0d2cad1032f8b edcc532c167c4ae2b74d6cbbe040ae356e1862f3 +edcc532c167c4ae2b74d6cbbe040ae356e1862f3 a647090d9409d12c72248d6b4a20ad38d252214a +a647090d9409d12c72248d6b4a20ad38d252214a eb63661bd1476f9156c6cf61534644f5b2d7b6bc +eb63661bd1476f9156c6cf61534644f5b2d7b6bc dbcb3cf9a959924a84fdc7cf79d1887c5e95f4dd +dbcb3cf9a959924a84fdc7cf79d1887c5e95f4dd b2e6ae7b8938c2518d58179bf92c54d7454c5243 +b2e6ae7b8938c2518d58179bf92c54d7454c5243 a4dbbfa5fddfc3e167a1b4c05e57336b05ee9222 +a4dbbfa5fddfc3e167a1b4c05e57336b05ee9222 22faaf83686db877ff9058220271ba8827717a9b +22faaf83686db877ff9058220271ba8827717a9b 2b11d3acea19d9917ac6a3b11c71e44d52c200d3 +2b11d3acea19d9917ac6a3b11c71e44d52c200d3 866681b74e95b997147b99c51e07da5d60feb432 +866681b74e95b997147b99c51e07da5d60feb432 494eadce2e32082499eddbf082ccc0e49ece3466 +494eadce2e32082499eddbf082ccc0e49ece3466 c45b0ca87c2b86f41f14bac0b162a446681aa601 +c45b0ca87c2b86f41f14bac0b162a446681aa601 11a467a8ef91545bb242890660b7c1ed16481f55 +11a467a8ef91545bb242890660b7c1ed16481f55 be6116e971bb865603ed4a6c8f83bd691c54422a +fff83466f384a50a9cdbc24fdbec64fbe97b397b be6116e971bb865603ed4a6c8f83bd691c54422a +be6116e971bb865603ed4a6c8f83bd691c54422a 38764bf86da93d5795e40d18947e4c6a8d71842f +38764bf86da93d5795e40d18947e4c6a8d71842f 566569e56f5ce387da9bd1238e12e4a4673193a9 +566569e56f5ce387da9bd1238e12e4a4673193a9 33cf143a502e8422991ffd33794c4344e3cfd733 +33cf143a502e8422991ffd33794c4344e3cfd733 2a51bc466941c8e4cc79a790df3b41f94efe902e +2a51bc466941c8e4cc79a790df3b41f94efe902e 67b2c7d27d32bc86e5c85546911865e6d53cbbd2 +67b2c7d27d32bc86e5c85546911865e6d53cbbd2 d12eb7e791044c266d07998cd4e302390f73c881 +d12eb7e791044c266d07998cd4e302390f73c881 5d8a2f9b91d23ef0302b3adf7c8c307a138eb03e +5d8a2f9b91d23ef0302b3adf7c8c307a138eb03e 6c93b89220d50081c68cfcc49a18b3f413c91044 +6c93b89220d50081c68cfcc49a18b3f413c91044 6733bbf4a7a0255f2134f3bc7013a3a0b44d9723 +6733bbf4a7a0255f2134f3bc7013a3a0b44d9723 e669693ecfde3d8f65b6f79da4c0a5275908855a +e669693ecfde3d8f65b6f79da4c0a5275908855a 0a8c497528261aa173658da4e2b416b3a58071f8 +0a8c497528261aa173658da4e2b416b3a58071f8 058bef15102031f9c04c7887b6497986f722513c +058bef15102031f9c04c7887b6497986f722513c e4339a3c50515554d514886f630f68557ccc57a3,7a8dbd329924b2c3a1c5b3dd7a754ae677995f25 +7a8dbd329924b2c3a1c5b3dd7a754ae677995f25 52591d24f412f3dedf650c931009dfe99dd74b3e +e4339a3c50515554d514886f630f68557ccc57a3 1b80dd0400d1deace38ef139ff02ff621f785bdf +1b80dd0400d1deace38ef139ff02ff621f785bdf fd4c0d8701b7646e93dba00409e9022dac714827 +52591d24f412f3dedf650c931009dfe99dd74b3e fb7e6638f82b75f13d06d9695667992eba806073 +fd4c0d8701b7646e93dba00409e9022dac714827 b04e689404c660fdf6727bf2645dd515f6a2fed4 +b04e689404c660fdf6727bf2645dd515f6a2fed4 83edad0b8e3b7d7932fa579d0dce19b074773b29 +83edad0b8e3b7d7932fa579d0dce19b074773b29 10d6c50ecd62eaaf8476fd1f7878a7e6a4b9bf0f,27a8f638a910eca20e09ad51deb3ea22182077e8 +10d6c50ecd62eaaf8476fd1f7878a7e6a4b9bf0f 97716c5057503600ac267505e910b7b601c2ae26 +97716c5057503600ac267505e910b7b601c2ae26 fb7e6638f82b75f13d06d9695667992eba806073 +fb7e6638f82b75f13d06d9695667992eba806073 d55ba5cbfdf0cb089cdb58a32d7aaea623fef1ed +d55ba5cbfdf0cb089cdb58a32d7aaea623fef1ed 6f7d6654c501279e136dae443ed655021fc25124 +6f7d6654c501279e136dae443ed655021fc25124 949d5407dbad5db056abd5b028a9cdce2c3eae58 +949d5407dbad5db056abd5b028a9cdce2c3eae58 6139430731c2e3daf64bf3515effab4064da2eef +6139430731c2e3daf64bf3515effab4064da2eef c1e7660763b4416639fb0e35b58f290da1a854e5 +c1e7660763b4416639fb0e35b58f290da1a854e5 c260f8f3ea5df6be3602ccddc140193ba64443fd +c260f8f3ea5df6be3602ccddc140193ba64443fd 2f6d498c71980333cb734d6a1226e8ebd46b2bef +2f6d498c71980333cb734d6a1226e8ebd46b2bef 10a8cb99bfe2b89a84510196977d3a6c9401e78c +10a8cb99bfe2b89a84510196977d3a6c9401e78c f4e6b4ecb213799fe9ebfaff2799b803eb4fa53d +f4e6b4ecb213799fe9ebfaff2799b803eb4fa53d 6b4a7cf4a41521712a2d8076f3d20acc84111f61 +6b4a7cf4a41521712a2d8076f3d20acc84111f61 96a83f9ea5e62c9adced7d43f9818eb86e832d25 +96a83f9ea5e62c9adced7d43f9818eb86e832d25 5a7b531a5237bc6f9d8ccdf4ead5db55a8017ce2 +5a7b531a5237bc6f9d8ccdf4ead5db55a8017ce2 ac5c30cfa9a0af5aa442b6cf1c3cb60809e6ae9f +ac5c30cfa9a0af5aa442b6cf1c3cb60809e6ae9f eed93e593410ead2dfb213c22cd4d461d748caf5 +eed93e593410ead2dfb213c22cd4d461d748caf5 681c4c04e0479999d9c39ba33a6c961c5f21e932 +681c4c04e0479999d9c39ba33a6c961c5f21e932 268ce73e8a93b35c48177f348e55e2b09ecf2ac2 +268ce73e8a93b35c48177f348e55e2b09ecf2ac2 91fc43b9f0070cc6c64f813846a19dc38e5885fe +91fc43b9f0070cc6c64f813846a19dc38e5885fe c4eadcfc06eeb2f82f7e84ebf3c1eede03f20c65 +c4eadcfc06eeb2f82f7e84ebf3c1eede03f20c65 50a6d511213fbb79c2105e6478e0a0c89ae32dff +50a6d511213fbb79c2105e6478e0a0c89ae32dff 55ad7b5c0301c04c61f781ec2e7c760eda44b8a5 +55ad7b5c0301c04c61f781ec2e7c760eda44b8a5 c64db4cd71340dec95f5e1fb95ce7a5c4b783cbd +c64db4cd71340dec95f5e1fb95ce7a5c4b783cbd e15d743b85df021b3c3a8af77165c81db0684ed8 +e15d743b85df021b3c3a8af77165c81db0684ed8 8a75426772eb59bd97a9657c5e622a4e934eecb7 +8a75426772eb59bd97a9657c5e622a4e934eecb7 7011408fb5511bc3278fa56429b2f4a43819dcc3 +7011408fb5511bc3278fa56429b2f4a43819dcc3 ee1d5c9fac14e0c5a23f0b1479968d535cb361ce +ee1d5c9fac14e0c5a23f0b1479968d535cb361ce a3760325d1d17ed96dc4138ae6e1f32bb3107f90 +a3760325d1d17ed96dc4138ae6e1f32bb3107f90 0323ded23f0f2937f939f8cb935a0529d1eac99c +0323ded23f0f2937f939f8cb935a0529d1eac99c 5cda9f73463a504d040ccce183bcfc3d1239fcd6 +5cda9f73463a504d040ccce183bcfc3d1239fcd6 aa94695956a625174f6d85c2f566a81c4107867e +aa94695956a625174f6d85c2f566a81c4107867e 03d9a6fefa74839a49232900092f7c5b1a4e53d9 +03d9a6fefa74839a49232900092f7c5b1a4e53d9 abf642e1fb04d7765589d5599e0de281bb92029e +abf642e1fb04d7765589d5599e0de281bb92029e 0c15178d6d1f09ff8f09fa430bc73adaab1d2d62 +0c15178d6d1f09ff8f09fa430bc73adaab1d2d62 708a0404a7604d2efcede5917e3254725bc86acf +708a0404a7604d2efcede5917e3254725bc86acf e174a07c36829083e912566dcd3907aa9bc83877 +6929385e83c3c54019e85e5eb4094d0c4fcbcb21 e174a07c36829083e912566dcd3907aa9bc83877 +e174a07c36829083e912566dcd3907aa9bc83877 754913fd32aa45542db1ef62fa4a9652b936fc29 +64c9c79a950c8a37d631cf7ea078270ac4eca7d9 1519ed155c9c1400fd579bc02cb50e1c47a3a56b +754913fd32aa45542db1ef62fa4a9652b936fc29 0251c2384e7f1b247cb63560c5ef1b5a7ad6331c +0251c2384e7f1b247cb63560c5ef1b5a7ad6331c 8e8dd3185e704f0b699e8712e1d4e1b4bbc94439,7a74b8e95278601116074b745efb8cc0cda35be5 +1519ed155c9c1400fd579bc02cb50e1c47a3a56b 5fb5dbfbf78c969ff4590c7d5e6ee60a98d6a256 +5fb5dbfbf78c969ff4590c7d5e6ee60a98d6a256 3200899a59caa8666a805583b2c0ea3228931542 +3200899a59caa8666a805583b2c0ea3228931542 39082cc602697fab98b65fa1a07daa276f31d1d0 +8e8dd3185e704f0b699e8712e1d4e1b4bbc94439 087b1eac2a1b7f3034e6eb39ba4fa6bb545ed25b,cb3bbc9d2e0a39c37bce340972c524a3b0c8e77f +087b1eac2a1b7f3034e6eb39ba4fa6bb545ed25b 1dd24dcdda7d20f38bd88a0c2c01a4283d0e3eb0 +39082cc602697fab98b65fa1a07daa276f31d1d0 a00177454224cbad76c210cdb433359f7628ff07 +a00177454224cbad76c210cdb433359f7628ff07 8f16c927857bc68a2d317d10641842e5ae4f475e +8f16c927857bc68a2d317d10641842e5ae4f475e 8abfd3775131b06db3b745f1c67a3b9ad5bba6ec +8abfd3775131b06db3b745f1c67a3b9ad5bba6ec 992c83b80ddbf4d0dbd67afd1f5cb0050d9bbacb +992c83b80ddbf4d0dbd67afd1f5cb0050d9bbacb 7a74b8e95278601116074b745efb8cc0cda35be5,00b438b957bdfbe2385f11cbd189ab5ddb02b05c +00b438b957bdfbe2385f11cbd189ab5ddb02b05c eb1aa9c1230160fe1a8cf99c5943c0c19cc4c82d,7a74b8e95278601116074b745efb8cc0cda35be5 +eb1aa9c1230160fe1a8cf99c5943c0c19cc4c82d a32edcfb82854905ee5d3efd3a59c158209c4b16 +7a74b8e95278601116074b745efb8cc0cda35be5 2741d9eb4fd52f98b05fc33534428c226c016bef +a32edcfb82854905ee5d3efd3a59c158209c4b16 c6224b1a9100e05cc5850b3dd5bcdab4c705fbed +2741d9eb4fd52f98b05fc33534428c226c016bef c661628acbf41075ef824a737bc225f6f173a0c6 +c661628acbf41075ef824a737bc225f6f173a0c6 56e69f81e0f86eb66f9ab620298f00e4613232d2 +c6224b1a9100e05cc5850b3dd5bcdab4c705fbed ac6f23131f686339af403d236dac13c1fd6f2e14,56e69f81e0f86eb66f9ab620298f00e4613232d2 +56e69f81e0f86eb66f9ab620298f00e4613232d2 1dd24dcdda7d20f38bd88a0c2c01a4283d0e3eb0 +ac6f23131f686339af403d236dac13c1fd6f2e14 f5fba357bdfc3898731bfbb3866ef40ee75b16c0 +f5fba357bdfc3898731bfbb3866ef40ee75b16c0 f5559ef39a659c9f42979d45e7583a1d388c881e +1dd24dcdda7d20f38bd88a0c2c01a4283d0e3eb0 b9f1218ee50d5a4df6aa0b76289e826b72d4f1bc +f5559ef39a659c9f42979d45e7583a1d388c881e 335c8473b59bdc38492c9ead1bc3a0b5245d2e17 +335c8473b59bdc38492c9ead1bc3a0b5245d2e17 e551f1cae08dbe419dc2320cdd30f1cb04dad75b +e551f1cae08dbe419dc2320cdd30f1cb04dad75b 90e6a7e419181c0fb3ea16d70a097b7099e25bd4 +90e6a7e419181c0fb3ea16d70a097b7099e25bd4 03ef168ab1775755638995b16d4c73ac64776c75 +03ef168ab1775755638995b16d4c73ac64776c75 b9f1218ee50d5a4df6aa0b76289e826b72d4f1bc +b9f1218ee50d5a4df6aa0b76289e826b72d4f1bc f5f300b27d1b2a90d051f6137dcad9aae07a556c +f5f300b27d1b2a90d051f6137dcad9aae07a556c 2d65cd8ad02de59743a61d2a04517f4b3968718b +2d65cd8ad02de59743a61d2a04517f4b3968718b 93e4191ac585f159d69c56d24ff90f8cbd130f72,e99d630f5587c9fc7c3319e98a4c0c45ee3ce939 +e99d630f5587c9fc7c3319e98a4c0c45ee3ce939 649822464b92911db5733c5a6cd604d27f691387 +649822464b92911db5733c5a6cd604d27f691387 93e4191ac585f159d69c56d24ff90f8cbd130f72 +93e4191ac585f159d69c56d24ff90f8cbd130f72 4f2bafcb9e72d6be2bbfd96f8496b897cae985f3 +4f2bafcb9e72d6be2bbfd96f8496b897cae985f3 470f227b7c55112c04a4d63ad7e7d081be0b1e36 +470f227b7c55112c04a4d63ad7e7d081be0b1e36 5e968a126b69f89494596d6e429dee59826abbf6 +5e968a126b69f89494596d6e429dee59826abbf6 8232118283fc2cfa70eec8239a1012a62a15948d,1ba6aba073c6860a1a020486827144afef86abba +8232118283fc2cfa70eec8239a1012a62a15948d 59a93a028a7d69ebeea9d2148615c411bb8be404 +1ba6aba073c6860a1a020486827144afef86abba 94a053d0eab42120fb0896f671db5fc1a9de46f5,a2ee369f433a570c5bcf673ec5d57f93a57ce54b +59a93a028a7d69ebeea9d2148615c411bb8be404 a2ee369f433a570c5bcf673ec5d57f93a57ce54b,94a053d0eab42120fb0896f671db5fc1a9de46f5 +a2ee369f433a570c5bcf673ec5d57f93a57ce54b 977ca5be29771ae6680f3cee3cb420feb186a691 +977ca5be29771ae6680f3cee3cb420feb186a691 9480b4262994433d56ea454f5f942631f4346774 +94a053d0eab42120fb0896f671db5fc1a9de46f5 c28e4b5652ff8d1c9c3a5525a3762034086c9ab6 +c28e4b5652ff8d1c9c3a5525a3762034086c9ab6 f8b993531b45d0022629fd19ca5340dd9c397618 +9480b4262994433d56ea454f5f942631f4346774 9ebad2b30da5317976e8176fc160fccef4c589fb +9ebad2b30da5317976e8176fc160fccef4c589fb 4aeb75f670ba69c9abd0ad109cc2d5b2ff3033d2 +4aeb75f670ba69c9abd0ad109cc2d5b2ff3033d2 d668d912e4bf2d89acbe50c524f72e4eaec835dd +d668d912e4bf2d89acbe50c524f72e4eaec835dd c2d166b052fc39a8461a56b46d0ee330893402d0 +c2d166b052fc39a8461a56b46d0ee330893402d0 90452f880b21795692a2ac3d5113aefc5963abba +f8b993531b45d0022629fd19ca5340dd9c397618 90452f880b21795692a2ac3d5113aefc5963abba +90452f880b21795692a2ac3d5113aefc5963abba c280060f24e08bbd58a9d8ea941ff3780ede11d1 +c280060f24e08bbd58a9d8ea941ff3780ede11d1 77f61cd330a3ca2373c1d432d05ce087c8fd0db1 +77f61cd330a3ca2373c1d432d05ce087c8fd0db1 9e56800a6942b9cc89cd15a1373c414049393b05 +9e56800a6942b9cc89cd15a1373c414049393b05 01ed63fe8a3016ef61c067400cee73407c1a4d79,14e9c3fb650acaa291b75625bfa4a58f05c8297e +14e9c3fb650acaa291b75625bfa4a58f05c8297e 01ed63fe8a3016ef61c067400cee73407c1a4d79 +01ed63fe8a3016ef61c067400cee73407c1a4d79 d7e5356bcad6e5622ea68cc039e89e86ba749493 +d7e5356bcad6e5622ea68cc039e89e86ba749493 3f0d1f8803cb6a95353b635c2dfe9c9cc4ef3899 +3f0d1f8803cb6a95353b635c2dfe9c9cc4ef3899 b5ed77d7454aac9d98703f7cd688bf408847c1ee +b5ed77d7454aac9d98703f7cd688bf408847c1ee 2a86e587bcf4871707cb3aa55ceb44702495b91d +2a86e587bcf4871707cb3aa55ceb44702495b91d 497953438434d529d1362091a6ee1fbca1ef2ee9 +497953438434d529d1362091a6ee1fbca1ef2ee9 1e9a20f13ab327da684893f312d18f06815f5a77,ae42e0260e2f476bb6c0558e1604d9b812a4b004 +ae42e0260e2f476bb6c0558e1604d9b812a4b004 ae21e2aec14b38a3186f609656779e22eec3a11b +ae21e2aec14b38a3186f609656779e22eec3a11b 915e74bc332cca88f57964fe501c1d5c05b6e79a +915e74bc332cca88f57964fe501c1d5c05b6e79a d05d52e7504b851b0932af9d52fbef30e08accca +d05d52e7504b851b0932af9d52fbef30e08accca 1e9a20f13ab327da684893f312d18f06815f5a77 +1e9a20f13ab327da684893f312d18f06815f5a77 b7bca59fa9703a5a024fc550340524fc591132fc +b7bca59fa9703a5a024fc550340524fc591132fc f598a7e51ea45ca101f2e89a1b31aa0618a9041e,18868f44fd07e5c73329377c60e946c8c4c4efb5 +f598a7e51ea45ca101f2e89a1b31aa0618a9041e b6ea4f981a526654afe9d6d30d5b462ae3a0cf62 +b6ea4f981a526654afe9d6d30d5b462ae3a0cf62 c57a166878875b960e8051d72eec716c016baf5b +c57a166878875b960e8051d72eec716c016baf5b f1ae1885662d78efd7bc206352c21a1a974a2c0b +f1ae1885662d78efd7bc206352c21a1a974a2c0b ab7e6db80c30b830ec8dc016e162f52b2ee7eb94 +ab7e6db80c30b830ec8dc016e162f52b2ee7eb94 6961246ad7afecc990d346b9d2f543b6abb76bf7 +6961246ad7afecc990d346b9d2f543b6abb76bf7 97727e82b875406e51e022fcddc642180f06e675 +97727e82b875406e51e022fcddc642180f06e675 3321c2c52278ba7f8d12aaea3cbc07f6a505fedc +3321c2c52278ba7f8d12aaea3cbc07f6a505fedc 067b4c3661c6a97f88ff34072107ee601e782183 +067b4c3661c6a97f88ff34072107ee601e782183 cd9d9347c272aa02e2292cc3fa2fd599f53bd2f8 +cd9d9347c272aa02e2292cc3fa2fd599f53bd2f8 64d93529768e368d3dbf59e3da39a1750ab556bb +64d93529768e368d3dbf59e3da39a1750ab556bb 30b0302862cb860f31ab9ab80e7fc8874e5be1a5 +30b0302862cb860f31ab9ab80e7fc8874e5be1a5 83fad2f941618f4b3efe58a2a40354e7d7f228e9 +83fad2f941618f4b3efe58a2a40354e7d7f228e9 744916ab205a49f31e30a3c215c50b9c1e7ba43c +744916ab205a49f31e30a3c215c50b9c1e7ba43c 8a292192e55474a928883137244d11ff852ac2f5 +8a292192e55474a928883137244d11ff852ac2f5 d2b6ddbe9c4dc205ed92955daceae90b976399e4 +d2b6ddbe9c4dc205ed92955daceae90b976399e4 794d62eebe3a2bb8dc687152712f02804c76714e +794d62eebe3a2bb8dc687152712f02804c76714e 856838e0f017591c07fa91f41cdca3423710d1a1 +856838e0f017591c07fa91f41cdca3423710d1a1 6f2b3e137f04276d578b367adf5b8ef4b1b75e7a +6f2b3e137f04276d578b367adf5b8ef4b1b75e7a f37121f8b18ab9076f299c55249a5f4a5ce83602,fde3dc46b70e5b82c514fe2af4c02cc0c6c8cf78 +fde3dc46b70e5b82c514fe2af4c02cc0c6c8cf78 504c555d5a09ab502c55ef8f6eba884ae8090421 +504c555d5a09ab502c55ef8f6eba884ae8090421 0179214de8763308df414fdd8c25174c2c4d1ac6 +0179214de8763308df414fdd8c25174c2c4d1ac6 237a19178bf7b962c419090447ed12b093f98031 +237a19178bf7b962c419090447ed12b093f98031 be9acfd8edc953fd7c1a27df479f5dcb22d3d023 +be9acfd8edc953fd7c1a27df479f5dcb22d3d023 6b11655edddb7fe8219566adf05a7313cd3f3a52 +f37121f8b18ab9076f299c55249a5f4a5ce83602 3271143f7080ffd0be43286f513b58200a6bde42 +6b11655edddb7fe8219566adf05a7313cd3f3a52 fe0ca9de59f0dd99b5fb45340b42bc2884b263f6 +3271143f7080ffd0be43286f513b58200a6bde42 fe0ca9de59f0dd99b5fb45340b42bc2884b263f6 +ee563960f8474b8b2d6ef1d964ce55be449caa94 fe0ca9de59f0dd99b5fb45340b42bc2884b263f6 +fe0ca9de59f0dd99b5fb45340b42bc2884b263f6 114eed176f7dc84e70c567f7a20d59093bed7105,e4b276aa24aa86724ac0cd824a7227881519c126,ece2bfcae2b3897da82c44c8371486191f1e8c10 +114eed176f7dc84e70c567f7a20d59093bed7105 a8cb71c532ecef1e04cc0090d7bbc9953f673362 +a8cb71c532ecef1e04cc0090d7bbc9953f673362 b79b86ca4b2865063eac92cbdee0fbb37c5f0743 +b79b86ca4b2865063eac92cbdee0fbb37c5f0743 de8934622a88ef3efcae29b44871ffbbbaff4753 +de8934622a88ef3efcae29b44871ffbbbaff4753 08a3d6e3440b4221f4191377a95795e408e90962 +08a3d6e3440b4221f4191377a95795e408e90962 6275b9b5c591725e9d838cfb0d9a69a676cfb736 +0fe0deb19435d23d4b71a8b359dcaf38963b7e2e ece2bfcae2b3897da82c44c8371486191f1e8c10 +ece2bfcae2b3897da82c44c8371486191f1e8c10 776745031ae77aa2af8cafe7d4f6084780499182 +776745031ae77aa2af8cafe7d4f6084780499182 3d4ae9e02e2e680af484d3072dd52945b6c5b83f +3d4ae9e02e2e680af484d3072dd52945b6c5b83f c460b80adbd94283479a317a59632e9ccf4600ce +c460b80adbd94283479a317a59632e9ccf4600ce 6275b9b5c591725e9d838cfb0d9a69a676cfb736,0b61bcfc94a82dde32ed899aaebf16a055aa4de9 +6275b9b5c591725e9d838cfb0d9a69a676cfb736 aaa37a7f4af579627ee26c512e13e995f0d0f777,5be250d6fc1102b29d0529bc344ab2f604b9e71f +aaa37a7f4af579627ee26c512e13e995f0d0f777 bfb563fbe2b0771d55b0f58de88c52b0e65e5157 +bfb563fbe2b0771d55b0f58de88c52b0e65e5157 ba67d062aed155feb5898ba14710bb9373576d44 +0b61bcfc94a82dde32ed899aaebf16a055aa4de9 ba67d062aed155feb5898ba14710bb9373576d44 +ba67d062aed155feb5898ba14710bb9373576d44 93728683855435e098dd85c5865dc9d5394358d5 +93728683855435e098dd85c5865dc9d5394358d5 e4718cf7ed770ae44fa1f433204f0313d2a82fef +e4b276aa24aa86724ac0cd824a7227881519c126 b711d2b4301cad9eb2d600792480c8365193e2a1 +b711d2b4301cad9eb2d600792480c8365193e2a1 e4718cf7ed770ae44fa1f433204f0313d2a82fef +e4718cf7ed770ae44fa1f433204f0313d2a82fef 87b98ca112fd8143b05ee24c80ab6734d0eca45a +87b98ca112fd8143b05ee24c80ab6734d0eca45a 9f03d93cddf2c7503c53eb639fe66d37cefb6a9b +9f03d93cddf2c7503c53eb639fe66d37cefb6a9b 8b52109594c7f506182eb0cf780a8e30d7605ab7 +8b52109594c7f506182eb0cf780a8e30d7605ab7 a630d7090cea3b1b4eb0b760d16b11506f8a59b6 +a630d7090cea3b1b4eb0b760d16b11506f8a59b6 4432b3c8fa5e5205e70b2195ff3869f1ebee18a5 +4432b3c8fa5e5205e70b2195ff3869f1ebee18a5 441e299543e0f819da8d988de6f36e5f593b5582 +441e299543e0f819da8d988de6f36e5f593b5582 c8b69bc77f121376922659f8a45b85026798313c +c8b69bc77f121376922659f8a45b85026798313c a354b5c1cb82ccca2e2ad6ccbe161f88e2e5f0d4 +a354b5c1cb82ccca2e2ad6ccbe161f88e2e5f0d4 68d79bff21bb8edebbe644e4ce83279bf1c680b8 +68d79bff21bb8edebbe644e4ce83279bf1c680b8 8de562aa651be4ca133a38bc798c05e5e5d9ac4c +8de562aa651be4ca133a38bc798c05e5e5d9ac4c 39718da514fa680d3b36220f278ded94fb864a8f +39718da514fa680d3b36220f278ded94fb864a8f 2e121e3655c16a333eaafabdf3d9a9be0979a99e +2e121e3655c16a333eaafabdf3d9a9be0979a99e a91345f8e232d8d120a1ba2a6959cf9b3009edaf,70391eee14574b70d75f91f6a7ba24fd0ffd93df +a91345f8e232d8d120a1ba2a6959cf9b3009edaf 596110698ae00ddcb774e58070f12f35f67b00ab +596110698ae00ddcb774e58070f12f35f67b00ab 7953e9dc317d38b0b7596c1249c2251c5a8528e4 +7953e9dc317d38b0b7596c1249c2251c5a8528e4 4a97fe2a81a0aa10a8bec8e6dea7189f6f3f4dc4 +18db59ea626c5bcfe6cad451022a7a369e40fa10 4a97fe2a81a0aa10a8bec8e6dea7189f6f3f4dc4 +4a97fe2a81a0aa10a8bec8e6dea7189f6f3f4dc4 7cb9fcca308241b8ee47ac03fbe225f34e4eab44 +7cb9fcca308241b8ee47ac03fbe225f34e4eab44 dabd344efb93270ef258726f7870d4485d334add +dabd344efb93270ef258726f7870d4485d334add c0aef352366ca03fc684a04a26af9123a2d7f403 +c0aef352366ca03fc684a04a26af9123a2d7f403 3eb427f66fab067982a1525785b6035db89f8fc3 +3eb427f66fab067982a1525785b6035db89f8fc3 25d7ed4419d1f50254f6b4f42dd78938ac4e5d1e +25d7ed4419d1f50254f6b4f42dd78938ac4e5d1e b5369b3646723455d85a19efde21b54b20f99b27,c60797615037705d285c62bb15b4ff38efa77d1a +b5369b3646723455d85a19efde21b54b20f99b27 2f99cf9da6268db580aa2046abcc7a4a70644887,55cc440b5e3701841011542eabd752945e529082 +2f99cf9da6268db580aa2046abcc7a4a70644887 c0aaf523c6e77bd3dc079a00b5e34a1584863a8a,3944bdfd6a0741fdd3fdf41c8e6ce4d3c124af66 +c0aaf523c6e77bd3dc079a00b5e34a1584863a8a 5824d18b655397fe0c5d316c228a886f70ec7e9c,a399f30afdaeb5b0b247b3cfdef05300c6f3803f +5824d18b655397fe0c5d316c228a886f70ec7e9c b054d488904c1db742d4d491a17a2fc7cd287b9e +b054d488904c1db742d4d491a17a2fc7cd287b9e 5fe44e93934b015546033d33ecbff9f3fbec8e9f,621d3c2ef213a43cad70eb978b3308a4c3e0595e +5fe44e93934b015546033d33ecbff9f3fbec8e9f b2ea6646eb94c43ebcbb98463157dcd38c1eac50 +b2ea6646eb94c43ebcbb98463157dcd38c1eac50 52d24fd4b2ee1236eb33e6f58ebba63f6af9ba79 +52d24fd4b2ee1236eb33e6f58ebba63f6af9ba79 244e676ac0b0e386d7620794d23806c13bca9113 +244e676ac0b0e386d7620794d23806c13bca9113 b6bf1dd82ba9dedbbbd963c379960f46a2555df0 +2abfcad6eb95acc73472061251b4d9fbb897c989 b6bf1dd82ba9dedbbbd963c379960f46a2555df0 +b6bf1dd82ba9dedbbbd963c379960f46a2555df0 0f8fa0be12ccac493e1d7d6be25ddcc7cb16a18e,456c27dbc63c1fd70ae48de899833c5ca02e6e32 +456c27dbc63c1fd70ae48de899833c5ca02e6e32 9f5f817c0ed579f0a3a7f3ba3a391403f6ee37bc +9f5f817c0ed579f0a3a7f3ba3a391403f6ee37bc 624ddf95e6b54a943a644c0b5e785c990880999f,0f8fa0be12ccac493e1d7d6be25ddcc7cb16a18e +624ddf95e6b54a943a644c0b5e785c990880999f 9a750784a33ab9d714cdc68949906610f76cb964 +9a750784a33ab9d714cdc68949906610f76cb964 0706805720a141819654f6446f832416b5c551a4 +0f8fa0be12ccac493e1d7d6be25ddcc7cb16a18e 6f42a208581102d3679d23617d936fa9f3c2225a,6789a2c68486802961334f34c07e8e881261e54c +6789a2c68486802961334f34c07e8e881261e54c a01342192b8f798b5700d48b060a927a1714d636,6f42a208581102d3679d23617d936fa9f3c2225a +6f42a208581102d3679d23617d936fa9f3c2225a 9e070b3017644c5621ea48c2beae202be4232c84,f1f17cc9c784db6de2905ed1374879c7524ba376 +0706805720a141819654f6446f832416b5c551a4 92c8226782546e3086fef83d361cf2cc866a9ec1 +9e070b3017644c5621ea48c2beae202be4232c84 92c8226782546e3086fef83d361cf2cc866a9ec1,849b4de9ea7d0cdf1fe4006709ee7072f2d13e23 +92c8226782546e3086fef83d361cf2cc866a9ec1 170a77e923c53908caff93faf855b22cf871cf6a +170a77e923c53908caff93faf855b22cf871cf6a a533b6fa408fd80356242171e2f827a449ea3812 +a533b6fa408fd80356242171e2f827a449ea3812 0ae58081efbb1cc9fc7b20368d9c1208972e767b +0ae58081efbb1cc9fc7b20368d9c1208972e767b 77620de737b78f85f7b30f7e298428ddd67bd928 +77620de737b78f85f7b30f7e298428ddd67bd928 b95f77dc672b96ded94aa1392769abcdd8eb2470 +b95f77dc672b96ded94aa1392769abcdd8eb2470 9d5efca0bda7c6edb3936805bfb5cd7ae32126dd +9d5efca0bda7c6edb3936805bfb5cd7ae32126dd 703316903c43fb0ee8b445fb4811262fc937968e +703316903c43fb0ee8b445fb4811262fc937968e d5ab33bd7c48cc126fb4ef8f086a6d862df59ef5 +d5ab33bd7c48cc126fb4ef8f086a6d862df59ef5 57fdf136efcbda786125e07951d6f8a8b7d14592 +57fdf136efcbda786125e07951d6f8a8b7d14592 1b76773ad44f3180d8d0dc4e77dc3b50485aa05d +1b76773ad44f3180d8d0dc4e77dc3b50485aa05d 37803689fe1e764cb95508dad401f34972f73179 +37803689fe1e764cb95508dad401f34972f73179 0d58b5f4ddb056a6c8cb2350292d118696aa63b0,f8bf61270c28add4f64ab7d4bc9767a21f18e831 +0d58b5f4ddb056a6c8cb2350292d118696aa63b0 76b4277ddca72719e1ce0692c44b8907085f9791 +76b4277ddca72719e1ce0692c44b8907085f9791 67151b5753c7819309760ac097aaed33d74e2f93,23745b43026065c5ec6a3d61b964e1d65659036a +67151b5753c7819309760ac097aaed33d74e2f93 a9bdb539385321ec79cace958a816d397b6625c7,43341d56e0f80c10302563c5773d8ed4c2f9f420 +a9bdb539385321ec79cace958a816d397b6625c7 5c94f3c9196e51913a0b8516423c95a1cca43362 +68a6b805c52f5da6ce3a5c58df25270c2045ab32 adc89fda393154699c1712a5d8869184419dd798 +5c94f3c9196e51913a0b8516423c95a1cca43362 c3d314c7c50116890ecf8cb6155c6ca7b9f711ef +c3d314c7c50116890ecf8cb6155c6ca7b9f711ef 25f400c8f88eaddd0ca48c63e6e3f0791cc9f21a +25f400c8f88eaddd0ca48c63e6e3f0791cc9f21a 8a40b211a4197f5016f1497240761123a7523fb2 +8a40b211a4197f5016f1497240761123a7523fb2 a1dbd06515099561a77523765ad303e23051b456 +a1dbd06515099561a77523765ad303e23051b456 2f03232e1d7998dd77f1e118585ba2e1420304e8,5464c15055afb0cf2627838a18d92f1081c7b066 +2f03232e1d7998dd77f1e118585ba2e1420304e8 a5ed8f0caaed7d6b63ad93abc1dddeb45a27fb8e +a5ed8f0caaed7d6b63ad93abc1dddeb45a27fb8e 2120db9cffa7487197f01bf528fdb79c5319d0c9,2f6825c738be3a9d276e65d43975278ba174d9b5 +2120db9cffa7487197f01bf528fdb79c5319d0c9 10b99d180db996c6f438191e7521b7c39826979b,32584d6c1d9d8af3873babb0d356e8400c9582c0 +10b99d180db996c6f438191e7521b7c39826979b bcfb084eb25a7124496664afc5c48df85d85e838 +bcfb084eb25a7124496664afc5c48df85d85e838 82bd7da1b39153c0429fb36653a21994150420c1 +82bd7da1b39153c0429fb36653a21994150420c1 900f227fc0add02b87b86d8c509242eff7a6c264,2890f3b6933eb96b4f338b85524ab4562abda157 +900f227fc0add02b87b86d8c509242eff7a6c264 eac8148602a78ff2819b562f63e09679f24b4cbf +eac8148602a78ff2819b562f63e09679f24b4cbf 841b30b8c962d535454b80a8e0bb5d4161225699 +841b30b8c962d535454b80a8e0bb5d4161225699 277cc86ec7d1921574b6fdc40e5af33efd1d27d4 +277cc86ec7d1921574b6fdc40e5af33efd1d27d4 69ed787cf98b13e1c6b9031871fbe5fe88284bd3 +69ed787cf98b13e1c6b9031871fbe5fe88284bd3 1bf5c0bd2017622e9d5cad94683a7f00b3a7985d,a692915fb36b1f34dabf71452af63e04c91be209 +1bf5c0bd2017622e9d5cad94683a7f00b3a7985d d823b9ddaeb9c1f2dfe6e1e914337bd0543357ae,cd95146b0abcec1cd52629d80db969fdd27fa303 +d823b9ddaeb9c1f2dfe6e1e914337bd0543357ae 5148b5915f997c933f63570bdff8461f1aa7278e +5148b5915f997c933f63570bdff8461f1aa7278e a6afe6e1d7adba44262416bd4931e54f70b479d8,1c79e4a8344be1d5d9a293a542fc057aa524c50d +a6afe6e1d7adba44262416bd4931e54f70b479d8 fc84397e48939f77d2f783eb85143bd9db674e1a +fc84397e48939f77d2f783eb85143bd9db674e1a 20865cc9cf5470ee39ab9e99ef6a853233a9ca2a,e821f056086d11d0a8ff2fa6ae58f5a44678f707 +20865cc9cf5470ee39ab9e99ef6a853233a9ca2a ddc112387c36d1c270004bc9458b3cd3d6749ce9 +ddc112387c36d1c270004bc9458b3cd3d6749ce9 6a182939795451cf6d3817c41c343ecf905e831c +6a182939795451cf6d3817c41c343ecf905e831c c269abcad799c19d0488a098ad3a861256e4aaac +c269abcad799c19d0488a098ad3a861256e4aaac 2a906e05b06fa45908f2cf37b416649fecf09b7e,85fa0e2f1429aadd858971eec1a3798867a5112e +2a906e05b06fa45908f2cf37b416649fecf09b7e 346da738c4dd3e54fc827b42ca65790e22239c23,d806a4bc7493caf7d6ac3d447ec476eb4ce428fd +24a725dc99507e55283f453f7b5ca7d8e70be52f 3766f8e4ea2efd1e01520e99d4e5bf2885c302c4,346da738c4dd3e54fc827b42ca65790e22239c23 +7b2c89a42fa0a68561aee72886a479db368d713b fa65768bcc90fec0ddaf912d92a6bda4d06b3f61,346da738c4dd3e54fc827b42ca65790e22239c23 +aca1299f55bdb0844095f98de9c4a2008eac6ad0 a16fc0d2d04199c1d6664bc80706f165dc915d39,346da738c4dd3e54fc827b42ca65790e22239c23 +346da738c4dd3e54fc827b42ca65790e22239c23 b960ebe7d03d215353778093773b8ce3bcc9fb27,eaf721a3d3f690dc5766dca97c05ee8f779f828b +5464c15055afb0cf2627838a18d92f1081c7b066 259631117742cbc4a691f43bc3ce278082455ab1,39bde846fc3cee61a8ca81872ddde83253f48925 +b960ebe7d03d215353778093773b8ce3bcc9fb27 259631117742cbc4a691f43bc3ce278082455ab1,03e6b6ae8854c6f585f3e82553dfc5311e49f53e +259631117742cbc4a691f43bc3ce278082455ab1 cdbe742d201adb616cba467563fb2bfb524dd16a +cdbe742d201adb616cba467563fb2bfb524dd16a d7af4dd892b8a48a5107c4bf871d5d25f63e8511 +d7af4dd892b8a48a5107c4bf871d5d25f63e8511 614169b1acb86b21b562f807a6b54aa164d4056a +614169b1acb86b21b562f807a6b54aa164d4056a 7e269b22b6070768ce18c0b81d7b802662b2b6ed +7e269b22b6070768ce18c0b81d7b802662b2b6ed 7d703fee73ee850af7325ac7e4eebb6514c2757e +7d703fee73ee850af7325ac7e4eebb6514c2757e 6b673d12166ae1a5729aa517bdfd2e8ad974170e +6b673d12166ae1a5729aa517bdfd2e8ad974170e edc83414c9a7955c8f874c2fed261d8e1ae2eb91 +edc83414c9a7955c8f874c2fed261d8e1ae2eb91 17f63f989af77ffcca34d142b8ef5c210323e098 +17f63f989af77ffcca34d142b8ef5c210323e098 958206e68abbb9bb2cc76256ab3202363678e61f,06a1cb9d9b23aadc5231cbb188b2fac1003fbe28 +958206e68abbb9bb2cc76256ab3202363678e61f da26ce8d3cc378e9e0d8246540197575428132f9 +da26ce8d3cc378e9e0d8246540197575428132f9 aeabc7304c582c9a58e6098443430cbd2b323616 +aeabc7304c582c9a58e6098443430cbd2b323616 6efedc27d5e08a15fb9501ad32c257738c48334e +6efedc27d5e08a15fb9501ad32c257738c48334e 3a9471a6ea20a92b57325b0c56448d3e313a1d1a,1eb7abcd285650928a22eb81185a63d36b1b2cba +3a9471a6ea20a92b57325b0c56448d3e313a1d1a 6aa0069d074711085d57def494f56ddeb65a7551,6129574e1588a0cf30d5d0762a8cf49a9ebb5585 +6aa0069d074711085d57def494f56ddeb65a7551 704e7039441ea5383545da405e3b5f4cf01077c3,b0c45c85fe85689c0c59660a15e3476340b6819a +704e7039441ea5383545da405e3b5f4cf01077c3 b44a2afd2a47a63d510b1d4b7d58cdf5fc13b65d +b0c45c85fe85689c0c59660a15e3476340b6819a 8a26c9c9d71007dad93508ff17c5971ff7dc13b3 +8a26c9c9d71007dad93508ff17c5971ff7dc13b3 b44a2afd2a47a63d510b1d4b7d58cdf5fc13b65d,8528e93d3ce01d0b8b209c599ab261aa1987a108 +b44a2afd2a47a63d510b1d4b7d58cdf5fc13b65d 8bb5134286f52a3dbb1979de5bee25d7460b3c36,09c716a4e30e8744365c158619b44006fbf6d3b6 +fa65768bcc90fec0ddaf912d92a6bda4d06b3f61 bb194efe1821622d96c8c43d2a4c9de17e800391,8bb5134286f52a3dbb1979de5bee25d7460b3c36 +a01342192b8f798b5700d48b060a927a1714d636 bbe5c643c42223f97c8914ba3cd26b3c8d2c5030,8bb5134286f52a3dbb1979de5bee25d7460b3c36 +8bb5134286f52a3dbb1979de5bee25d7460b3c36 cb8d623593567f34e3fbf89a1b640cdb7b1eda75,2fae4888f332dfba920901c5afaf9ac448ca89c9 +cb8d623593567f34e3fbf89a1b640cdb7b1eda75 c31a46930cee2835641e43171f6c3f8800da3ae8,e71001dca11670f6e468d5b3c05c78292a748834 +c31a46930cee2835641e43171f6c3f8800da3ae8 90059ea0179772a7d296a382bb3c94865003c33e,dec8d412cdcc82e55fd516b1b1a874f290e7a806 +90059ea0179772a7d296a382bb3c94865003c33e 07eda936ba952eb3255eca4e2cbc00d49c3fd831,a2b3efa030a54e6cfb6c6736fca7e1e27d07cd15 +07eda936ba952eb3255eca4e2cbc00d49c3fd831 0ac98cae0481794557025cd5002aa2508d5347b6 +0ac98cae0481794557025cd5002aa2508d5347b6 fdfd424b83ec718a8cf74f38b01d8f1005e01faa,50414b8e0e67e191f1ae38bde54e30189de97b34 +fdfd424b83ec718a8cf74f38b01d8f1005e01faa 0cadfc4182b8bb43635020f393f5cdd6578b7cfd +0cadfc4182b8bb43635020f393f5cdd6578b7cfd dcf421dabda2384d57913343e73dd01688eb4dcf +dcf421dabda2384d57913343e73dd01688eb4dcf 82e28e89e54c198a6aa3c6435b5b32eec05ed65f +82e28e89e54c198a6aa3c6435b5b32eec05ed65f 657b6ecb353c1f5b0b91d2d5161aff9063af3fb0 +657b6ecb353c1f5b0b91d2d5161aff9063af3fb0 afa3279d3b6cb8913ba3d6eed8e635f66fa59d8e,30dc6100056269e9d384711478be9dd1bd744ddf +afa3279d3b6cb8913ba3d6eed8e635f66fa59d8e 4485968e237121d19cce63d18312987c84f0860e,599461b731bbb3081f49dcd72c356695da4bf483 +4485968e237121d19cce63d18312987c84f0860e 21dd573ab7ab0a63d35c0df07df08dae8b19bb16,08a1393c61b3c6d2ee96a35b52ae945806d0299e +21dd573ab7ab0a63d35c0df07df08dae8b19bb16 66eb2de9fa18125906e5d13abf52705839c9d088,3129220de08efe91135e7b1256772167e0dcdf15 +66eb2de9fa18125906e5d13abf52705839c9d088 fc9432d5a51c65f1716cf0ba20b1e693ccd2edce,5941191cd2682ef374df3afeebc0ae9d242162db +fc9432d5a51c65f1716cf0ba20b1e693ccd2edce f72fea4b3bc98ca7ab186eacce57b3dfd2557032 +f72fea4b3bc98ca7ab186eacce57b3dfd2557032 ade6384a7b0e4d065e18076ffa901e580679e26d,dd090afbe47f0aa25d6ec8cfe484fa02c23eb61a ADDED fossil-utils/justtesting/setup.dat Index: fossil-utils/justtesting/setup.dat ================================================================== --- /dev/null +++ fossil-utils/justtesting/setup.dat @@ -0,0 +1,9 @@ +[command] +0 rm -rf /tmp/$USER/megatest +1 mkdir -p /tmp/$USER/megatest +2 cp /home/matt/fossils/megatest.fossil /tmp/$USER/megatest +3 cd /tmp/$USER/megatest +4 fossil open megatest.fossil;fossil up trunk +5 fossil set autosync 0 +7 fossil set gmerge '' +8 fossil scrub --private --force ADDED fossil-utils/justtesting/sheet-names.cfg Index: fossil-utils/justtesting/sheet-names.cfg ================================================================== --- /dev/null +++ fossil-utils/justtesting/sheet-names.cfg @@ -0,0 +1,4 @@ +timeline +extra +branches +setup ADDED fossil-utils/justtesting/sxml/_sheets.sxml Index: fossil-utils/justtesting/sxml/_sheets.sxml ================================================================== --- /dev/null +++ fossil-utils/justtesting/sxml/_sheets.sxml @@ -0,0 +1,69 @@ +((@ (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 + "2020-06-01T04:28:18Z") + (urn:oasis:names:tc:opendocument:xmlns:meta:1.0:creation-date + "2020-06-01T01:13:31Z"))) + (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")) + "timeline") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "extra") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "branches") + (http://www.gnumeric.org/v10.dtd:SheetName + (@ (http://www.gnumeric.org/v10.dtd:Rows "65536") + (http://www.gnumeric.org/v10.dtd:Cols "256")) + "setup")) + (http://www.gnumeric.org/v10.dtd:Geometry + (@ (Width "2220") (Height "804"))) + (http://www.gnumeric.org/v10.dtd:UIData + (@ (SelectedTab "0")))) ADDED fossil-utils/justtesting/sxml/_workbook.sxml Index: fossil-utils/justtesting/sxml/_workbook.sxml ================================================================== --- /dev/null +++ fossil-utils/justtesting/sxml/_workbook.sxml @@ -0,0 +1,1 @@ +(*TOP* (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"")) ADDED fossil-utils/justtesting/sxml/branches.sxml Index: fossil-utils/justtesting/sxml/branches.sxml ================================================================== --- /dev/null +++ fossil-utils/justtesting/sxml/branches.sxml @@ -0,0 +1,135 @@ +(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 "16") + (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 "none") + (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 "95.25") (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 "16")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "2") (CursorCol "1")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "2") + (startCol "1") + (endRow "2") + (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")))) ADDED fossil-utils/justtesting/sxml/extra.sxml Index: fossil-utils/justtesting/sxml/extra.sxml ================================================================== --- /dev/null +++ fossil-utils/justtesting/sxml/extra.sxml @@ -0,0 +1,137 @@ +(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 "722") + (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 "none") + (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 "243") (No "0"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "462") (No "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") (Count "705")))) + (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")))) ADDED fossil-utils/justtesting/sxml/setup.sxml Index: fossil-utils/justtesting/sxml/setup.sxml ================================================================== --- /dev/null +++ fossil-utils/justtesting/sxml/setup.sxml @@ -0,0 +1,129 @@ +(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 "1") + (http://www.gnumeric.org/v10.dtd:MaxRow "8") + (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 + "\"setup\"") + (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 "none") + (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 "48") (No "0"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "333") (No "1")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.75")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "0") (Count "9")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "7") (CursorCol "0")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "7") + (startCol "0") + (endRow "7") + (endCol "255")))) + (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 fossil-utils/justtesting/sxml/timeline.sxml Index: fossil-utils/justtesting/sxml/timeline.sxml ================================================================== --- /dev/null +++ fossil-utils/justtesting/sxml/timeline.sxml @@ -0,0 +1,547 @@ +(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 "17") + (http://www.gnumeric.org/v10.dtd:MaxRow "65535") + (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 "none") + (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 "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 "256") + (startCol "0") + (endRow "431") + (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 "432") + (startCol "0") + (endRow "463") + (endCol "4")) + (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 "464") + (startCol "0") + (endRow "511") + (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 "512") + (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 "432") + (startCol "5") + (endRow "448") + (endCol "5")) + (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 "449") + (startCol "5") + (endRow "449") + (endCol "5")) + (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 "450") + (startCol "5") + (endRow "463") + (endCol "5")) + (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 "432") + (startCol "6") + (endRow "463") + (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 "8") + (endRow "511") + (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 "243.8") (No "0"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "89.25") + (No "1") + (HardSize "1") + (Count "2"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "51") (No "3") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "49.5") (No "4") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "105") (No "5") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "6"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "70.5") (No "7") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "48") (No "8"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "60.75") (No "9") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "34.5") (No "10") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "177") (No "11") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "63.75") (No "12") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "413.2") (No "13") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "213.8") (No "14") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "198.8") (No "15") (HardSize "1"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "104.2") (No "16"))) + (http://www.gnumeric.org/v10.dtd:ColInfo + (@ (Unit "78.75") (No "17")))) + (http://www.gnumeric.org/v10.dtd:Rows + (@ (DefaultSizePts "12.1")) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "0"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") + (No "1") + (Hidden "1") + (Count "17"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") + (No "18") + (Hidden "1") + (Count "41"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "59") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") + (No "60") + (Hidden "1") + (Count "131"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "191") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") + (No "192") + (Hidden "1") + (Count "215"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "407"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "408") (Count "10"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "418") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "419") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "420"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "421") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "422") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "423") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "424") (Count "18"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "442") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "443"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "444") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "445"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") + (No "446") + (Hidden "1") + (Count "3"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "449") (Count "7"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") (No "456") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "457") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "458") (Count "2"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") + (No "460") + (Hidden "1") + (Count "3"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "463") (Count "4"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") + (No "467") + (Hidden "1") + (Count "15"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "482") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") + (No "483") + (Hidden "1") + (Count "5"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") (No "488") (Hidden "1"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") + (No "489") + (Hidden "1") + (Count "4"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") + (No "493") + (Hidden "1") + (Count "5"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "13.5") + (No "498") + (Hidden "1") + (Count "3"))) + (http://www.gnumeric.org/v10.dtd:RowInfo + (@ (Unit "12.1") + (No "501") + (Hidden "1") + (Count "65035")))) + (http://www.gnumeric.org/v10.dtd:Selections + (@ (CursorRow "426") (CursorCol "13")) + (http://www.gnumeric.org/v10.dtd:Selection + (@ (startRow "426") + (startCol "13") + (endRow "426") + (endCol "13")))) + (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:Filters + (http://www.gnumeric.org/v10.dtd:Filter + (@ (Area "A1:Q65536")) + (http://www.gnumeric.org/v10.dtd:Field + (@ (ValueType0 "v1.65-broken") + (Value0 "60") + (Type "expr") + (Op0 "eq") + (Index "1"))))) + (http://www.gnumeric.org/v10.dtd:Solver + (@ (ProgramR "0") + (ProblemType "0") + (NonNeg "1") + (ModelType "0") + (MaxTime "60") + (MaxIter "1000") + (Discr "0") + (AutoScale "0")))) ADDED fossil-utils/justtesting/timeline.dat Index: fossil-utils/justtesting/timeline.dat ================================================================== --- /dev/null +++ fossil-utils/justtesting/timeline.dat cannot compute difference between binary files Index: launch.scm ================================================================== --- launch.scm +++ launch.scm @@ -30,10 +30,11 @@ (declare (unit launch)) (declare (uses subrun)) (declare (uses common)) (declare (uses configf)) (declare (uses db)) +(declare (uses ezsteps)) (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") @@ -48,13 +49,19 @@ ;; stepname {VAR=first,second,third ...} command ... ;; where the {VAR=first,second,third ...} is optional. ;; given an exit code and whether or not logpro was used calculate OK/BAD ;; return #t if we are ok, #f otherwise -(define (steprun-good? logpro exitcode) +(define (steprun-good? logpro exitcode stepparms) (or (eq? exitcode 0) - (and logpro (eq? exitcode 2)))) + (and logpro (eq? exitcode 2)) ;; shouldn't this be (member exitcode 2 ...) with the other ok codes? + (let* ((params (alist-ref 'params stepparms)) ;; get the params section + (keep-going (if params + (alist-ref "keep-going" params equal?) + #f))) + (debug:print 0 *default-log-port* "keep-going=" keep-going) + (and keep-going (equal? (car keep-going) "yes"))))) ;; if handed a string, process it, else look for MT_CMDINFO (define (launch:get-cmdinfo-assoc-list #!key (encoded-cmd #f)) (let ((enccmd (if encoded-cmd encoded-cmd (getenv "MT_CMDINFO")))) (if enccmd @@ -85,199 +92,10 @@ ((equal? status "PASS") "PASS") ;; skip the message part if status is pass (status (conc (configf:lookup dat "final" "exit-status") ": " (if msg msg "no message"))) (else #f))) #f))) -(define (launch:runstep ezstep run-id test-id exit-info m tal testconfig) ;;; TODO: deprecate me in favor of ezsteps.scm - (let* ((stepname (car ezstep)) ;; do stuff to run the step - (stepinfo (cadr ezstep)) - ;; (let ((info (cadr ezstep))) - ;; (if (proc? info) "" info))) - ;; (stepproc (let ((info (cadr ezstep))) - ;; (if (proc? info) info #f))) - (stepparts (string-match (regexp "^(\\{([^\\}\\{]*)\\}\\s*|)(.*)$") stepinfo)) - (stepparams (if (and (list? stepparts) - (> (length stepparts) 1)) - (list-ref stepparts 2) - #f)) ;; for future use, {VAR=1,2,3}, run step for each - (paramparts (if (string? stepparams) - (map (lambda (x)(string-split x "=")) (string-split-fields "[^;]*=[^;]*" stepparams)) - '())) - (subrun (alist-ref "subrun" paramparts equal?)) - (stepcmd (if (and (list? stepparts) - (> (length stepparts) 2)) - (list-ref stepparts 3) - (conc "# error, no command for step "stepname))) - (script "") ; "#!/bin/bash\n") ;; yep, we depend on bin/bash FIXME!!!\ - (logpro-file (conc stepname ".logpro")) - (html-file (conc stepname ".html")) - (dat-file (conc stepname ".dat")) - (tconfig-logpro (configf:lookup testconfig "logpro" stepname)) - (logpro-used (common:file-exists? logpro-file))) - - (debug:print 0 *default-log-port* "stepparts: " stepparts ", stepparams: " stepparams - ", paramparts: " paramparts ", subrun: " subrun ", stepcmd: " stepcmd) - - (if (and tconfig-logpro - (not logpro-used)) ;; no logpro file found but have a defn in the testconfig - (begin - (with-output-to-file logpro-file - (lambda () - (print ";; logpro file extracted from testconfig\n" - ";;") - (print tconfig-logpro))) - (set! logpro-used #t))) - - ;; NB// can safely assume we are in test-area directory - (debug:print 4 *default-log-port* "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts - " stepparams: " stepparams " stepcmd: " stepcmd) - - ;; ;; first source the previous environment - ;; (let ((prev-env (conc ".ezsteps/" prevstep (if (string-search (regexp "csh") - ;; (get-environment-variable "SHELL")) ".csh" ".sh")))) - ;; (if (and prevstep (common:file-exists? prev-env)) - ;; (set! script (conc script "source " prev-env)))) - - ;; call the command using mt_ezstep - ;; (set! script (conc "mt_ezstep " stepname " " (if prevstep prevstep "x") " " stepcmd)) - - (debug:print 4 *default-log-port* "script: " script) - (rmt:teststep-set-status! run-id test-id stepname "start" "-" #f #f) - ;; now launch the actual process - (call-with-environment-variables - (list (cons "PATH" (conc (get-environment-variable "PATH") ":."))) - (lambda () ;; (process-run "/bin/bash" "-c" "exec ls -l /tmp/foobar > /tmp/delme-more.log 2>&1") - (let* ((cmd (conc stepcmd " > " stepname ".log 2>&1")) ;; >outfile 2>&1 - (pid #f)) - (let ((proc (lambda () - (set! pid (process-run "/bin/bash" (list "-c" cmd)))))) - (if subrun - (begin - (debug:print-info 0 *default-log-port* "Running without MT_.* environment variables.") - (common:without-vars proc "^MT_.*")) - (proc))) - - (with-output-to-file "Makefile.ezsteps" - (lambda () - (print stepname ".log :") - (print "\t" cmd) - (if (common:file-exists? (conc stepname ".logpro")) - (print "\tlogpro " stepname ".logpro " stepname ".html < " stepname ".log")) - (print) - (print stepname " : " stepname ".log") - (print)) - #:append) - - (rmt:test-set-top-process-pid run-id test-id pid) - (let processloop ((i 0)) - (let-values (((pid-val exit-status exit-code)(process-wait pid #t))) - (mutex-lock! m) - (launch:einf-pid-set! exit-info pid) ;; (vector-set! exit-info 0 pid) - (launch:einf-exit-status-set! exit-info exit-status) ;; (vector-set! exit-info 1 exit-status) - (launch:einf-exit-code-set! exit-info exit-code) ;; (vector-set! exit-info 2 exit-code) - (mutex-unlock! m) - (if (eq? pid-val 0) - (begin - (thread-sleep! 2) - (processloop (+ i 1)))) - ))))) - (debug:print-info 0 *default-log-port* "step " stepname " completed with exit code " (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2)) - ;; now run logpro if needed - (if logpro-used - (let* ((logpro-exe (or (getenv "LOGPRO_EXE") "logpro")) - (pid (process-run (conc "/bin/sh -c '"logpro-exe" "logpro-file " " (conc stepname ".html") " < " stepname ".log > /dev/null'")))) - (let processloop ((i 0)) - (let-values (((pid-val exit-status exit-code)(process-wait pid #t))) - (mutex-lock! m) - ;; (make-launch:einf pid: pid exit-status: exit-status exit-code: exit-code) - (launch:einf-pid-set! exit-info pid) ;; (vector-set! exit-info 0 pid) - (launch:einf-exit-status-set! exit-info exit-status) ;; (vector-set! exit-info 1 exit-status) - (launch:einf-exit-code-set! exit-info exit-code) ;; (vector-set! exit-info 2 exit-code) - (mutex-unlock! m) - (if (eq? pid-val 0) - (begin - (thread-sleep! 2) - (processloop (+ i 1))))) - (debug:print-info 0 *default-log-port* "logpro for step " stepname " exited with code " (launch:einf-exit-code exit-info))))) ;; (vector-ref exit-info 2))))) - - (let ((exinfo (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2)) - (logfna (if logpro-used (conc stepname ".html") "")) - (comment #f)) - (if logpro-used - (let ((datfile (conc stepname ".dat"))) - ;; load the .dat file into the test_data table if it exists - (if (common:file-exists? datfile) - (set! comment (launch:load-logpro-dat run-id test-id stepname))) - (rmt:test-set-log! run-id test-id (conc stepname ".html")))) - (rmt:teststep-set-status! run-id test-id stepname "end" exinfo comment logfna)) - ;; set the test final status - (let* ((process-exit-status (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2)) - (this-step-status (cond - ((and (eq? process-exit-status 2) logpro-used) 'warn) ;; logpro 2 = warnings - ((and (eq? process-exit-status 3) logpro-used) 'check) ;; logpro 3 = check - ((and (eq? process-exit-status 4) logpro-used) 'waived) ;; logpro 4 = waived - ((and (eq? process-exit-status 5) logpro-used) 'abort) ;; logpro 5 = abort - ((and (eq? process-exit-status 6) logpro-used) 'skip) ;; logpro 6 = skip - ((eq? process-exit-status 0) 'pass) ;; logpro 0 = pass - (else 'fail))) - (overall-status (cond - ((eq? (launch:einf-rollup-status exit-info) 2) 'warn) ;; rollup-status (vector-ref exit-info 3) - ((eq? (launch:einf-rollup-status exit-info) 0) 'pass) ;; (vector-ref exit-info 3) - (else 'fail))) - (next-status (cond - ((eq? overall-status 'pass) this-step-status) - ((eq? overall-status 'warn) - (if (eq? this-step-status 'fail) 'fail 'warn)) - ((eq? overall-status 'abort) 'abort) - (else 'fail))) - (next-state ;; "RUNNING") ;; WHY WAS THIS CHANGED TO NOT USE (null? tal) ?? - (cond - ((null? tal) ;; more to run? - "COMPLETED") - (else "RUNNING")))) - (debug:print 4 *default-log-port* "Exit value received: " (launch:einf-exit-code exit-info) " logpro-used: " logpro-used - " this-step-status: " this-step-status " overall-status: " overall-status - " next-status: " next-status " rollup-status: " (launch:einf-rollup-status exit-info)) ;; (vector-ref exit-info 3)) - (case next-status - ((warn) - (launch:einf-rollup-status-set! exit-info 2) ;; (vector-set! exit-info 3 2) ;; rollup-status - ;; NB// test-set-status! does rdb calls under the hood - (tests:test-set-status! run-id test-id next-state "WARN" - (if (eq? this-step-status 'warn) "Logpro warning found" #f) - #f)) - ((check) - (launch:einf-rollup-status-set! exit-info 3) ;; (vector-set! exit-info 3 3) ;; rollup-status - ;; NB// test-set-status! does rdb calls under the hood - (tests:test-set-status! run-id test-id next-state "CHECK" - (if (eq? this-step-status 'check) "Logpro check found" #f) - #f)) - ((waived) - (launch:einf-rollup-status-set! exit-info 4) ;; (vector-set! exit-info 3 3) ;; rollup-status - ;; NB// test-set-status! does rdb calls under the hood - (tests:test-set-status! run-id test-id next-state "WAIVED" - (if (eq? this-step-status 'check) "Logpro waived found" #f) - #f)) - ((abort) - (launch:einf-rollup-status-set! exit-info 5) ;; (vector-set! exit-info 3 4) ;; rollup-status - ;; NB// test-set-status! does rdb calls under the hood - (tests:test-set-status! run-id test-id next-state "ABORT" - (if (eq? this-step-status 'abort) "Logpro abort found" #f) - #f)) - ((skip) - (launch:einf-rollup-status-set! exit-info 6) ;; (vector-set! exit-info 3 4) ;; rollup-status - ;; NB// test-set-status! does rdb calls under the hood - (tests:test-set-status! run-id test-id next-state "SKIP" - (if (eq? this-step-status 'skip) "Logpro skip found" #f) - #f)) - ((pass) - (tests:test-set-status! run-id test-id next-state "PASS" #f #f)) - (else ;; 'fail - (launch:einf-rollup-status-set! exit-info 1) ;; (vector-set! exit-info 3 1) ;; force fail, this used to be next-state but that doesn't make sense. should always be "COMPLETED" - (tests:test-set-status! run-id test-id "COMPLETED" "FAIL" (conc "Failed at step " stepname) #f) - ))) - logpro-used)) - (define (launch:manage-steps run-id test-id item-path fullrunscript ezsteps subrun test-name tconfigreg exit-info m) ;; (let-values ;; (((pid exit-status exit-code) ;; (run-n-wait fullrunscript))) ;; (tests:test-set-status! test-id "RUNNING" "n/a" #f #f) @@ -348,11 +166,11 @@ (append (or ezstepslst '()) (list (list "subrun" (conc "{subrun=true} " mt-cmd))))))) ;; process the ezsteps (if ezsteps - (begin + (let* ((all-steps-dat (make-hash-table))) ;; keep all the info around as stepname ==> alist; where 'params is the params list (add other stuff as needed) (if (not (common: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-error 0 *default-log-port* "ezsteps defined but ezstepslst is zero length") (let loop ((ezstep (car ezstepslst)) @@ -359,16 +177,19 @@ (tal (cdr ezstepslst)) (prevstep #f)) (debug:print-info 0 *default-log-port* "Processing ezstep \"" (string-intersperse ezstep " ") "\"") ;; check exit-info (vector-ref exit-info 1) (if (launch:einf-exit-status exit-info) ;; (vector-ref exit-info 1) - (let ((logpro-used (launch:runstep ezstep run-id test-id exit-info m tal testconfig)) - (stepname (car ezstep))) + (let* ((logpro-used (launch:runstep ezstep run-id test-id exit-info m tal testconfig all-steps-dat)) + (stepname (car ezstep)) + (stepparms (hash-table-ref all-steps-dat stepname))) + (setenv "MT_STEP_NAME" stepname) + (pp (hash-table->alist all-steps-dat)) ;; if logpro-used read in the stepname.dat file (if (and logpro-used (common:file-exists? (conc stepname ".dat"))) (launch:load-logpro-dat run-id test-id stepname)) - (if (steprun-good? logpro-used (launch:einf-exit-code exit-info)) + (if (steprun-good? logpro-used (launch:einf-exit-code exit-info) stepparms) (if (not (null? tal)) (loop (car tal) (cdr tal) stepname)) (debug:print 0 *default-log-port* "WARNING: step " (car ezstep) " failed. Stopping"))) (debug:print 0 *default-log-port* "WARNING: a prior step failed, stopping at " ezstep))))))))) @@ -909,17 +730,25 @@ (running-cnt (rmt:get-count-tests-running-for-run-id run-id)) (all-test-launched (rmt:get-var (conc "lunch-complete-" run-id))) (current-state (rmt:get-run-state run-id)) (current-status (rmt:get-run-status run-id))) ;;get-vars run-id to query metadata table to check if all completed. if all-test-launched = yes then only not-completed-cnt = 0 means everyting is completed if no entry found in the table do nothing - (debug:print 0 *default-log-port* "rollup run state/status") + (debug:print 0 *default-log-port* "Running test cnt :" running-cnt) (rmt:set-state-status-and-roll-up-run run-id current-state current-status) - + (runs:update-junit-test-reporter-xml run-id) (cond ((and all-test-launched (eq? not-completed-cnt 0) (equal? all-test-launched "yes" )) - (debug:print 0 *default-log-port* "look for post hook.") - (runs:run-post-hook run-id)) + (if (and (equal? (rmt:get-var (conc "end-of-run-" run-id)) "no") (common:simple-lock (conc "endOfRun" run-id))) + (begin + (debug:print 4 *default-log-port* "look for post hook. currseconds: " (current-seconds) " EOR " (rmt:get-var (conc "end-of-run-" run-id))) + (debug:print 0 *default-log-port* "End of Run Detected.") + (rmt:set-var (conc "end-of-run-" run-id) "yes") + ;(thread-sleep! 10) + (runs:run-post-hook run-id) + (debug:print 4 *default-log-port* "currseconds: " (current-seconds)" eor: " (rmt:get-var (conc "end-of-run-" run-id))) + (common:simple-unlock (conc "endOfRun" run-id))) + (debug:print 0 *default-log-port* "End of Run Detected but not running post hook. This should happen when eor is set to yes. This will happen only when 2 tests exit at smae time. eor= " (rmt:get-var (conc "end-of-run-" run-id))))) ((> running-cnt 3) (debug:print 0 *default-log-port* "There are " running-cnt " tests running." )) ((> running-cnt 0) (debug:print 0 *default-log-port* "running cnt > 0 but <= 3 kill-running-tests-if-dead" ) (let ((kill-cnt (launch:kill-tests-if-dead run-id))) Index: megatest-version.scm ================================================================== --- megatest-version.scm +++ megatest-version.scm @@ -18,6 +18,6 @@ ;; Always use two or four digit decimal ;; 1.01, 1.02...1.10,1.11,1.1101 ... 1.99,2.00.. (declare (unit megatest-version)) -(define megatest-version 1.6548) +(define megatest-version 1.6603) Index: megatest.scm ================================================================== --- megatest.scm +++ megatest.scm @@ -43,22 +43,24 @@ (declare (uses api)) (declare (uses tasks)) ;; only used for debugging. (declare (uses env)) (declare (uses diff-report)) (declare (uses commonmod)) +(declare (uses adjutant)) ;; (declare (uses ftail)) ;; (import ftail) -(import stml2 mutils commonmod) +(import stml2 mutils commonmod adjutant) ;; invoke the imports ;; (declare (uses mtargs.import)) ;; (declare (uses mtconfigf.import)) (declare (uses cookie.import)) (declare (uses stml2.import)) (declare (uses pkts.import)) (declare (uses commonmod.import)) +(declare (uses adjutant.import)) (define *db* #f) ;; this is only for the repl, do not use in general!!!! (include "common_records.scm") (include "key_records.scm") @@ -181,10 +183,12 @@ from standard in. Each line is comma delimited with four fields category,variable,value,comment Queries -list-runs patt : list runs matching pattern \"patt\", % is the wildcard + -fields fieldspec : fields to include in json dump; runs:id,runame+tests:testname+steps + -dumpmode MODE : dump in MODE format instead of sexpr, MODE=json,ini,sexp etc. (add -debug 0,9 to see which file contributes each line) -show-keys : show the keys used in this megatest setup -test-files targpatt : get the most recent test path/file matching targpatt e.g. %/% or '*.log' returns list sorted by age ascending, see examples below -test-paths : get the test paths matching target, runname, item and test patterns. @@ -191,16 +195,14 @@ -list-disks : list the disks available for storing runs -list-targets : list the targets in runconfigs.config -list-db-targets : list the target combinations used in the db -show-config : dump the internal representation of the megatest.config file -show-runconfig : dump the internal representation of the runconfigs.config file - -dumpmode MODE : dump in MODE format instead of sexpr, MODE=json,ini,sexp etc. (add -debug 0,9 to see which file contributes each line) -show-cmdinfo : dump the command info for a test (run in test environment) -section sectionName -var varName : for config and runconfig lookup value for sectionName varName -since N : get list of runs changed since time N (Unix seconds) - -fields fieldspec : fields to include in json dump; runs:id,runame+tests:testname+steps -sort fieldname : in -list-runs sort tests by this field -testdata-csv [categorypatt/]varpatt : dump testdata for given category Misc -start-dir path : switch to this directory before running megatest @@ -215,10 +217,12 @@ -update-meta : update the tests metadata for all tests -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 - to automatically figure out hostname + -adjutant C,M : start the server/adjutant with allocated cores C and Mem M (Gig), + use 0,0 to auto use full machine -transport http|rpc : use http or rpc for transport (default is http) -log logfile : send stdout and stderr to logfile -list-servers : list the servers -kill-servers : kill all servers -repl : start a repl (useful for extending megatest) @@ -250,10 +254,11 @@ -run-patt -target-patt -dumpmode -list-test-time : list time requered to complete each test in a run. It following following arguments -runname -target -dumpmode -syscheck : do some very basic checks; write access and space in tmp, home, runs, links and is $DISPLAY valid + -list-waivers : dump waivers for specified target, runname, testpatt to stdout Diff report -diff-rep : generate diff report (must include -src-target, -src-runname, -target, -runname and either -diff-email or -diff-html) -src-target @@ -321,19 +326,21 @@ ":variable" ":value" ":expected" ":tol" ":units" + ;; misc "-start-dir" "-run-patt" "-target-patt" "-contour" "-area-tag" "-area" "-run-tag" "-server" + "-adjutant" "-transport" "-port" "-extract-ods" "-pathmod" "-env2file" @@ -382,10 +389,11 @@ "-diff-email" "-sync-to" "-pgsync" "-kill-wait" ;; wait this long before removing test (default is 10 sec) "-diff-html" + ) (list "-h" "-help" "--help" "-manual" "-version" "-force" @@ -429,10 +437,11 @@ "-list-db-targets" "-show-runconfig" "-show-config" "-show-cmdinfo" "-get-run-status" + "-list-waivers" ;; queries "-test-paths" ;; get path(s) to a test, ordered by youngest first "-runall" ;; run all tests, respects -testpatt, defaults to % @@ -510,10 +519,11 @@ (let* ((no-watchdog-args '("-list-runs" "-testdata-csv" "-list-servers" "-server" + "-adjutant" "-list-disks" "-list-targets" "-show-runconfig" ;;"-list-db-targets" "-show-runconfig" @@ -903,10 +913,18 @@ (if (args:get-arg "-server") (let ((tl (launch:setup)) (transport-type (string->symbol (or (args:get-arg "-transport") "http")))) (server:launch 0 transport-type) (set! *didsomething* #t))) + +;; The adjutant is a bit different, it does NOT run (launch:setup) as it is not necessarily tied to +;; a specific Megatest area. Detail are being hashed out and this may change. +;; +(if (args:get-arg "-adjutant") + (begin + (adjutant-run) + (set! *didsomething* #t))) (if (or (args:get-arg "-list-servers") (args:get-arg "-kill-servers")) (let ((tl (launch:setup))) (if tl ;; all roads from here exit @@ -1677,24 +1695,113 @@ (set! *time-to-exit* #t) ) ;; end if true branch (end of a let) ) ;; end if ) ;; end if -list-runs -;; Don't think I need this. Incorporated into -list-runs instead -;; -;; (if (and (args:get-arg "-since") -;; (launch:setup)) -;; (let* ((since-time (string->number (args:get-arg "-since"))) -;; (run-ids (db:get-changed-run-ids since-time))) -;; ;; (rmt:get-tests-for-runs-mindata run-ids testpatt states status not-in) -;; (print (sort run-ids <)) -;; (set! *didsomething* #t))) - +;; list-waivers +(if (and (args:get-arg "-list-waivers") + (launch:setup)) + (let* ((runpatt (or (args:get-arg "-runname") "%")) + (testpatt (common:args-get-testpatt #f)) + (keys (rmt:get-keys)) + (runsdat (rmt:get-runs-by-patt + keys runpatt + (common:args-get-target) #f #f + '("id" "runname" "state" "status" "owner" "event_time" "comment") 0)) + (runs (db:get-rows runsdat)) + (header (db:get-header runsdat)) + (results (make-hash-table)) ;; [target] ( (testname/itempath . "comment") ... ) + (addtest (lambda (target testname itempath comment) + (hash-table-set! results target (cons (cons (conc testname "/" itempath) comment) + (hash-table-ref/default results target '()))))) + (last-target #f)) + (for-each + (lambda (run) + (let* ((run-id (db:get-value-by-header run header "id")) + (target (rmt:get-target run-id)) + (runname (db:get-value-by-header run header "runname")) + (tests (rmt:get-tests-for-run + run-id testpatt '("COMPLETED") '("WAIVED") #f #f #f 'testname 'asc ;; use qryvals if test-spec provided + #f #f #f))) + (if (not (equal? target last-target)) + (print "[" target "]")) + (set! last-target target) + (print "# " runname) + (for-each + (lambda (testdat) + (let* ((testfullname (conc (db:test-get-testname testdat) + (if (equal? "" (db:test-get-item-path testdat)) + "" + (conc "/" (db:test-get-item-path testdat))) + ))) + (print testfullname " " (db:test-get-comment testdat)))) + tests))) + runs) + (set! *didsomething* #t))) ;;====================================================================== ;; full run ;;====================================================================== + +(define (handle-run-requests target runname keys keyvals need-clean) + (if (or (args:get-arg "-kill-rerun") (args:get-arg "-rerun-clean")) ;; first set states/statuses correct + ;; For rerun-clean do we or do we not support the testpatt? + (let ((states (or (configf:lookup *configdat* "validvalues" "cleanrerun-states") + "KILLREQ,KILLED,UNKNOWN,INCOMPLETE,STUCK,NOT_STARTED")) + (statuses (or (configf:lookup *configdat* "validvalues" "cleanrerun-statuses") + "FAIL,INCOMPLETE,ABORT,CHECK,DEAD,PREQ_FAIL,PREQ_DISCARDED"))) + (hash-table-set! args:arg-hash "-preclean" #t) + (runs:operate-on 'set-state-status + target + (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) + ;; "%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") + (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") + state: states + ;; status: statuses + new-state-status: "NOT_STARTED,n/a") + (runs:clean-cache target runname *toppath*) + (runs:operate-on 'set-state-status + target + (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) + ;; "%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") + (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") + ;; state: states + status: statuses + new-state-status: "NOT_STARTED,n/a"))) + ;; RERUN ALL + (if (args:get-arg "-rerun-all") ;; first set states/statuses correct + (let* ((rconfig (full-runconfigs-read))) + (hash-table-set! args:arg-hash "-preclean" #t) + (runs:operate-on 'set-state-status + target + (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) + (common:args-get-testpatt rconfig) ;; (args:get-arg "-testpatt") + state: #f + ;; status: statuses + new-state-status: "NOT_STARTED,n/a") + (runs:clean-cache target runname *toppath*) + (runs:operate-on 'set-state-status + target + (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) + (common:args-get-testpatt rconfig) ;; (args:get-arg "-testpatt") + ;; state: states + status: #f + new-state-status: "NOT_STARTED,n/a"))) + (let* ((config-reruns (let ((x (configf:lookup *configdat* "setup" "reruns"))) + (if x (string->number x) #f))) + (rerun-cnt (if config-reruns + config-reruns + 1))) + + (runs:run-tests target + runname + #f ;; (common:args-get-testpatt #f) + ;; (or (args:get-arg "-testpatt") + ;; "%") + user + args:arg-hash + run-count: rerun-cnt))) ;; get lock in db for full run for this directory ;; for all tests with deps ;; walk tree of tests to find head tasks ;; add head tasks to task queue @@ -1714,72 +1821,39 @@ (args:get-arg "-rerun-clean") (args:get-arg "-rerun-all") (args:get-arg "-runtests") (args:get-arg "-kill-rerun")) (let ((need-clean (or (args:get-arg "-rerun-clean") - (args:get-arg "-rerun-all")))) + (args:get-arg "-rerun-all"))) + (orig-cmdline (string-intersperse (argv) " "))) (general-run-call "-runall" "run all tests" (lambda (target runname keys keyvals) - (if (or (args:get-arg "-kill-rerun") (args:get-arg "-rerun-clean")) ;; first set states/statuses correct - ;; For rerun-clean do we or do we not support the testpatt? - (let ((states (or (configf:lookup *configdat* "validvalues" "cleanrerun-states") - "KILLREQ,KILLED,UNKNOWN,INCOMPLETE,STUCK,NOT_STARTED")) - (statuses (or (configf:lookup *configdat* "validvalues" "cleanrerun-statuses") - "FAIL,INCOMPLETE,ABORT,CHECK,DEAD,PREQ_FAIL,PREQ_DISCARDED"))) - (hash-table-set! args:arg-hash "-preclean" #t) - (runs:operate-on 'set-state-status - target - (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) - ;; "%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") - (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") - state: states - ;; status: statuses - new-state-status: "NOT_STARTED,n/a") - (runs:clean-cache target runname *toppath*) - (runs:operate-on 'set-state-status - target - (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) - ;; "%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") - (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt") - ;; state: states - status: statuses - new-state-status: "NOT_STARTED,n/a"))) - ;; RERUN ALL - (if (args:get-arg "-rerun-all") ;; first set states/statuses correct - (let* ((rconfig (full-runconfigs-read))) - (hash-table-set! args:arg-hash "-preclean" #t) - (runs:operate-on 'set-state-status - target - (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) - (common:args-get-testpatt rconfig) ;; (args:get-arg "-testpatt") - state: #f - ;; status: statuses - new-state-status: "NOT_STARTED,n/a") - (runs:clean-cache target runname *toppath*) - (runs:operate-on 'set-state-status - target - (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname")) - (common:args-get-testpatt rconfig) ;; (args:get-arg "-testpatt") - ;; state: states - status: #f - new-state-status: "NOT_STARTED,n/a"))) - (let* ((config-reruns (let ((x (configf:lookup *configdat* "setup" "reruns"))) - (if x (string->number x) #f))) - (rerun-cnt (if config-reruns - config-reruns - 1))) - - (runs:run-tests target - runname - #f ;; (common:args-get-testpatt #f) - ;; (or (args:get-arg "-testpatt") - ;; "%") - user - args:arg-hash - run-count: rerun-cnt)))))) + (if (or (string-search "%" target) + (string-search "%" runname)) ;; we are being asked to re-run multiple runs + (let* ((run-specs (rmt:simple-get-runs runname #f #f target #f))) ;; list of simple-run records + (debug:print-info 0 *default-log-port* "Pattern supplied for target or runname with " + (length run-specs) " matches round. Running each in turn.") + (if (null? run-specs) + (debug:print 0 *default-log-port* "WARNING: No runs match target " target " and runname " runname)) + (for-each (lambda (spec) + (let* ((precmd (if (args:get-arg "-precmd")(conc (args:get-arg "-precmd") " ") "")) + (newcmdline (conc + precmd + (string-substitute + (conc "target " target) + (conc "target " (simple-run-target spec)) + (string-substitute + (conc "runname " runname) + (conc "runname " (simple-run-runname spec)) + orig-cmdline))))) + (debug:print 0 *default-log-port* "ORIG: " orig-cmdline) + (debug:print 0 *default-log-port* "NEW: " newcmdline) + (system newcmdline))) + run-specs)) + (handle-run-requests target runname keys keyvals need-clean)))))) ;;====================================================================== ;; run one test ;;====================================================================== Index: mtut.scm ================================================================== --- mtut.scm +++ mtut.scm @@ -23,10 +23,11 @@ (define (toplevel-command . a) #f) (use srfi-1 posix srfi-69 readline ;; regex regex-case srfi-69 apropos json http-client directory-utils rpc typed-records;; (srfi 18) extras) srfi-19 srfi-18 extras format regex regex-case (prefix dbi dbi:) + (prefix sqlite3 sqlite3:) nanomsg) (declare (uses common)) (declare (uses megatest-version)) (declare (uses margs)) @@ -841,12 +842,11 @@ (contours (configf:get-section mtconf "contours")) (torun (make-hash-table)) ;; target => ( ... info ... ) (rgentargs (hash-table-keys rgconf))) ;; these are the targets registered for automatically triggering ;;(print "rgentargs: " rgentargs) - - (for-each + (for-each (lambda (runkey) (let* ((keydats (configf:get-section rgconf runkey))) (for-each (lambda (sense) ;; these are the sense rules (let* ((key (car sense)) @@ -1429,10 +1429,11 @@ (areas (configf:get-section mtconf "areas")) (contours (configf:get-section mtconf "contours")) (pkts (find-pkts pdb '(cmd) '())) (torun (make-hash-table)) ;; target => ( ... info ... ) (rgentargs (hash-table-keys rgconf))) ;; these are the targets registered for automatically triggering + (sqlite3:set-busy-handler! (dbi:db-conn pdb) (sqlite3:make-busy-timeout 10000)) (for-each (lambda (pktdat) (let* ((pkta (alist-ref 'apkt pktdat)) (action (alist-ref 'A pkta)) (cmdline (pkt->cmdline pkta)) Index: runs.scm ================================================================== --- runs.scm +++ runs.scm @@ -16,11 +16,11 @@ ;; along with Megatest. If not, see . ;; strftime('%m/%d/%Y %H:%M:%S','now','localtime') (use (prefix sqlite3 sqlite3:) srfi-1 posix regex regex-case srfi-69 (srfi 18) - posix-extras directory-utils pathname-expand typed-records format) + posix-extras directory-utils pathname-expand typed-records format sxml-serializer sxml-modifications) (declare (unit runs)) (declare (uses db)) (declare (uses common)) (declare (uses items)) @@ -532,10 +532,19 @@ ;; run the run prehook if there are no tests yet run for this run: ;; (runs:run-pre-hook run-id) ;; mark all test launced flag as false in the meta table (rmt:set-var (conc "lunch-complete-" run-id) "no") + (debug:print-info 1 *default-log-port* "Setting end-of-run to no") + (let* ((config-reruns (let ((x (configf:lookup *configdat* "setup" "reruns"))) + (if x (string->number x) #f))) + (config-rerun-cnt (if config-reruns + config-reruns + 1))) + (if (eq? config-rerun-cnt run-count) + (rmt:set-var (conc "end-of-run-" run-id) "no"))) + (rmt:set-run-state-status run-id "new" "n/a") ;; now add non-directly referenced dependencies (i.e. waiton) ;;====================================================================== ;; refactoring this block into tests:get-full-data ;; @@ -685,21 +694,21 @@ (if (not (hash-table-ref/default flags "-preclean" #f)) (hash-table-set! flags "-preclean" #t)) (if (not (hash-table-ref/default flags "-rerun" #f)) (hash-table-set! flags "-rerun" "STUCK/DEAD,n/a,ZERO_ITEMS")) ;; recursive call to self - (runs:run-tests target runname test-patts user flags run-count: (- run-count 1))))) + (runs:run-tests target runname test-patts user flags run-count: (- run-count 1))) + (launch:end-of-run-check run-id))) (debug:print-info 0 *default-log-port* "No tests to run"))) (debug:print-info 4 *default-log-port* "All done by here") ;; TODO: try putting post hook call here - ;(if (eq? run-count 0) - ; (begin - ; (debug:print-info 0 *default-log-port* "Calling Post Hook") + ; (debug:print-info 2 *default-log-port* " run-count " run-count) ; (runs:run-post-hook run-id)) ; (debug:print-info 2 *default-log-port* "Not calling post hook runcount = " run-count )) (rmt:tasks-set-state-given-param-key task-key "done") + ;; (sqlite3:finalize! tasks-db) )) ;; loop logic. These are used in runs:run-tests-queue to make it a bit more readable. @@ -1678,12 +1687,12 @@ (else (debug:print-info 4 *default-log-port* "cond branch - " "rtq-9") (debug:print-info 4 *default-log-port* "Exiting loop with...\n hed=" hed "\n tal=" tal "\n reruns=" reruns)) ))) ;; end loop on sorted test names ;; this is the point where everything is launched and now you can mark the run in metadata table as all launched - (rmt:set-var (conc "lunch-complete-" run-id) "yes") - + (rmt:set-var (conc "lunch-complete-" run-id) "yes") + ;; now *if* -run-wait we wait for all tests to be done ;; Now wait for any RUNNING tests to complete (if in run-wait mode) (thread-sleep! 10) ;; I think there is a race condition here. Let states/statuses settle (let wait-loop ((num-running (rmt:get-count-tests-running-for-run-id run-id)) (prev-num-running 0)) @@ -2085,10 +2094,19 @@ sorted))) ;; (print "Sorted: " (map simple-run-event_time sorted)) ;; (print "Remove: " (map simple-run-event_time to-remove)))) (hash-table-keys runs-ht)) runs-ht)) + +(define (remove-last-path-directory path-in) + (let* ((dparts (string-split path-in "/")) + (path-out (conc "/" (string-intersperse (take dparts (- (length dparts) 1)) "/"))) + ) + path-out + ) +) + ;; (define (runs:remove-all-but-last-n-runs-per-target target-patts runpatt num-to-keep) ;; (let ((data (runs:get-all-but-most-recent-n-per-target target-patts runpatt num-to-keep))) ;; (for-each ;; (lambda (target) @@ -2154,10 +2172,12 @@ (tests (if (not (equal? run-state "locked")) (proc-get-tests run-id) '())) (lasttpath "/does/not/exist/I/hope") (lastrealpath "/does/not/exist/I/hope") + ;; there may be a number of different disks used in the same run. + (run-paths-hash (make-hash-table)) (worker-thread #f)) (debug:print-info 4 *default-log-port* "runs:operate-on run=" run ", header=" header) (if (not (null? tests)) (begin (case action @@ -2336,18 +2356,40 @@ ;; 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 - (set! lasttpath (db:test-get-rundir new-test-dat)) ;; remember this path for run removal - (if (file-exists? lasttpath) - (set! lastrealpath (resolve-pathname lasttpath)) - (set! lastrealpath lasttpath)) - (runs:remove-test-directory new-test-dat mode) ;; 'remove-all) - - (if (not (null? tal)) - (loop (car tal)(cdr tal))))))) + (let ((rundir (db:test-get-rundir new-test-dat))) + (if (and (not (string= rundir "/tmp/badname")) + (file-exists? rundir) + (substring-index run-name rundir) + (substring-index target rundir) + ) + (begin + (set! lasttpath (db:test-get-rundir new-test-dat)) ;; remember this path for run removal + (set! lastrealpath (remove-last-path-directory (resolve-pathname lasttpath))) + (hash-table-set! run-paths-hash lastrealpath 1) + (runs:remove-test-directory new-test-dat mode) ;; 'remove-all) + ) + (begin + (debug:print 2 *default-log-port* "Not removing directory " rundir " because either it doesn't exist or has a bad name") + (debug:print 2 *default-log-port* "Is /tmp/badname: " (string= rundir "/tmp/badname")) + (debug:print 2 *default-log-port* "Exists: " (file-exists? rundir)) + (debug:print 2 *default-log-port* "Has run-name: " (substring-index run-name rundir)) + (debug:print 2 *default-log-port* "Has target: " (substring-index target rundir)) + ;;PJH remove record from db no need to cleanup directory + (case mode + ((remove-data-only)(mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) (db:test-get-state test)(db:test-get-status test) #f)) + ((archive-remove) (mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) "ARCHIVED" #f #f)) + (else (rmt:delete-test-records (db:test-get-run_id test) (db:test-get-id test)))) + + ) + ) + ) + + (if (not (null? tal)) + (loop (car tal)(cdr tal))))))) (rmt:update-run-stats run-id (rmt:get-raw-run-stats run-id))) ((kill-runs) ;; RUNNING -> KILLREQ ;; LAUNCHED,RUNNING,REMOTEHOSTSTART -> NOT STARTED (cond @@ -2419,31 +2461,34 @@ ;; remove the run if zero tests remain (if (eq? action 'remove-runs) (let* ((run-id (db:get-value-by-header run header "id")) ;; NB// masks run-id from above? (remtests (mt:get-tests-for-run run-id #f '("DELETED") '("n/a") not-in: #t))) (if (null? remtests) ;; no more tests remaining - ;; Remove the last dir from the path. - ;; And same for the link-resolved path - (let* ((dparts (string-split lasttpath "/")) - (linkspath (conc "/" (string-intersperse (take dparts (- (length dparts) 1)) "/"))) - (real-dparts (string-split lastrealpath "/")) - (realpath (conc "/" (string-intersperse (take real-dparts (- (length real-dparts) 1)) "/"))) - ) - - (debug:print 1 *default-log-port* "Removing run: " linkspath) - (if (not keep-records) - (begin - (debug:print 1 *default-log-port* "Removing DB records for the run.") - (rmt:delete-run run-id) - (rmt:delete-old-deleted-test-records)) - ) - (debug:print 1 *default-log-port* "Recursively removing links dir " linkspath) - (runs:recursive-delete-with-error-msg linkspath) - - (debug:print 1 *default-log-port* "Recursively removing real dir " realpath) - (runs:recursive-delete-with-error-msg realpath) - + (let* ((linkspath (remove-last-path-directory lasttpath)) + (runpaths (hash-table-keys run-paths-hash)) + ) + + (debug:print 2 *default-log-port* "run-paths-hash: " (hash-table-keys run-paths-hash)) + + (debug:print 1 *default-log-port* "Removing target " target "run: " run-name) + (if (not keep-records) + (begin + (debug:print 1 *default-log-port* "Removing DB records for the run.") + (rmt:delete-run run-id) + (rmt:delete-old-deleted-test-records)) + ) + (if (not (equal? linkspath "/does/not/exist/I")) + (begin + (debug:print 1 *default-log-port* "Recursively removing links dir " linkspath) + (runs:recursive-delete-with-error-msg linkspath))) + + (for-each (lambda(runpath) + (debug:print 1 *default-log-port* "Recursively removing runs dir " runpath) + (runs:recursive-delete-with-error-msg runpath) + ) + runpaths + ) ))))) )) runs) ;; special case - archive get (if (equal? (args:get-arg "-archive") "get") @@ -2699,10 +2744,102 @@ (conc "INSERT OR REPLACE INTO test_data (test_id,category,variable,value,expected,tol,units,comment) " "SELECT " (db:test-get-id new-testdat) ",category,variable,value,expected,tol,units,comment FROM test_data WHERE test_id=?;") (db:test-get-id testdat)))) )) prev-tests))) + +(define doc-template + '(*TOP* + (*PI* xml "version='1.0'") + (testsuite))) + +(define (runs:update-junit-test-reporter-xml run-id) + (let* ( + (junit-test-reporter (configf:lookup *configdat* "runs" "junit-test-reporter-xml")) + (junit-test-report-dir (configf:lookup *configdat* "runs" "junit-test-report-dir")) + (xml-dir (if (and junit-test-reporter (equal? junit-test-reporter "yes" )) + (if junit-test-report-dir + junit-test-report-dir + (conc (getenv "MT_LINKTREE") "/" (getenv "MT_TARGET") "/" (getenv "MT_RUNNAME"))) + #f)) + (xml-ts-name (if xml-dir + (conc (getenv "MT_TESTSUITENAME")"."(string-translate (getenv "MT_TARGET") "/" ".") "." (getenv "MT_RUNNAME")) + #f)) + (keyname (if xml-ts-name (common:get-signature xml-ts-name) #f)) + (xml-path (if xml-dir + (conc xml-dir "/" keyname ".xml") + #f)) + + (test-data (if xml-dir + (rmt:get-tests-for-run run-id "%" '() '() ;; run-id testpatt states statuses + #f #f ;; offset limit + #f ;; not-in + #f ;; sort-by + #f ;; sort-order + #f ;; get full data (not 'shortlist) + 0 ;; (runs:gendat-inc-results-last-update *runs:general-data*) ;; last update time + #f) + '())) + (tests-count (if xml-dir (length test-data) #f))) + (if (and junit-test-reporter (equal? junit-test-reporter "yes" )) + (begin + ;((sxml-modify! `("testsuite" insert-into (@ (name ,xml-ts-name) (tests ,tests-count)))) doc) + + (let loop ((test (car test-data)) + (tail (cdr test-data)) + (doc doc-template) + (fail-cnt 0) + (error-cnt 0)) + (let* ((test-name (vector-ref test 2)) + (test-itempath (vector-ref test 11)) + (tc-name (conc test-name (if (and test-itempath (not (equal? test-itempath ""))) (conc "." (string-translate test-itempath "/" "." )) ""))) + (test-state (vector-ref test 3)) + (comment (vector-ref test 14)) + (test-status (vector-ref test 4)) + (exc-msg (conc "No bucket for State " test-state " Status " test-status)) + (new-doc (cond + ((member test-state (list "RUNNING" )) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name)) (inProgress)))) doc)) + ((member test-state (list "LAUNCHED" "REMOTEHOSTSTART" "NOT_STARTED")) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name)) (inQueue)))) doc)) + ((member test-status (list "PASS" "WARN" "WAIVED")) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name))))) doc)) + ((member test-status (list "FAIL" "CHECK")) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name)) (failure (@ (message ,comment) (type "failure")))))) doc)) + ((member test-status (list "DEAD" "KILLED" "ABORT" "PREQ_FAIL" "PREQ_DISCARDED")) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name)) (failure (@ (message ,comment) (type "error")))))) doc)) + ((member test-status (list "SKIP")) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name)) (skipped (@ (type "skipped")))))) doc)) + (else + (debug:print 0 *default-log-port* (conc "What do I do with State " test-state " Status " test-status)) + ((sxml-modify `("testsuite" insert-into (testcase (@ (name ,tc-name)) (failure (@ (message ,exc-msg) (type "error")))))) doc)))) + (new-error-cnt (if (member test-status (list "DEAD" "KILLED" "ABORT" "PREQ_FAIL" "PREQ_DISCARDED")) + (+ error-cnt 1) + error-cnt)) + (new-fail-cnt (if (member test-status (list "FAIL" "CHECK")) + (+ fail-cnt 1) + fail-cnt))) + (if (null? tail) + (let* ((final-doc ((sxml-modify `("testsuite" insert-into (@ (name ,xml-ts-name) (tests ,tests-count) (errors ,error-cnt) (failures ,fail-cnt)))) new-doc))) + (debug:print 0 *default-log-port* "modify attrib error=" error-cnt " fail= " fail-cnt) + (handle-exceptions + exn + (let* ((msg ((condition-property-accessor 'exn 'message) exn))) + (debug:print 0 *default-log-port* (conc "WARNING: Failed to update file" xml-path". Message:" msg))) + + (if (not (file-exists? xml-dir)) + (create-directory xml-dir #t)) + (if (not (rmt:no-sync-get/default keyname #f)) + (begin + (rmt:no-sync-set keyname "on") + (debug:print 0 *default-log-port* "creating xml at " xml-path) + (with-output-to-file xml-path + (lambda () + (print (sxml-serializer#serialize-sxml final-doc ns-prefixes: (list (cons 'gnm "http://foo")))))) + (rmt:no-sync-del! keyname)) + (debug:print 0 *default-log-port* "Could not get the lock. Skip writing the xml file.")))) + (loop (car tail) (cdr tail) new-doc new-fail-cnt new-error-cnt)))))))) ;; clean cache files (define (runs:clean-cache target runname toppath) (if target