pax_global_header00006660000000000000000000000064132525653340014522gustar00rootroot0000000000000052 comment=b99622087233178368cff6cf38ec72fa01dfd8a6 Hermes-0.0.20180315/000077500000000000000000000000001325256533400135065ustar00rootroot00000000000000Hermes-0.0.20180315/.gitignore000066400000000000000000000000541325256533400154750ustar00rootroot00000000000000.*~ *~ t1 t2 testreports *.tar.gz *.tar.bz2 Hermes-0.0.20180315/COPYRIGHT000066400000000000000000000026671325256533400150140ustar00rootroot00000000000000Hermes License ----------- Hermes is licensed under the terms of the MIT license reproduced below. This means that Lua is free software and can be used for both academic and commercial purposes at absolutely no cost. =============================================================================== Copyright (C) 2008-2011 Robert McLay Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =============================================================================== (end of COPYRIGHT) Hermes-0.0.20180315/H5MGFdiff/000077500000000000000000000000001325256533400151455ustar00rootroot00000000000000Hermes-0.0.20180315/H5MGFdiff/CmdLineOptions.lua000066400000000000000000000016211325256533400205370ustar00rootroot00000000000000require("strict") CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local usage = "H5MGFdiff -r resultFn -f xdrdiff.lua xdr1 xdr2" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } cmdlineParser:add_option{ name = {'-f','--file'}, dest = 'tdesc', action = 'store' } cmdlineParser:add_option{ name = {'-r', '--resultfile'}, dest = 'resultFn', action = 'store' } local optionTbl, pargs = cmdlineParser:parse(arg) local masterTbl = masterTbl() for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs if (#masterTbl.pargs < 2) then Error("Usage: ",usage) end end Hermes-0.0.20180315/H5MGFdiff/H5MGFdiff.tasks000066400000000000000000000001611325256533400176510ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"CmdLineOptions"} task{"Wrapper"} return masterTbl().status end Hermes-0.0.20180315/H5MGFdiff/Wrapper.lua000066400000000000000000000016721325256533400172760ustar00rootroot00000000000000require("strict") require("serializeTbl") require("fileOps") Wrapper = BaseTask:new() function Wrapper:execute(myTable) local masterTbl = masterTbl() assert(loadfile(masterTbl.tdesc))() local cmdA = {} cmdA[#cmdA + 1] = "compMGF" cmdA[#cmdA + 1] = "-t" cmdA[#cmdA + 1] = self:prep(masterTbl.pargs[1]) cmdA[#cmdA + 1] = "-g" cmdA[#cmdA + 1] = self:prep(masterTbl.pargs[2]) cmdA[#cmdA + 1] = "-r" cmdA[#cmdA + 1] = masterTbl.resultFn for i,v in ipairs(testdescript.tolerances.vars) do cmdA[#cmdA + 1] = v.name .. " " .. v.rel .. " " .. v.abs end local cmdline = table.concat(cmdA," ") print ("cmdline:",cmdline) masterTbl.status = os.execute(cmdline .. " > H5MGFdiff.log 2>&1") end function Wrapper:prep(fn) local dir = dirname(fn) local bfn = barefilename(fn) local i,j, fn1 = bfn:find("(.*)_%d_soln.h5") if (i) then bfn = fn1 end return pathJoin(dir,bfn) end Hermes-0.0.20180315/Hermes.db000066400000000000000000000004311325256533400152360ustar00rootroot00000000000000-- -*- lua -*- -- created: Mon Mar 5 14:04:57 2018 -- ProjectData = { ["HermesVersion"] = "2.8", ["HermesVersionDate"] = "Mon Mar 5 14:04:57 2018", PackageList = { { ["pkgName"] = "hermes", ["revision"] = "head", }, }, ["ProjectName"] = "hermes", } Hermes-0.0.20180315/Makefile000066400000000000000000000057101325256533400151510ustar00rootroot00000000000000REQUIRED_PKGS := BeautifulTbl ColumnTable Dbg hash Optiks Optiks_Option strict \ fileOps string_utils serializeTbl pairsByKeys TermWidth Stencil \ capture declare inherits CMDS := findcmd testFinish testcleanup tm updateProjectDataVersion wrapperDiff BINList := $(patsubst %, bin/%, $(CMDS)) bin/lua_cmd CMDList := $(CMDS) lib VERSION := $(shell updateProjectDataVersion --version) MAIN_DIR := Hermes.db Makefile COPYRIGHT dist: $(MAKE) DistD=DIST _dist _dist: _distMkDir _distMainDir _distBin _distCmds _distCleanupSVN _distReqPkg _distTar _distMkDir: $(RM) -r $(DistD) mkdir $(DistD) _distMainDir: cp $(MAIN_DIR) $(DistD) _distBin: mkdir $(DistD)/bin cp $(BINList) $(DistD)/bin _distCmds: cp -r $(CMDList) $(DistD) _distCleanupSVN: find $(DistD) -name .svn | xargs rm -rf _distReqPkg: cp `findLuaPkgs $(REQUIRED_PKGS)` $(DistD)/lib _distTar: echo "hermes"-$(VERSION) > .fname; \ $(RM) -r `cat .fname` `cat .fname`.tar*; \ mv ${DistD} `cat .fname`; \ tar chf `cat .fname`.tar `cat .fname`; \ bzip2 `cat .fname`.tar; \ rm -rf `cat .fname` .fname; install: $(INSTALLDIR) cp -r * $(INSTALLDIR) $(RM) $(INSTALLDIR)/bin/updateProjectDataVersion $(INSTALLDIR): mkdir -p $@ gittag: ifneq ($(TAG),) @git status -s > /tmp/hermes$$$$; \ if [ -s /tmp/hermes$$$$ ]; then \ echo "All files not checked in => try again"; \ else \ updateProjectDataVersion --new_version $(TAG); \ git commit -m "moving to TAG_VERSION $(TAG)" Hermes.db; \ git tag -a $(TAG) -m 'Setting TAG_VERSION to $(TAG)' ; \ fi; \ rm -f /tmp/hermes$$$$ else @echo "To git tag do: make gittag TAG=?" endif world_update: @git status -s > /tmp/git_st_$$$$; \ if [ -s /tmp/git_st_$$$$ ]; then \ echo "All files not checked in => try again"; \ else \ branchName=`git status | head -n 1 | sed 's/^[# ]*On branch //g'`; \ git push github $$branchName; \ git push --tags github $$branchName; \ git push rtm_github $$branchName; \ git push --tags rtm_github $$branchName; \ fi; \ rm -f /tmp/git_st_$$$$ Hermes-0.0.20180315/README.md000077700000000000000000000000001325256533400236302tm/doc/getting_started_with_tm.txtustar00rootroot00000000000000Hermes-0.0.20180315/bin/000077500000000000000000000000001325256533400142565ustar00rootroot00000000000000Hermes-0.0.20180315/bin/H5MGFdiff000077500000000000000000000000631325256533400156420ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/b2dDiff000077500000000000000000000000631325256533400154430ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/bsearchSvn000077500000000000000000000000631325256533400163010ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/checkout000077500000000000000000000000631325256533400160100ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/dadcircDiff000077500000000000000000000000631325256533400163650ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/epoch000077500000000000000000000000631325256533400153010ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/f90continue000077500000000000000000000000631325256533400163460ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/findcmd000077500000000000000000000000631325256533400156070ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/lua_cmd000077500000000000000000000017461325256533400156200ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- cmdPath=$1 cmdName=`expr "$cmdPath" : '.*/\(.*\)'` execDir=`expr "$cmdPath" : '\(.*\)/'` if [ -z $execDir ]; then execDir="./" fi shift cwd=$PWD cd $execDir projectDir='' done=0 prev='' while [ $done != 1 ]; do if [ -f Hermes.db ]; then done=1 projectDir=$PWD else prev=$PWD cd .. if [ $PWD = '/' -o $prev = $PWD ]; then echo Did not find 'Hermes.db', Hermes must be in a project. exit; fi fi done cd $cwd execLuaPath="$projectDir/lib/?.lua;$projectDir/tools/?.lua" extra= if [ "x$LUA_PATH" != x ]; then extra=";$LUA_PATH" else extra=";`lua -e 'print(package.path)'`" fi export LUA_PATH="$execLuaPath$extra" for i in "$@"; do if [ "$i" = "-v" -o "$i" = "-D" ]; then echo "projectDir : $projectDir" echo "LUA_PATH : $LUA_PATH" echo "LUA_CPATH : $LUA_CPATH" echo "execDir : $execDir" echo "cmdPath : $cmdPath" echo break fi done $projectDir/lib/tool.lua $cmdPath "$@" Hermes-0.0.20180315/bin/mk000077500000000000000000000001451325256533400146130ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- cmd=`expr "$0" : '\(.*\)/'` cmd="$cmd/wmake" lua_cmd $cmd "$@" Hermes-0.0.20180315/bin/mpr000077500000000000000000000000631325256533400150010ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/newproject000077500000000000000000000000631325256533400163630ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/pairTest000077500000000000000000000000631325256533400157760ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/ptop_cmd000077500000000000000000000000631325256533400160100ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/stwDiff000077500000000000000000000000631325256533400156110ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/symlinkSimInputFiles000077500000000000000000000000631325256533400203450ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/testFinish000077500000000000000000000000631325256533400163230ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/testcleanup000077500000000000000000000000631325256533400165320ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/tm000077500000000000000000000000631325256533400146230ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/updateProjectDataVersion000077500000000000000000000000631325256533400211540ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/wm000077500000000000000000000001451325256533400146270ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- cmd=`expr "$0" : '\(.*\)/'` cmd="$cmd/wmake" lua_cmd $cmd "$@" Hermes-0.0.20180315/bin/wmake000077500000000000000000000000631325256533400153070ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/wrapperDiff000077500000000000000000000000631325256533400164540ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/bin/xdrdiff000077500000000000000000000000631325256533400156310ustar00rootroot00000000000000#!/bin/sh # -*- shell-script -*- lua_cmd $0 "$@" Hermes-0.0.20180315/epoch/000077500000000000000000000000001325256533400146045ustar00rootroot00000000000000Hermes-0.0.20180315/epoch/CmdLineOptions.lua000066400000000000000000000014751325256533400202050ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local Usage = "epoch [options]" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=Usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } cmdlineParser:add_option{ name = {'-d', '--date'}, dest = 'date', action = 'store', type = 'string', } cmdlineParser:add_option{ name = {'-u', '--uuid'}, dest = 'uuid', action = 'store', type = 'string', } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/epoch/Epoch.lua000066400000000000000000000002111325256533400163370ustar00rootroot00000000000000require("strict") require("build_epoch") Epoch = BaseTask:new() function Epoch:execute(myTable) build_epoch() print (epoch()) end Hermes-0.0.20180315/epoch/epoch.tasks000066400000000000000000000001421325256533400167460ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"CmdLineOptions"} task{"Epoch"} return 0 end Hermes-0.0.20180315/f90continue/000077500000000000000000000000001325256533400156515ustar00rootroot00000000000000Hermes-0.0.20180315/f90continue/CmdLineOptions.lua000066400000000000000000000015451325256533400212500ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "Usage: f90continue [options] *.f *.f90 *.F *.F90" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count', help = 'Increasing the level of verbosity help output', } cmdlineParser:add_option{ name = {'-m','--ampersand'}, dest = 'column', action = 'store', type = 'number', default = 81, help = 'Minimum column where \'&\' will go', } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/f90continue/F90Continue.lua000066400000000000000000000034041325256533400204200ustar00rootroot00000000000000require("string_utils") F90Continue = BaseTask:new() function F90Continue:execute(myTable) local masterTbl = masterTbl() for _,fn in ipairs(masterTbl.pargs) do local status = F90Continue:moveMarker(fn) if (status) then os.rename(fn, fn .. "~") os.rename(fn..".new", fn) end end end function F90Continue:moveMarker(fn) local masterTbl = masterTbl() local f = assert(io.open(fn)) local whole = f:read("*all") local column = masterTbl.column f:close() local lineA = {} local b = nil local e = nil for l in whole:split("\n") do local i,j = l:find("&%s*$") if (not i or i == column) then if (b) then e = #lineA F90Continue:lineUp(lineA,b,e) b = nil end lineA[#lineA+1] = l else if (not b) then b = #lineA + 1 end l = l:sub(1,i-1) local jb = l:find("%s+$") or 0 l = l:sub(1,jb-1) local count = column - l:len() - 1 if (count < 0 ) then count = 2 end lineA[#lineA+1] = l .. string.rep(" ",count) .. "&" end end whole = table.concat(lineA,"\n") f = assert(io.open(fn .. ".new", "w")) f:write(whole) f:close() return true end function F90Continue:lineUp(lineA, b, e) local masterTbl = masterTbl() local column = masterTbl.column local mcolumn = 0 for c = b, e do local l = lineA[c] mcolumn = math.max(mcolumn, l:find("&")) end if (mcolumn <= column) then return end for c = b, e do local l = lineA[c] local i = l:find("&") local count = mcolumn - i lineA[c] = l:sub(1,i-1) .. string.rep(" ",count) .. "&" end end Hermes-0.0.20180315/f90continue/f90continue.tasks000066400000000000000000000001511325256533400210600ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"CmdLineOptions"} task{"F90Continue"} return 0 end Hermes-0.0.20180315/findcmd/000077500000000000000000000000001325256533400151125ustar00rootroot00000000000000Hermes-0.0.20180315/findcmd/CmdLineOptions.lua000066400000000000000000000012451325256533400205060ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() local function vname() return "1.0" end function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local Optiks = require("Optiks") local usage = "Usage: findcmd [options] cmd" local cmdlineParser = Optiks:new{usage=usage,version=vname(), error = Error} cmdlineParser:add_option{ name = {'--pathOnly'}, dest = 'pathOnly', action = 'store_true', help = 'return just the path without the command', } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/findcmd/findcmd.tasks000066400000000000000000000006601325256533400175670ustar00rootroot00000000000000-- -*- lua -*- require("fileOps") function taskMain() local masterTbl = masterTbl() local path = os.getenv('PATH') or '' task{"CmdLineOptions"} local cmd = masterTbl.pargs[1] local results = findInPath(cmd,path) if (masterTbl.pathOnly) then results = dirname(results) if (results:sub(-1) == '/') then results = results:sub(1,-2) end end print(results) return 0 end Hermes-0.0.20180315/lib/000077500000000000000000000000001325256533400142545ustar00rootroot00000000000000Hermes-0.0.20180315/lib/BaseTask.lua000066400000000000000000000003251325256533400164540ustar00rootroot00000000000000require("strict") BaseTask = {} function BaseTask:new(name) local o = {} setmetatable(o,self) self.__index = self o.name = name return o end function BaseTask:name() return self.name end Hermes-0.0.20180315/lib/CleanEnv.lua000066400000000000000000000046241325256533400164600ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") require("string_utils") require("fileOps") require("pairsByKeys") local getenv = posix.getenv local setenv = posix.setenv local concatTbl = table.concat local keepT = { ['ACCOUNT'] = 'keep', ['HOME'] = 'keep', ['USER'] = 'keep', ['LD_LIBRARY_PATH'] = 'keep', ['LUA_CPATH'] = 'keep', ['LUA_PATH'] = 'keep', ['BASH_ENV'] = 'keep', ['TARG'] = 'keep', ['TARGET'] = 'keep', -- ['PATH'] = 'neat', } local execT = { gcc = 'keep', icc = 'keep', lua = 'keep', python = 'keep', tm = 'keep', expr = 'keep', seq = 'keep', sed = 'keep', rm = 'keep', sha1sum = 'keep', mpirun = 'keep', cmake = 'keep', Rscript = 'keep', } local function cleanPath(v) local pathT = {} local pathA = {} local idx = 0 for path in v:split(':') do idx = idx + 1 path = path_regularize(path) if (pathT[path] == nil) then pathT[path] = { idx = idx, keep = false } pathA[#pathA+1] = path end end local keepPathA = { "/bin", "/usr/bin" } for i = 1,#keepPathA do local path = keepPathA[i] if (pathT[path]) then pathT[path].keep = true end end local myPath = concatTbl(pathA,':') pathA = {} for execName in pairs(execT) do local cmd = findInPath(execName, myPath) if (not cmd:find("unknown_path_for") ) then local p = path_regularize(dirname(cmd)) pathT[p].keep = true end end for path in pairs(pathT) do if (v:find('^/usr/')) then pathT[path].keep = true end end -- Step 1: Make a sparse array with path as values local t = {} for k, v in pairs(pathT) do if (v.keep) then t[v.idx] = k end end -- Step 2: Use pairsByKeys to copy paths into pathA in correct order local n = 0 for _, v in pairsByKeys(t) do n = n + 1 pathA[n] = v end -- Step 3: rebuild path return concatTbl(pathA,':') end function cleanEnv() local envT = getenv() for k, v in pairs(envT) do local keep = keepT[k] if (not keep) then setenv(k, nil, true) elseif (keep == 'neat') then setenv(k, cleanPath(v), true) end end end Hermes-0.0.20180315/lib/ReadProject.lua000066400000000000000000000033001325256533400171550ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") ReadProject = BaseTask:new() require("strict") require("fileOps") local dbg = require("Dbg"):dbg() local function findPackageName(fileName) local masterTbl = masterTbl() local projectDir = masterTbl.projectDir local projectData = masterTbl.projectData local i,j, p, icnt local pkgTbl = {} local icnt = 0 for _,v in ipairs(projectData.PackageList or {}) do pkgTbl[v.pkgName] = v icnt = icnt + 1 end if (icnt == 0) then return "" end local paths = {} i,j, p = fileName:find( projectDir .. "/(.*)") if (p == nil) then return "" end while (1) do paths[#paths + 1] = p i,j, p = p:find("^(.*)/") if (not i) then break end end local pkgName = "" for _,p in ipairs(paths) do if (pkgTbl[p]) then pkgName = p break end end if (pkgName == "") then pkgName = paths[#paths] else local t = pkgTbl[pkgName] for k in pairs(t) do masterTbl[k] = t[k] end end return pkgName end function ReadProject:execute(myTable) local masterTbl = masterTbl() masterTbl.projectDir = findDirInDirTree(posix.getcwd(),masterTbl.projectFn) local projectFn = pathJoin(masterTbl.projectDir, masterTbl.projectFn) assert(loadfile(projectFn))() masterTbl.projectData = ProjectData masterTbl.packageName = findPackageName(posix.getcwd()) masterTbl.packageDir = pathJoin(masterTbl.projectDir, masterTbl.packageName) dbg.print{"packageDir: ","\"",masterTbl.packageDir,"\"\n"} dbg.print{"packageName: ","\"",masterTbl.packageName,"\"\n"} dbg.print{"projectDir: ","\"",masterTbl.projectDir,"\"\n"} end Hermes-0.0.20180315/lib/build_epoch.lua000066400000000000000000000010441325256533400172330ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") epoch = false function build_epoch() if (posix.gettimeofday) then local x1, x2 = posix.gettimeofday() if (x2 == nil) then epoch = function() local t = posix.gettimeofday() return t.sec + t.usec*1.0e-6 end else epoch = function() local t1, t2 = posix.gettimeofday() return t1 + t2*1.0e-6 end end else require("sys") epoch = sys.gettimeofday end end Hermes-0.0.20180315/lib/dirlist.lua000066400000000000000000000017471325256533400164420ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") require("fileOps") local lfs = require("lfs") function dirlist(path) local list = {} list.dirs = {} list.files = {} local attr = lfs.attributes(path) if (attr == nil or attr.mode ~= "directory") then return list end for fn in lfs.dir(path) do if (fn ~= "." and fn ~= "..") then local f = pathJoin(path, fn) local attr = lfs.attributes(f) if (type(attr) == "table") then if (attr.mode == "directory") then table.insert(list.dirs, fn) else table.insert(list.files, fn) end end end end return list end function filelist(path) local list = {} local attr = lfs.attributes(path) if (attr == nil or attr.mode ~= "directory") then return list end for fn in lfs.dir(path) do if (fn ~= "." and fn ~= "..") then list[#list + 1] = fn end end return list end Hermes-0.0.20180315/lib/engine.lua000066400000000000000000000065301325256533400162300ustar00rootroot00000000000000-- -*- lua -*- _DEBUG = false local posix = require("posix") require("strict") local dbg = require("Dbg"):dbg() require("fileOps") Error = nil engine = {} master = { projectFn = "Hermes.db", } function ErrorStd(...) ErrorDbg(...) os.exit(1) end function fixFileName(name) name = name:gsub("[ &'\"!()[@#]","_") name = name:gsub("]","_") return name end function ErrorDbg(...) io.stderr:write("\nError: ") for _,v in ipairs{...} do io.stderr:write(v) end io.stderr:write("\n") end function engine.buildLuaPath(taskDir, execName) local luaPathTbl = {} table.insert(luaPathTbl, pathJoin(taskDir, "?" )) table.insert(luaPathTbl, pathJoin(taskDir, "?.lua")) table.insert(luaPathTbl, "?.lua;?") table.insert(luaPathTbl, package.path) package.path = table.concat(luaPathTbl,";") end function engine.splitCmdName(path) return splitFileName(path) end function engine.execute(execDir, execName) engine.execDir = execDir engine.execName = execName local masterTbl = masterTbl() -- Load the Hermes.db file from the Hermes Project file: Hermes.db local projDir = findDirInDirTree(engine.execDir, masterTbl.projectFn) local fn = pathJoin(projDir, masterTbl.projectFn) assert(loadfile(fn))() masterTbl.HermesVersion = ProjectData.HermesVersion local taskDir = pathJoin(projDir, execName) local taskFileName = pathJoin(taskDir, execName .. ".tasks") masterTbl.taskDir = taskDir assert(loadfile(taskFileName))() engine.buildLuaPath(taskDir,execName) require("BaseTask") -- count number of '-v' or '--verbose' in argument list local verboseCnt = 0 local debugCnt = 0 for i,v in ipairs(arg) do if (v == '-v' or v == '--verbose') then verboseCnt = verboseCnt + 1 end if (v == '-D' or v == '--debug') then debugCnt = debugCnt + 1 end end engine.verboseCnt = math.max(verboseCnt, debugCnt) Error = ErrorStd if (engine.verboseCnt > 0) then dbg:activateDebug(engine.verboseCnt) end dbg.start{"engine()"} dbg.start{"engine initial state()", level=2} dbg.print{'projDir: ',projDir, "\n"} dbg.print{'execDir: ',execDir, "\n"} dbg.print{'execName: ',execName, "\n"} dbg.print{'taskDir: ',taskDir, "\n"} dbg.print{'taskFileName: ',taskFileName, "\n"} dbg.fini("engine initial state") local rtn = taskMain() dbg.fini("engine") return rtn end function engine.verbosityLevel() return engine.verboseCnt end function findDirInDirTree(wd, fn) local masterTbl = masterTbl() local cwd = posix.getcwd() local dir = nil local prev = "" posix.chdir(wd) while (true) do local fullFn = pathJoin(wd, fn) local mystat = posix.stat(fullFn) if (mystat and mystat.type == 'regular') then dir = wd break end if (wd == '/' or wd == prev) then Error("You must be in a project! Did not find: " .. masterTbl.projectFn) end prev = wd posix.chdir("..") wd = posix.getcwd() end posix.chdir(cwd) return dir end function masterTbl() return master end function task(myTable) local name = myTable[1] table.remove(myTable,1) dbg.start{"task{",name,"}"} require(name) local myTask = _G[name]:new(name) myTask:execute(myTable) dbg.fini() end Hermes-0.0.20180315/lib/findInPath.lua000066400000000000000000000100401325256533400167760ustar00rootroot00000000000000_G._DEBUG = false -- Required by luaposix 33 local posix = require("posix") require("strict") local concatTbl = table.concat local function argsPack(...) local arg = { n = select("#", ...), ...} return arg end local pack = (_VERSION == "Lua 5.1") and argsPack or table.pack -------------------------------------------------------------------------- -- remove leading and trailing spaces. -- @param self input string function string.trim(self) local ja = self:find("%S") if (ja == nil) then return "" end local jb = self:find("%s+$") or 0 return self:sub(ja,jb-1) end -------------------------------------------------------------------------- -- An iterator to loop split a pieces. This code is from the -- lua-users.org/lists/lua-l/2006-12/msg00414.html -- @param self input string -- @param pat pattern to split on. function string.split(self, pat) pat = pat or "%s+" local st, g = 1, self:gmatch("()("..pat..")") local function getter(myself, segs, seps, sep, cap1, ...) st = sep and seps + #sep return myself:sub(segs, (seps or 0) - 1), cap1 or sep, ... end local function splitter(myself) if st then return getter(myself, st, g()) end end return splitter, self end -------------------------------------------------------------------------- -- Join argument into a path that has single slashes between directory -- names and no trailing slash. -- @return a file path with single slashes between directory names -- and no trailing slash. function pathJoin(...) local a = {} local arg = pack(...) for i = 1, arg.n do local v = arg[i] if (v and v ~= '') then local vType = type(v) if (vType ~= "string") then local msg = "bad argument #" .. i .." (string expected, got " .. vType .. " instead)\n" assert(vType ~= "string", msg) end v = v:trim() if (v:sub(1,1) == '/' and i > 1) then if (v:len() > 1) then v = v:sub(2,-1) else v = '' end end v = v:gsub('//+','/') if (v:sub(-1,-1) == '/') then if (v:len() > 1) then v = v:sub(1,-2) elseif (i == 1) then v = '/' else v = '' end end if (v:len() > 0) then a[#a + 1] = v end end end local s = concatTbl(a,"/") s = path_regularize(s) return s end -------------------------------------------------------------------------- -- Remove leading and trail spaces and extra slashes. -- @param value A path -- @return A clean canonical path. function path_regularize(value) if value == nil then return nil end value = value:gsub("^%s+", "") value = value:gsub("%s+$", "") value = value:gsub("//+" , "/") value = value:gsub("/%./", "/") value = value:gsub("/$" , "") if (value == '') then value = ' ' return value end local t = {} local icnt = 0 for dir in value:split("/") do icnt = icnt + 1 if ( dir == ".." and icnt > 1) then t[#t] = nil elseif (dir ~= "." or icnt == 1) then t[#t+1] = dir end end value = concatTbl(t,"/") return value end -------------------------------------------------------------------------- -- find the absolute path to an executable. -- @param exec Name of executable -- @param path The path to use. If nil then use env PATH. function findInPath(exec, path) local result = "unknown_path_for_" .. (exec or "unknown") if ( exec == nil) then return result end exec = exec:trim() local i = exec:find(" ") local cmd = exec local tail = "" if (i) then cmd = exec:sub(1,i-1) tail = exec:sub(i) end if (cmd:find("/")) then if (posix.access(cmd,"x")) then return exec else return result end end path = path or os.getenv("PATH") for dir in path:split(":") do local fullcmd = pathJoin(dir, cmd) if (posix.access(fullcmd,"x")) then result = fullcmd .. tail break end end return result end Hermes-0.0.20180315/lib/getUname.lua000066400000000000000000000011371325256533400165260ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") function getUname() local t = {} local osName = posix.uname("%s") local machName = posix.uname("%m") osName = string.gsub(osName,"[ /]","_") if (string.lower(osName) == "aix") then machName = "rs6k" elseif (osName:lower():sub(1,4) == "irix") then osName = "Irix" machName = "mips" end t.osName = osName t.machName = machName t.hostName = posix.uname("%n") t.os_mach = osName .. '-' .. machName t.target = os.getenv("TARGET") or "" return t end Hermes-0.0.20180315/lib/ignoreDirList.lua000066400000000000000000000003231325256533400175330ustar00rootroot00000000000000require("strict") function ignoreDirList() local ignoreT = { ['.'] = 1, ['..'] = 1, ['.svn'] = 1, ['.git'] = 1, CVS = 1, ['.bzr'] = 1, ['.hg'] = 1, ['.span'] = 1} return ignoreT end Hermes-0.0.20180315/lib/tool.lua000077500000000000000000000005071325256533400157410ustar00rootroot00000000000000#!/usr/bin/env lua _DEBUG = false local posix = require("posix") require("strict") function tool() require ("engine") for i = 1,#arg do arg[i-1] = arg[i] end arg[#arg] = nil local execDir, execName = engine.splitCmdName(arg[0]) return engine.execute(execDir, execName) end os.exit(tool()) Hermes-0.0.20180315/mpr/000077500000000000000000000000001325256533400143045ustar00rootroot00000000000000Hermes-0.0.20180315/mpr/BuildMpprunCmd.lua000066400000000000000000000011701325256533400176730ustar00rootroot00000000000000require("fileOps") BuildMpprunCmd = BaseTask:new() function BuildMpprunCmd:execute(myTable) local masterTbl = masterTbl() local pargs = masterTbl.pargs local machineFile = ' ' if (masterTbl.hostlist) then machineFile = '-machinefile ' .. masterTbl.hostlist .. " " end local cmd = findInPath(masterTbl.pargs[1]) if (cmd == nil) then ErrorStd("Did not find Command: "..masterTbl.pargs[1]) end local extra = table.concat(masterTbl.pargs, " ", 2) local mprcmd = "mpirun -np " .. masterTbl.np .. machineFile .. cmd .. " " .. extra --print (mprcmd) os.execute(mprcmd) end Hermes-0.0.20180315/mpr/CmdLineOptions.lua000066400000000000000000000033011325256533400176730ustar00rootroot00000000000000 CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "mpr [options]" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } cmdlineParser:add_option{ name = {'-n','--np'}, dest = 'np', action = 'store', type = 'number', default = 1 } cmdlineParser:add_option{ name = {'--test'}, dest = 'test', action = 'store_true' } cmdlineParser:add_option{ name = {'--wait_done_flag'}, dest = 'wait_done', action = 'store_true' } cmdlineParser:add_option{ name = {'--delete_input_file'}, dest = 'del_input', action = 'store_true' } cmdlineParser:add_option{ name = {'-t','--time'}, dest = 'time', action = 'store', type = 'number' } cmdlineParser:add_option{ name = {'--qsub', '--batch'}, dest = 'batch', action = 'store_true' } cmdlineParser:add_option{ name = {'-q','--qname', '--queueName' }, dest = 'qname', action = 'store' } cmdlineParser:add_option{ name = {'--hostlist','--host'}, dest = 'hostlist', action = 'store' } cmdlineParser:add_option{ name = {'--nodify'}, dest = 'nodify', action = 'store' } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/mpr/mpr.tasks000066400000000000000000000002441325256533400161510ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"ReadProject"} task{"CmdLineOptions"} local masterTbl = masterTbl() task{"BuildMpprunCmd"} return 0 end Hermes-0.0.20180315/newproject/000077500000000000000000000000001325256533400156665ustar00rootroot00000000000000Hermes-0.0.20180315/newproject/CmdLineOptions.lua000066400000000000000000000011461325256533400212620ustar00rootroot00000000000000 CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local Optiks = require("Optiks") local usage = "newproject project_name" cmdlineParser = Optiks:new{usage = usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } local optionTbl, pargs = cmdlineParser:parse(arg) local masterTbl = masterTbl() for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs if (#masterTbl.pargs < 1) then Error("Usage: ",usage) end end Hermes-0.0.20180315/newproject/CreateProject.lua000066400000000000000000000011731325256533400211250ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") CreateProject = BaseTask:new() function CreateProject:execute(myTable) local masterTbl = masterTbl() local projName = masterTbl.pargs[1] os.execute("mkdir ".. projName) posix.chdir(projName) userName = os.getenv("USER") if (userName == nil) then userName = os.getenv("LOGNAME") end if (userName == nil) then userName = '' end tbl = { ProjectName = projName, TestLocation = 'rt', UserName = userName, PackageList = {} } serializeTbl{name="ProjectData", value=tbl, fn="Hermes.db",indent=true} end Hermes-0.0.20180315/newproject/newproject.tasks000066400000000000000000000001471325256533400211170ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"CmdLineOptions"} task{"CreateProject"} return 0 end Hermes-0.0.20180315/pairTest/000077500000000000000000000000001325256533400153015ustar00rootroot00000000000000Hermes-0.0.20180315/pairTest/CmdLineOptions.lua000066400000000000000000000015171325256533400206770ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local Optiks = require("Optiks") local usage = "Usage: pairTest cmd" local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count', help = 'Increasing the level of verbosity help output', } cmdlineParser:add_option{ name = {'-s','--step'}, dest = 'nStep', action = 'store', type = "number", default = -1, help = 'Increasing the level of verbosity help output', } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/pairTest/PairTest.lua000066400000000000000000000047621325256533400175500ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") PairTest = BaseTask:new() require("fileOps") local lfs = require("lfs") local max = math.max local concatTbl = table.concat local ignoreT = { [".msg"] = 1, [".log"] = 1} local function findFiles(path, pattern) local a = {} for file in lfs.dir(path) do local ext = extname(file) if (not ignoreT[ext]) then local i,j = file:find(pattern) if (i) then a[#a + 1] = file end end end table.sort(a) return a end function PairTest:execute(myTable) local masterTbl = masterTbl() local cmd = masterTbl.cmd local OVERWRITE = true local passed = true local nStep = masterTbl.nStep if (not cmd) then masterTbl.status = 1 return end if (nStep < 0) then nStep = cmd.maxStep end for iStep = 0, nStep do posix.setenv(cmd.PREFIX .. "EVENTSTEP", iStep, OVERWRITE) print ("-----------------------------------------") print (" EventStep: "..tostring(iStep)) print ("-----------------------------------------\n") for _,v in ipairs(cmd.runCmd) do io.stdout:write(" Running: ",v,"\n") os.execute("("..v .. ") 2>&1 >/dev/null") end local fn1A = findFiles(cmd.testA.dirs[1], cmd.testA.fn) local fn2A = findFiles(cmd.testA.dirs[2], cmd.testA.fn) local num = max(#fn1A, #fn2A) for i = 1, num do if (fn1A[i] ~= fn2A[i]) then print("1:", tostring(fn1A[i]), "2:", tostring(fn2A[i])) return else local a = {} a[#a + 1] = "cmp" a[#a + 1] = pathJoin(cmd.testA.dirs[1], fn1A[i]) a[#a + 1] = pathJoin(cmd.testA.dirs[2], fn1A[i]) a[#a + 1] = "2>&1 > /tmp/testCmd.out" local cmdStr = concatTbl(a," ") local status = os.execute(cmdStr) if (status ~= 0) then os.execute("cat /tmp/testCmd.out") os.execute("rm /tmp/testCmd.out") os.execute("cat ".. pathJoin(cmd.testA.dirs[1], cmd.testA.fn) .. ".msg") os.execute("cat ".. pathJoin(cmd.testA.dirs[2], cmd.testA.fn) .. ".msg") return end os.execute("rm /tmp/testCmd.out") end end print ("------------------------------------------") print (" EventStep: "..tostring(iStep).." Passed") print ("------------------------------------------") print ("\n") end end Hermes-0.0.20180315/pairTest/ReadCmdFile.lua000066400000000000000000000005521325256533400201050ustar00rootroot00000000000000ReadCmdFile = BaseTask:new() local load = (_VERSION == "Lua 5.1") and loadstring or load function ReadCmdFile:execute(myTable) local masterTbl = masterTbl() local cmdFn = masterTbl.pargs[1] if (not cmdFn) then return end local cmdFile = io.open(cmdFn,"r") local s = cmdFile:read("*all") assert(load(s))() masterTbl.cmd = cmd end Hermes-0.0.20180315/pairTest/example.cmd.lua000066400000000000000000000006661325256533400202110ustar00rootroot00000000000000cmd = { PREFIX = "B2D_", name = "bouss2d", runCmd = { "cd ~/w/Bouss2d_161/; bouss2d -B run/c0_test.nml -I data -O output", "cd ~/w/bouss2d/; bouss2d -B run/c0_test.nml -I data -O output",}, testCmd = { "cd ~/w/bouss2d/; cmp ~/w/Bouss2d_161/output/c0_test.mtx output/c0_test.mtx", "cd ~/w/bouss2d/; cmp ~/w/Bouss2d_161/output/c0_test.soln output/c0_test.soln",}, maxStep = 1 } Hermes-0.0.20180315/pairTest/pairTest.tasks000066400000000000000000000002151325256533400201410ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"CmdLineOptions"} task{"ReadCmdFile"} task{"PairTest"} return masterTbl().status end Hermes-0.0.20180315/ptop_cmd/000077500000000000000000000000001325256533400153135ustar00rootroot00000000000000Hermes-0.0.20180315/ptop_cmd/ProjectTop.lua000066400000000000000000000015531325256533400201130ustar00rootroot00000000000000ProjectTop = BaseTask:new() _DEBUG = false local posix = require("posix") require("strict") require("fileOps") local lfs = require("lfs") function ProjectTop:execute(myTable) local masterTbl = masterTbl() local pargs = masterTbl.pargs local wd = lfs.currentdir() local packageDir = masterTbl.packageDir local i,j = wd:find(packageDir) if (i == nil) then io.stderr:write("Current directory not in a project: ",wd,"\n") return end local topDir = pathJoin(masterTbl.projectDir, masterTbl.packageName) if ((masterTbl.verbosityLevel or 0) > 1) then io.stderr:write ("topDir", topDir, "\n") end local attr = lfs.attributes(topDir) if (attr == nil or attr.mode ~= 'directory') then io.stderr:write ("topDir: ".. topDir.." not found") return end print ("cd " .. topDir) end Hermes-0.0.20180315/ptop_cmd/ptop_cmd.tasks000066400000000000000000000001641325256533400201700ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"ReadProject"} task{"ProjectTop"} return masterTbl().status end Hermes-0.0.20180315/testFinish/000077500000000000000000000000001325256533400156265ustar00rootroot00000000000000Hermes-0.0.20180315/testFinish/CmdLineOptions.lua000066400000000000000000000020351325256533400212200ustar00rootroot00000000000000-- $Id: CmdLineOptions.lua 302 2009-02-04 23:56:32Z mclay $ -- CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "testfinish [options]" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-c'}, dest = 'cmdResultFn', action = 'store', type = 'string', } cmdlineParser:add_option{ name = {'-r','--resultFn'}, dest = 'resultFn', action = 'store', type = 'string', } cmdlineParser:add_option{ name = {'-t','--runtimeFn'}, dest = 'runtimeFn', action = 'store', type = 'string', } cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/testFinish/Finish.lua000066400000000000000000000056411325256533400175570ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") require("build_epoch") require("serializeTbl") require("getUname") require("fileOps") require("string_utils") local dbg = require("Dbg"):dbg() local lfs = require("lfs") local load = (_VERSION == "Lua 5.1") and loadstring or load Finish = BaseTask:new() function Finish.parseInput(self, fnA) local result = "passed" for i = 1, #fnA do local fn = fnA[i] local attr = lfs.attributes(fn) if ( not attr or type(attr) ~= "table" or attr.mode ~= "file") then return "failed" end local ext = extname(fn) local singleR if (ext == ".lua") then singleR = self:parseLuaResult(fn) else singleR = self:parseCSVResult(fn) end if (singleR ~= "passed") then return singleR end end return result end acceptT = { failed = true, passed = true, diff = true } function Finish.parseCSVResult(self, fn) local result = "passed" local f = io.open(fn,"r") local whole = f:read("*all") local found = false f:close() for line in whole:split("\n") do line = line:trim() local first = line:sub(1,1) if (first ~= "#" and line:len() > 0) then local word = line local idx = line:find(',') if (idx) then word = line:sub(1, idx-1) end word = word:lower() found = true if (word ~= "passed") then result = word break end end end if (not found) then result = "failed" end return acceptT[result] and result or "failed" end function Finish.parseLuaResult(self, fn) local f = io.open(fn,"r") local result = "passed" local found = false if (f) then local s = f:read("*all") assert(load(s))() for i,v in ipairs(myTbl) do local word = v.result:lower() found = true if (word ~= "passed") then result = word end end end if (not found) then result = "failed" end return acceptT[result] and result or "failed" end function Finish.execute(self,myTable) local masterTbl = masterTbl() --------------------------------------------------------------- -- Diff tools write out "result.lua" local resultFn = masterTbl.resultFn local runtimeFn = masterTbl.runtimeFn local pargs = masterTbl.pargs if (masterTbl.cmdResultFn) then pargs[#pargs+1] = masterTbl.cmdResultFn end local result = self:parseInput(pargs) local myResult = { testresult = result } serializeTbl{name="myResult", value=myResult, fn=resultFn, indent=true} local t = getUname() build_epoch() assert(loadfile(runtimeFn))() runtime.end_time = epoch() for k in pairs(t) do runtime[k] = t[k] end serializeTbl{name="runtime", value=runtime, fn=runtimeFn, indent=true} end Hermes-0.0.20180315/testFinish/testFinish.tasks000066400000000000000000000002411325256533400210120ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"ReadProject"} -- Project file shows top of dir tree task{"CmdLineOptions"} task{"Finish"} return 0 end Hermes-0.0.20180315/testcleanup/000077500000000000000000000000001325256533400160355ustar00rootroot00000000000000Hermes-0.0.20180315/testcleanup/CmdLineOptions.lua000066400000000000000000000015061325256533400214310ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "testcleanup [options]" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } cmdlineParser:add_option{ name = {'-k','--keep'}, dest = 'keep', action = 'store', type = 'number', default = 0 } cmdlineParser:add_option{ name = {'--show'}, dest = 'show', action = 'store_true', } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/testcleanup/FindAllTmFiles.lua000066400000000000000000000020221325256533400213310ustar00rootroot00000000000000require("strict") require("dirlist") require("fileOps") require("ignoreDirList") local lfs = require("lfs") FindAllTmFiles = BaseTask:new() function FindAllTmFiles:execute(myTable) local masterTbl = masterTbl() local testRptRootDir = masterTbl.testRptRootDir local pattern = masterTbl.testRptExt local tmTbl = {} self:allTMFiles(testRptRootDir, pattern, tmTbl) table.sort(tmTbl) for i = 1, masterTbl.keep do table.remove(tmTbl) -- remove last entry end masterTbl.tmfiles = tmTbl end function FindAllTmFiles:allTMFiles(path, pattern, t) local ignoreT = ignoreDirList() for file in lfs.dir(path) do if (not ignoreT[file]) then local f = pathJoin(path, file) local attr = lfs.attributes (f) assert (type(attr) == "table") if (attr.mode == "directory") then self:allTMFiles(f, pattern, t) elseif (file:sub(1,2) ~= ".#" and file:find(pattern,1,true)) then t[#t + 1] = f end end end end Hermes-0.0.20180315/testcleanup/Initialize.lua000066400000000000000000000011421325256533400206370ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") require("getUname") require("fileOps") Initialize = BaseTask:new() function Initialize:execute(myTable) local masterTbl = masterTbl() masterTbl.testlistFn = "my.tests" masterTbl.testRptLoc = "testreports" masterTbl.testRptExt = ".tm" masterTbl.descriptExt = ".tdesc" masterTbl.testRptRootDir = pathJoin(masterTbl.projectDir, masterTbl.testRptLoc) local t = getUname() masterTbl.os_mach = t.os_mach masterTbl.hostname = t.hostName masterTbl.target = t.target end Hermes-0.0.20180315/testcleanup/RemoveTestDirs.lua000066400000000000000000000040221325256533400214550ustar00rootroot00000000000000require("dirlist") require("fileOps") require("ignoreDirList") RemoveTestDirs = BaseTask:new() local function execute(cmd) if (masterTbl().show) then print (cmd) else os.execute(cmd) end end function RemoveTestDirs:execute(myTable) local masterTbl = masterTbl() local cmd --------------------------------------------- -- Remove test directories from each .tm file -- then remove the test for i,v in ipairs(masterTbl.tmfiles) do self:removeDir(v) cmd = "rm ".. v execute(cmd) end --------------------------------------------- -- Remove the target directories in -- "masterTbl.testRptRootDir" local ignoreT = ignoreDirList() local t = dirlist(masterTbl.testRptRootDir) local targetA = t.dirs for _,target in ipairs(targetA) do if (not ignoreT[target]) then local dir = pathJoin(masterTbl.testRptRootDir, target) local list = dirlist(dir) -- '.' and '..' are automatically removed by 'dirlist' if (#list.files == 0) then cmd = "rm -rf " .. dir execute(cmd) end end end end function RemoveTestDirs:removeDir(file) -- read each tm file and remove test local masterTbl = masterTbl() local cmd assert(loadfile(file))() for i,v in ipairs(testresults.tests) do -- Convert id into testdir name local i, j, dir, fn, idTag = v.id:find("(.*)/([^/]*)/(.*)") if (i == nil) then dir = "./" _, _, fn, idTag = v.id:find("([^/]*)/(.*)") end local outputDir = pathJoin(masterTbl.projectDir, v.outputDir) if (isDir(outputDir)) then cmd = "rm -rf ".. outputDir execute(cmd) end local idDir = pathJoin(masterTbl.projectDir, dir, idTag) if (isDir(idDir)) then local list = dirlist(idDir) -- '.' and '..' are automatically removed by 'dirlist' if (#list.files == 0 or masterTbl.keep == 0) then cmd = "rm -rf " .. idDir execute(cmd) end end end end Hermes-0.0.20180315/testcleanup/testcleanup.tasks000066400000000000000000000003251325256533400214330ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"ReadProject"} task{"Initialize"} task{"CmdLineOptions"} local masterTbl = masterTbl() task{"FindAllTmFiles"} task{"RemoveTestDirs"} return 0 end Hermes-0.0.20180315/tm/000077500000000000000000000000001325256533400141265ustar00rootroot00000000000000Hermes-0.0.20180315/tm/AnalyzeTests.lua000066400000000000000000000065711325256533400172700ustar00rootroot00000000000000require("strict") require("common") local Dbg = require("Dbg") AnalyzeTests = BaseTask:new() local load = (_VERSION == "Lua 5.1") and loadstring or load MyResult = nil function AnalyzeTests:execute(myTable) local masterTbl = myTable.masterTbl local tstTbl = masterTbl.tstTbl local rptTbl = masterTbl.rptTbl local dbg = Dbg:dbg() local tstSummary = {} local testValues = Tst:testresultValues() for k in pairs(testValues) do tstSummary[k] = 0 end tstSummary.total = 0 masterTbl.errors = 0 masterTbl.diffCnt = 0 masterTbl.failCnt = 0 masterTbl.totalTestTime = 0 local epoch = masterTbl.currentEpoch if (next(tstTbl) == nil) then epoch = masterTbl.origEpoch end local status = 'passed' if (next(rptTbl) == nil) then status = ' ' end for id in pairs(rptTbl) do local tst = rptTbl[id] if (not tst:get("runInBackground")) then local resultFn = fullFn(tst:get('resultFn')) assert(loadfile(resultFn))() local result = myResult.testresult:lower() dbg.print{"tst.testName: ", tst.testName, " result: ",result,"\n"} -- Save result in current test tst:set('result', result) -- Accumulate test results if (testValues[result] == nil) then result = result or "nil" Error("Unknown test result: " .. result .. " from: " .. resultFn) end tstSummary[result] = tstSummary[result] + 1 tstSummary.total = tstSummary.total + 1 if (testValues[result] < testValues[status] ) then status = result end if (result ~= 'passed') then masterTbl.errors = masterTbl.errors + 1 end if (result == 'diff') then masterTbl.diffCnt = masterTbl.diffCnt + 1 end if (result == 'failed') then masterTbl.failCnt= masterTbl.failCnt + 1 end -- Save runtime in current test assert(loadfile(fullFn(tst:get('runtimeFn'))))() local tstTime local t, _ if (runtime.start_time < 0 or runtime.end_time < 0) then tstTime = '****' t = -1 else t = runtime.end_time - runtime.start_time _, _, tstTime = string.format("%10.3g", t):find("^%s*([0123456789.-e+]+%s*)") masterTbl.totalTestTime = masterTbl.totalTestTime + t end local versionFn = fullFn(tst:get("versionFn")) local f = io.open(versionFn,"r") if (f) then local s = f:read("*all") assert(load(s))() tst:set('ProgVersion',ProgVersion) f:close() end local messageFn = fullFn(tst:get("messageFn")) local f = io.open(messageFn,"r") if (f) then local s = f:read("*all") assert(load(s))() tst:set('message',messageTbl.message) f:close() end tst:set('runtime', t) tst:set('strRuntime', tstTime) for k in pairs(runtime) do tst:set(k,runtime[k]) end end end if (masterTbl.totalTestTime <= 0) then masterTbl.errors = 0 end masterTbl.tstSummary = tstSummary masterTbl.status = status masterTbl.epoch = epoch end Hermes-0.0.20180315/tm/Batch.lua000066400000000000000000000013171325256533400156540ustar00rootroot00000000000000require("strict") local masterTbl = masterTbl() local concatTbl = table.concat local execute = os.execute local dbg = require("Dbg"):dbg() local M = inheritsFrom(JobSubmitBase) M.my_name = "Batch" function M.queue(tbl, envTbl, funcTbl) local t = funcTbl.batchTbl.queueTbl local name = tbl.name local result = t[name] or name return result end function M.runtest(self, tbl) local logFileNm = masterTbl.batchLog or tbl.idTag .. ".log" local a = {} a[#a + 1] = self.batchTbl.submitCmd a[#a + 1] = tbl.scriptFn a[#a + 1] = ">>" a[#a + 1] = logFileNm a[#a + 1] = "2>&1" local s = concatTbl(a," ") execute(s) end return M Hermes-0.0.20180315/tm/BatchSystem.lua000066400000000000000000000062521325256533400170640ustar00rootroot00000000000000BatchSystems = { SLURM = { stampede = { submitHeader = [[ # stampede #SBATCH -J $(JOBNAME) #SBATCH -o $(JOBNAME).%j.out #SBATCH -p $(QUEUE) #SBATCH -N $(NODES) #SBATCH -n $(NP) #SBATCH -t $(TIME) #SBATCH -A $(ACCOUNT) ]], maxCoresPerNode = 16, }, }, SGE = { ranger = { submitHeader= [[ # ranger #$ -V #$ -cwd #$ -N $(JOBNAME) #$ -A $(ACCOUNT) #$ -pe $(NPway NP=$(NP), NODES=$(NODES), WAY=$(WAY)) #$ -q $(QUEUE) #$ -l h_rt=$(TIME) ]], maxCoresPerNode = 16, }, longhorn = { submitHeader= [[ # longhorn #$ -V #$ -cwd #$ -N $(JOBNAME) #$ -P hpc #$ -A $(ACCOUNT) #$ -pe $(NPway NP=$(NP), NODES=$(NODES), WAY=$(WAY)) #$ -q $(QUEUE) #$ -l h_rt=$(TIME) ]], maxCoresPerNode = 8, }, ls4 = { submitHeader= [[ # lonestar #$ -V #$ -cwd #$ -N $(JOBNAME) #$ -A $(ACCOUNT) #$ -pe $(NPway NP=$(NP), NODES=$(NODES), WAY=$(WAY)) #$ -q $(QUEUE) #$ -l h_rt=$(TIME) ]], maxCoresPerNode = 12, }, }, PBS = { harvard = { submitHeader= [[ #PBS -N $(JOBNAME) #PBS -A $(ACCOUNT) #PBS -q $(QUEUE) #PBS -o $(LOGNAME) #PBS -l walltime="$(TIME)" #PBS -l size="$(NP)" #PBS -j oe ]], maxCoresPerNode = 16, }, garnet = { submitHeader= [[ #PBS -V #PBS -N $(JOBNAME) #PBS -A $(ACCOUNT) #PBS -q $(QUEUE) #PBS -l walltime=$(TIME) #PBS -l ncpus=$(NP) #PBS -j oe #PBS -o $(JOBNAME).oe # START OF COMMANDS umask 007 umask cd $PBS_O_WORKDIR ]], maxCoresPerNode = 16, }, diamond = { submitHeader= [[ #PBS -V #PBS -N $(JOBNAME) #PBS -A $(ACCOUNT) #PBS -q $(QUEUE) #PBS -l walltime=$(TIME) #PBS -l ncpus=$(NP) #PBS -j oe # START OF COMMANDS umask 007 umask cd $PBS_O_WORKDIR ]], maxCoresPerNode = 16, }, chugach = { submitHeader= [[ #PBS -V #PBS -N $(JOBNAME) #PBS -A $(ACCOUNT) #PBS -q $(QUEUE) #PBS -l walltime=$(TIME) #PBS -l mppwidth=$(NP) #PBS -j oe # START OF COMMANDS umask 007 umask cd $PBS_O_WORKDIR ]], maxCoresPerNode = 16, }, }, } Hermes-0.0.20180315/tm/BatchSystemDefault.lua000066400000000000000000000066001325256533400203660ustar00rootroot00000000000000BatchSystems = { INTERACTIVE = { default = { submitHeader = "", mprCmd = "mpirun -np $(NP) $(CMD) $(CMD_ARGS)", CurrentWD = ".", maxCoresPerNode = 1, submitCmd = "", queueTbl = {}, }, }, SGE = { default = { submitHeader= [[ #$ -V #$ -cwd #$ -N $(JOBNAME) #$ -A $(ACCOUNT) #$ -pe $(NPway NP=$(NP) NODES=$(NODES) WAY=$(WAY)) #$ -q $(QUEUE) #$ -l h_rt=$(TIME) ]], mprCmd = "ibrun $(CMD) $(CMD_ARGS)", submitCmd = "qsub ", queueTbl = {short="development", medium="normal", long="long", systest="systest"}, CurrentWD = ".", maxCoresPerNode = 1, NODES = -1, WAY = -1, NPway = function(tbl, envTbl, funcTbl) local batchTbl = funcTbl.batchTbl local np = tonumber(tbl.NP) or -1 local npWay local maxWay = batchTbl.maxCoresPerNode local userWay = tonumber(tbl.WAY) or -1 local way if (userWay > 0 ) then way = userWay else way = batchTbl.maxCoresPerNode end local nNodes = -1 local userNodes = tonumber(tbl.NODES) or -1 if (userNodes > 0) then nNodes = userNodes end if (nNodes > 0) then npWay = tostring(way) .. "way " .. tostring(nNodes*maxWay) elseif (np <= maxWay and way == maxWay) then npWay = tostring(np) .. "way " .. maxWay else nNodes = math.ceil(np/way) npWay = way .. "way " .. tostring(nNodes*maxWay) end return npWay end, } }, LSF = { default = { submitHeader= [[ #BSUB -J $(JOBNAME) #BSUB -q $(QUEUE) #BSUB -W $(TIME) #BSUB -o $(LOGNAME) #BSUB -W $(TIME) #BSUB -n $(NP) ]], mprCmd = "ibrun $(CMD) $(CMD_ARGS)", submitCmd = "bsub < ", CurrentWD = "$LS_SUBCWD", maxCoresPerNode = 1, }, }, SLURM = { default = { submitHeader= [[ #SBATCH -J $(JOBNAME) #SBATCH -o $(LOGNAME) #SBATCH -p $(QUEUE) #SBATCH -N $(NODES) #SBATCH -n $(NP) #SBATCH -t $(TIME) #SBATCH -A $(ACCOUNT) ]], mprCmd = "ibrun $(CMD) $(CMD_ARGS)", submitCmd = "sbatch ", CurrentWD = ".", maxCoresPerNode = 1, }, }, PBS = { default = { submitHeader= [[ #PBS -N $(JOBNAME) #PBS -A $(ACCOUNT) #PBS -q $(QUEUE) #PBS -o $(LOGNAME) #PBS -l walltime="$(TIME)" #PBS -l size="$(NP)" #PBS -j oe ]], mprCmd = "aprun -n $(NP) $(CMD) $(CMD_ARGS)", submitCmd = "qsub ", CurrentWD = "$PBS_O_WORKDIR", maxCoresPerNode = 1, }, }, } Hermes-0.0.20180315/tm/BuildMasterTbl.lua000066400000000000000000000034221325256533400175070ustar00rootroot00000000000000require("strict") BuildMasterTbl = BaseTask:new() function BuildMasterTbl:execute(myTable) local masterTbl = masterTbl() -------------------------------------------------------------------------- -- This is very tricky: the 'mt' metatable uses the metamethod to extract -- values from the parent master table if they don't exist in the child -- master table. local mt = { __index = function (t,k) return t.mtblFunc()[k] end } local mtblFunc = masterTbl.mtblFunc if (not masterTbl.tagTbl) then masterTbl.tagTbl = {} for _,tag in ipairs(masterTbl.tagA) do masterTbl.tagTbl[tag] = {} masterTbl.tagTbl[tag].targetTbl = {} masterTbl.tagTbl[tag].mtblFunc = mtblFunc masterTbl.tagTbl[tag].tag = tag setmetatable(masterTbl.tagTbl[tag], mt) for _, target in ipairs(masterTbl.targetA) do masterTbl.tagTbl[tag].targetTbl[target] = {} masterTbl.tagTbl[tag].targetTbl[target].tag = tag masterTbl.tagTbl[tag].targetTbl[target].target = target masterTbl.tagTbl[tag].targetTbl[target].mtblFunc = mtblFunc setmetatable(masterTbl.tagTbl[tag].targetTbl[target], mt) end end return end for tag in pairs(masterTbl.tagTbl) do masterTbl.tagTbl[tag].mtblFunc = mtblFunc masterTbl.tagTbl[tag].tag = tag setmetatable(masterTbl.tagTbl[tag], mt) for target in pairs(masterTbl.tagTbl[tag].targetTbl) do masterTbl.tagTbl[tag].targetTbl[target].tag = tag masterTbl.tagTbl[tag].targetTbl[target].target = target masterTbl.tagTbl[tag].targetTbl[target].mtblFunc = mtblFunc setmetatable(masterTbl.tagTbl[tag].targetTbl[target], mt) end end end Hermes-0.0.20180315/tm/CmdLineOptions.lua000066400000000000000000000125641325256533400175300ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") require("common") require("string_utils") require("fileOps") require("version") CmdLineOptions = BaseTask:new() local function vname() return "tm "..Version end function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "Usage: tm [options] [file] [directory]" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage,version=vname(), error = Error} cmdlineParser:add_option{ name = {'-a','--analyze'}, dest = 'analyzeFlag', action = 'store_true', help = 'Analyze for the current target', } cmdlineParser:add_option{ name = {'-A','--Analyze'}, dest = 'AnalyzeFlag', action = 'store_true', help = 'Analyze for the all targets', } cmdlineParser:add_option{ name = {'-b','--batch'}, dest = 'BatchFlag', action = 'store_true', help = 'Submit tests to a batch queue', } cmdlineParser:add_option{ name = {'--batchlog'}, dest = 'batchLog', action = 'store', help = 'filename to capture submit script info', } cmdlineParser:add_option{ name = {'--epoch'}, dest = 'epoch', action = 'store', type = 'number', default = -1, help = 'Use the epoch given', } cmdlineParser:add_option{ name = {'-f','--full'}, dest = 'full', action = 'store_true', help = 'Report individual test results when spanning targets', } cmdlineParser:add_option{ name = {'-g','--generate'}, dest = 'generate', action = 'store_true', help = 'Generate a test list and store in "my.tests" in project directory', } cmdlineParser:add_option{ name = {'-k','--keyword'}, dest = 'keywords', action = 'append', help = 'A keyword to select tests', } cmdlineParser:add_option{ name = {'--interactive'}, dest = 'InteractiveFlag', action = 'store_true', help = 'Force batch run to be interactive.', } cmdlineParser:add_option{ name = {'-m','--min', '--minNP'}, dest = 'minNP', action = 'store', type = 'number', help = 'the minimum number of processor that will be run', } cmdlineParser:add_option{ name = {'-n', '--times'}, dest = 'ntimes', action = 'store', type = 'number', default = 1, help = 'Run each test the number of times given', } cmdlineParser:add_option{ name = {'-r','--restart'}, dest = 'restart', action = 'append', type = 'string', help = 'A restart criteria to select tests to rerun, "-r wrong" will restart all test that did not pass', } cmdlineParser:add_option{ name = {'-R','--Restart'}, dest = 'Restart', action = 'append', type = 'string', help = 'A restart criteria to select tests to rerun, "-r wrong" will restart all test that did not pass. This will span targets, "-r" only does the current target', } cmdlineParser:add_option{ name = {'-s','--status'}, dest = 'statusList', action = 'append', type = 'string', help = 'Only print individual test that match a particular status, "-s wrong" reports all tests that do not pass', } cmdlineParser:add_option{ name = {'-t','--target'}, dest = 'targetList', action = 'append', type = 'string', help = 'A target string. It sets $(TARGET) in runScript', } cmdlineParser:add_option{ name = {'--tag'}, dest = 'tagA', action = 'append', type = 'string', help = 'Tag test with string given', } cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count', help = 'Increasing the level of verbosity help output', } cmdlineParser:add_option{ name = {'-D','--debug'}, dest = 'debugLevel', action = 'count', help = 'Increasing the level of debug support', } cmdlineParser:add_option{ name = {'-x','--max', '--maxNP'}, dest = 'maxNP', action = 'store', type = 'number', help = 'the maximum number of processor that will be run', } local optionTbl, pargs = cmdlineParser:parse(arg) if (#optionTbl.Restart > 0) then optionTbl.restart = optionTbl.Restart end if (optionTbl.AnalyzeFlag) then optionTbl.analyzeFlag = optionTbl.AnalyzeFlag end for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs masterTbl.cwd = posix.getcwd() if (masterTbl.batchLog) then if (masterTbl.batchLog:sub(1,1) ~= '/') then masterTbl.batchLog = pathJoin(masterTbl.cwd,masterTbl.batchLog) end posix.unlink(masterTbl.batchLog) end masterTbl.tagA = expandOptions(masterTbl.tagA) masterTbl.targetList = expandOptions(masterTbl.targetList) masterTbl.spanning = masterTbl.AnalyzeFlag or (#masterTbl.Restart > 0) or (#masterTbl.tagA > 0) or (#masterTbl.targetList > 1) end function expandOptions(aa) local a = {} for _,v in ipairs(aa) do for s in v:split("[ :,]") do s = s:trim() if (s ~= "") then a[#a+1] = s end end end return a end Hermes-0.0.20180315/tm/CreateTestReport.lua000066400000000000000000000015541325256533400200750ustar00rootroot00000000000000require("strict") CreateTestReport = BaseTask:new() require("serializeTbl") require("fileOps") function CreateTestReport:execute(myTable) local masterTbl = masterTbl() local target = myTable.target local prefix = "" if (target ~= "") then prefix = target .. "-" end local uuid = prefix .. UUIDString(masterTbl.epoch) .. "-" .. masterTbl.os_mach local tstReportFn = pathJoin(masterTbl.testRptDir, uuid .. masterTbl.testRptExt) masterTbl.tstReportFn = tstReportFn -------------------------------------------------------- -- Do not create a report when there are no tests to run if (next(masterTbl.tstTbl) == nil) then return end local HumanData = '' local testresults = buildTestReportTable(HumanData,masterTbl) serializeTbl{name="testresults", value=testresults, fn=tstReportFn, indent=true} end Hermes-0.0.20180315/tm/FindTests.lua000066400000000000000000000232161325256533400165400ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") FindTests = BaseTask:new() require("common") require("Tst") require("dirlist") require("fileOps") local Dbg = require("Dbg") function FindTests:execute(myTable) local masterTbl = masterTbl() local pargs = {} local dbg = Dbg:dbg() masterTbl.candidateTsts = {} if (masterTbl.spanning ~= myTable.spanning) then return end for _,v in ipairs(masterTbl.pargs) do pargs[#pargs + 1] = v end if (#pargs < 1) then if (#masterTbl.restart > 0 or masterTbl.analyzeFlag) then FindTests:findLastTM(pargs) else local fn = pathJoin(masterTbl.projectDir, masterTbl.testlistFn) if (isFile(fn)) then pargs[#pargs + 1] = fn else pargs[#pargs + 1] = "." end end elseif (#masterTbl.restart > 0 or masterTbl.analyzeFlag) then for i = 1, #pargs do local path = pargs[i] local ext = extname(path) if (ext ~= ".tm") then Error("Illegal file: ",path,"\n", "The options -r and -a expect *.tm files in the $(projectdir)/testreport directory\n", "or none when using the last generated testing run") end end end for i,path in ipairs(pargs) do local mystat = posix.stat(path) if (mystat == nil) then path = pathJoin(masterTbl.projectDir,path) mystat = posix.stat(path) end dbg.print{"Reading: ",path,"\n"} if (mystat and mystat.type == "regular") then if (path:find(masterTbl.testRptExt.."$")) then FindTests:readTMfile(path) elseif (path:find(masterTbl.descriptExt.."$")) then FindTests:readTestDescriptFn(path) else FindTests:readTestList(path) end else dbg.print{"Searching: ",path,"\n"} FindTests:search(path) end end end function FindTests:buildCandidateTsts(testA, ntimes, target, epoch, candidateTsts) local idA = {} for _,v in ipairs(testA) do idA[#idA+1] = v.id end FindTests:buildCandidateTsts_id(idA, ntimes, target, epoch, candidateTsts) local tstKeys = Tst:testfields() -- Copy results from previous run to current test. -- Active is controlled by user input not last run. for _,v in ipairs(testresults.tests) do local tst = candidateTsts[v.id] v.active = tst:get("active") for _,key in ipairs(tstKeys) do tst[key] = v[key] end end end function FindTests:readTestDescriptFn(path) local masterTbl = masterTbl() local tagA = masterTbl.tagA local targetA = masterTbl.targetA local fn = pathJoin(posix.getcwd(), path) local epoch = masterTbl.origEpoch local dbg = Dbg:dbg() assert(loadfile(fn))() dbg.print{"Found: ",fn,"\n"} if (masterTbl.spanning) then masterTbl.tagTbl = masterTbl.tagTbl or {} for _,tag in ipairs(tagA) do masterTbl.tagTbl[tag] = masterTbl.tagTbl[tag] or {} masterTbl.tagTbl[tag].targetTbl = masterTbl.tagTbl[tag].targetTbl or {} local targT = masterTbl.tagTbl[tag].targetTbl for _,target in ipairs(targetA) do targT[target] = targT[target] or {} targT[target].candidateTsts = targT[target].candidateTsts or {} targT[target].target = target local candidateTsts = targT[target].candidateTsts local tstTbl = buildTstTbl(fn, testdescript, target, epoch, masterTbl.ntimes) for id in pairs(tstTbl) do candidateTsts[id] = tstTbl[id] end targT[target].epoch = epoch end end else local target = masterTbl.target local tstTbl = buildTstTbl(fn, testdescript, target, epoch, masterTbl.ntimes) masterTbl.epoch = epoch masterTbl.target = target masterTbl.candidateTsts = masterTbl.candidateTsts or {} local candidateTsts = masterTbl.candidateTsts for id in pairs(tstTbl) do candidateTsts[id] = tstTbl[id] end end end function FindTests:readTMfile(path) local masterTbl = masterTbl() local tagA = masterTbl.tagA local dbg = Dbg:dbg() dbg.print{"readTMfile: ",path,"\n"} assert(loadfile(path))() -- Use original Epoch from TM file local epoch = testresults.origEpoch local ntimes = testresults.ntimes masterTbl.ntimes = ntimes if (masterTbl.spanning) then local tag = testresults.tag masterTbl.tagTbl = masterTbl.tagTbl or {} masterTbl.tagTbl[tag] = masterTbl.tagTbl[tag] or {} masterTbl.tagTbl[tag].origEpoch = epoch masterTbl.tagTbl[tag].targetTbl = masterTbl.tagTbl[tag].targetTbl or {} local targT = masterTbl.tagTbl[tag].targetTbl for target in pairs(testresults.tests.targetTbl) do local a = testresults.tests.targetTbl[target] targT[target] = targT[target] or {} targT[target].candidateTsts = targT[target].candidateTsts or {} FindTests:buildCandidateTsts(a, ntimes, target, epoch, targT[target].candidateTsts) targT[target].ntimes = ntimes targT[target].origEpoch = epoch targT[target].epoch = epoch targT[target].tag = testresults.tag end else local target = testresults.target local a = testresults.tests masterTbl.candidateTsts = masterTbl.candidateTsts or {} masterTbl.tag = testresults.tag masterTbl.epoch = epoch masterTbl.origEpoch = epoch masterTbl.target = target FindTests:buildCandidateTsts(a, ntimes, target, epoch, masterTbl.candidateTsts) end end function FindTests:readTestList(fn) local masterTbl = masterTbl() local tagA = masterTbl.tagA local targetA = masterTbl.targetA local dbg = Dbg:dbg() dbg.print{"readTestList: ",fn,"\n"} assert(loadfile(fn))() local epoch = masterTbl.origEpoch local ntimes = masterTbl.ntimes if (masterTbl.spanning) then masterTbl.tagTbl = masterTbl.tagTbl or {} for tag in ipairs(tagA) do masterTbl.tagTbl[tag] = masterTbl.tagTbl[tag] or {} masterTbl.tagTbl[tag].targetTbl = masterTbl.tagTbl[tag].targetTbl or {} local targT = masterTbl.tagTbl[tag].targetTbl for target in ipairs(targetA) do targT[target] = targT[target] or {} targT[target].epoch = epoch targT[target].candidateTsts = targT[target].candidateTsts or {} FindTests:buildCandidateTsts_id(testlist, ntimes, target, epoch, targT[target].candidateTsts) end end else masterTbl.epoch = epoch local target = targetA[1] masterTbl.target = targetA[1] masterTbl.candidateTsts = masterTbl.candidateTsts or {} FindTests:buildCandidateTsts_id(testlist, ntimes, target, epoch, masterTbl.candidateTsts) end end function FindTests:buildCandidateTsts_id(idA, ntimes, target, epoch, candidateTsts) local masterTbl = masterTbl() -- Transform id into test description file -- with a list of id's used local fnTbl = {} for _,id in ipairs(idA) do local _, _, fn, idTag = id:find("^(.*)/(.*)") fn = pathJoin(masterTbl.projectDir, fn .. ".tdesc") fnTbl[fn] = fnTbl[fn] or {} table.insert(fnTbl[fn],id) end local cwd = posix.getcwd() -- Read in test description file, store tests with id -- in masterTbl.candidateTsts for fn in pairs(fnTbl) do local d, f = splitFileName(fn) posix.chdir(d) assert(loadfile(f))() local tstTbl = buildTstTbl(fn, testdescript, target, epoch, ntimes) for i,id in ipairs(fnTbl[fn]) do candidateTsts[id] = tstTbl[id] end end posix.chdir(cwd) end function FindTests:search(path) local dbg = Dbg:dbg() local masterTbl = masterTbl() if (not posix.access(path)) then return end local cwd = posix.getcwd() posix.chdir(path) if (masterTbl.verbosityLevel > 3) then dbg.print{"Searching: ",posix.getcwd(),"\n"} end dbg.print{"FindTests:search dirlist(\".\")"} local list = dirlist(".") local found = false for _,v in ipairs(list.files) do if (v:find("%.tdesc$")) then FindTests:readTestDescriptFn(v) found = true end end if (not found) then for _,v in ipairs(list.dirs) do local dir = pathJoin(posix.getcwd(), v) FindTests:search(dir) end end posix.chdir(cwd) end function FindTests:findLastTM(pargs) local dbg = Dbg:dbg() local masterTbl = masterTbl() local pattern = masterTbl.os_mach .. '%' .. masterTbl.testRptExt .. "$" pattern = pattern:gsub("%-", "%%-") local tmTbl = {} local testRptDir = masterTbl.testRptDir local tagA if (masterTbl.spanning) then tagA = masterTbl.tagA else tagA = {''} end for _, tag in ipairs(tagA) do if (masterTbl.spanning) then testRptDir = pathJoin(masterTbl.testRptDirRoot,".span",tag) end dbg.print{"FindTests:findLastTM: filelist(\"",testRptDir ,"\")\n"} local list = filelist(testRptDir) for _,v in ipairs(list) do if (v:find(pattern)) then tmTbl[#tmTbl + 1] = v end end local tmFileName = nil if (#tmTbl > 0) then table.sort(tmTbl) for i = #tmTbl, 1, -1 do local fn = pathJoin(testRptDir, tmTbl[i]) local attr = lfs.attributes(fn) if (attr and attr.size > 0) then tmFileName = fn; break end end end if (tmFileName) then pargs[#pargs+1] = tmFileName end end end Hermes-0.0.20180315/tm/Gauntlet.lua000066400000000000000000000014211325256533400164120ustar00rootroot00000000000000require("strict") Gauntlet = {} function Gauntlet.new(self, gauntletData) local o = {} setmetatable(o,self) self.__index = self self.gauntletData = gauntletData self.dispatchTbl = gauntletData.dispatchTbl self.runTbl = {} return o end function Gauntlet.add(self, name, value) local setupFn = self.dispatchTbl[name][1] local applyFn = self.dispatchTbl[name][2] if (value == nil) then return end if (type(value) == "table" and #value < 1) then return end setupFn(self.gauntletData, name, value) self.runTbl[name] = applyFn end function Gauntlet.apply(self, candidateTsts) for name in pairs(self.runTbl) do local applyFn = self.runTbl[name] applyFn(self.gauntletData, name, candidateTsts) end end Hermes-0.0.20180315/tm/GauntletData.lua000066400000000000000000000040711325256533400172100ustar00rootroot00000000000000require("strict") require("Tst") GauntletData = {} function GauntletData.setupNP(self, name, value) if (value[1]) then self.minNP = value[1] end if (value[2]) then self.maxNP = value[2] end end function GauntletData.setupList(self, name, value) self.data[name] = value end function GauntletData.applyNP(self, name, candidateTsts) for id in pairs(candidateTsts) do local tst = candidateTsts[id] if (tst:get('active')) then np = tst:get('np') tst:set('active', (self.minNP <= np ) and (np <= self.maxNP)) end end end function GauntletData.applyKeyword(self, name, candidateTsts) for id in pairs(candidateTsts) do local tst = candidateTsts[id] if (tst:get('active')) then tst:set('active', tst:hasAllKeywords(self.data[name])) end end end function GauntletData.setupRestart(self, name, value) local restartValueTbl = {} local testresultTbl = Tst:testresultValues() for _,v in ipairs(value) do if (v == 'wrong') then for v in pairs(testresultTbl) do if (testresultTbl[v] < testresultTbl['passed']) then restartValueTbl[v] = 1 end end elseif (testresultTbl[v]) then restartValueTbl[v] = 1 end end self.restartValueTbl = restartValueTbl end function GauntletData.applyRestart(self, name, candidateTsts) for id in pairs(candidateTsts) do local tst = candidateTsts[id] local active = tst:get('active') if (tst:get('active')) then local result = tst:get('result') if (self.restartValueTbl[result] ~= nil) then tst:set('active', true ) else tst:set('report', true ) tst:set('active', false) end end end end function GauntletData:new(o) o = o or {} setmetatable(o,self) self.__index = self o.dispatchTbl = { keywords = { GauntletData.setupList, GauntletData.applyKeyword }, NP = { GauntletData.setupNP, GauntletData.applyNP }, restart = { GauntletData.setupRestart, GauntletData.applyRestart } } o.minNP = 0 o.maxNP = 1.e20 o.data = {} return o end Hermes-0.0.20180315/tm/Initialize.lua000066400000000000000000000127201325256533400167340ustar00rootroot00000000000000require("strict") require("GauntletData") require("Gauntlet") require("getUname") require("dirlist") require("version") require("string_utils") require("ignoreDirList") require("fileOps") Initialize = BaseTask:new() JobSubmitBase = {} local function processTag(tagA) local masterTbl = masterTbl() for i, tag in ipairs(tagA) do local ltag = tag:lower() if (ltag == 'today') then tag = ymdString(epoch()) elseif (ltag == 'yesterday') then tag = ymdString(epoch()-86400.0) end tagA[i] = tag end ----------------------------------------------------------------- -- if Analyzing or Restarting and no tags (or '*') then -- get file names in .span directory. -- if no tag specified then use last directory in list -- if tag = '*' then get all dirs. if ((#tagA < 1 or tagA[1] == '*') and (masterTbl.AnalyzeFlag or #masterTbl.Restart > 0)) then local dir = pathJoin(masterTbl.testRptDirRoot, ".span") local a = filelist(dir) table.sort(a) if (#tagA < 1) then tagA[1] = a[#a] else tagA = {} for _,v in ipairs(a) do tagA[#tagA+1] = v end end end if (#tagA < 1) then tagA[1] = ymdString(masterTbl.currentEpoch) end return tagA, table.concat(tagA," ") end function Initialize:execute(myTable) local mtblFunc = masterTbl local masterTbl = masterTbl() masterTbl.testRptLoc = "testreports" masterTbl.testRptDirRoot = pathJoin(masterTbl.projectDir, masterTbl.testRptLoc) masterTbl.tstReportFn = nil masterTbl.mtblFunc = mtblFunc masterTbl.testlistFn = "my.tests" masterTbl.targExt = ".targ" masterTbl.testRptExt = ".tm" masterTbl.descriptExt = ".tdesc" masterTbl.TM_Version = "TM "..Version masterTbl.Lua_Version = _G._VERSION masterTbl.errors = 0 masterTbl.diffCnt = 0 masterTbl.failCnt = 0 masterTbl.setparent = function(k,v) local mtbl = masterTbl.mtblFunc() mtbl[k] = v end JobSubmitBase = require("JobSubmitBase") ---------------------------------------------------------------------------------- -- Use user supplied command line epoch if given (default is -1) masterTbl.currentEpoch = epoch() if (masterTbl.epoch > 0) then masterTbl.currentEpoch = masterTbl.epoch end masterTbl.origEpoch = masterTbl.currentEpoch masterTbl.tagA, masterTbl.tagString = processTag(masterTbl.tagA) ----------------------------------------------------------------------------------- -- Add projectDir to package.path for user functions package.path = masterTbl.projectDir .. "/?;" .. masterTbl.projectDir .. "/?.lua;" .. package.path -- Get os info and store in masterTbl local t = getUname() for k in pairs(t) do masterTbl[k] = t[k] end -- Create name for span report local currentUUid = UUIDString(masterTbl.origEpoch) .. "-" .. masterTbl.os_mach masterTbl.tstSpanReportFn = pathJoin(masterTbl.testRptDirRoot, ".span", currentUUid .. masterTbl.testRptExt) -- Setup up gauntlet masterTbl.gauntlet = Gauntlet:new(GauntletData:new()) local testresultValues = Tst:testresultValues() local testresultsTbl = {} if (#masterTbl.statusList == 0) then testresultsTbl = testresultValues else for _,v in ipairs(masterTbl.statusList) do if (v == 'wrong') then for k in pairs(testresultValues) do if (testresultValues[k] < testresultValues['passed']) then testresultsTbl[k] = 1 end end else testresultsTbl[v] = 1 end end end masterTbl.testresultsTbl = testresultsTbl Initialize:build_targetA() masterTbl.spanning = masterTbl.AnalyzeFlag or (#masterTbl.Restart > 0) or (#masterTbl.tagA > 1) or (#masterTbl.targetA > 1) end function Initialize:build_targetA() local masterTbl = masterTbl() local mtblFunc = masterTbl.mtblFunc local targetA = {} masterTbl.targetA = targetA for _,v in ipairs(masterTbl.targetList) do targetA[#targetA + 1] = v end Initialize:processTargFiles() if (#targetA < 1 and not masterTbl.spanning) then targetA[1] = os.getenv("TARGET") or os.getenv("TARG_SUMMARY") or "" end end function Initialize:processTargFiles() local masterTbl = masterTbl() local pargs = {} local pattern = '%' .. masterTbl.targExt .. "$" for _,item in ipairs(masterTbl.pargs) do if (item:find(pattern)) then Initialize:readTargFile(item) else pargs[#pargs + 1] = item end end masterTbl.pargs = pargs end function Initialize:readTargFile(fn) local masterTbl = masterTbl() local f = assert(io.open(fn,"r")) local s = f:read("*all") local t = {} for line in s:split("\n") do local i = line:find('#') if (i) then line = line:sub(1,i-1) end if (not line:find('^%s*$')) then t[#t + 1] = line end end s = table.concat(t,"\n") t = {} for item in s:split("%s+") do t[item] = 1 end local tt = {} for k in pairs(t) do tt[#tt + 1] = k end table.sort(tt) local targetA = masterTbl.targetA for _,v in ipairs(tt) do targetA[#targetA + 1] = v end f:close() end Hermes-0.0.20180315/tm/Interactive.lua000066400000000000000000000013441325256533400171100ustar00rootroot00000000000000require("strict") require("inherits") local assert = assert local concatTbl = table.concat local date = os.date local execute = os.execute local findInPath = findInPath local format = string.format local loadfile = loadfile local print = print local systemG = _G local M = inheritsFrom(JobSubmitBase) M.my_name = "INTERACTIVE" function M.runtest(self, tbl) local a = {} a[#a + 1] = "./" .. tbl.scriptFn a[#a + 1] = ">" a[#a + 1] = tbl.idTag .. ".log" a[#a + 1] = "2>&1" if (tbl.background) then a[#a + 1] = "> or %<%string%>% (I like <>) *End # Local Variables: # mode: outline # end: Hermes-0.0.20180315/tm/ReportAllResults.lua000066400000000000000000000143641325256533400201270ustar00rootroot00000000000000require("strict") ReportAllResults = BaseTask:new() require("ReportResults") require("fileOps") require("TermWidth") function ReportAllResults:execute(myTable) local tagA = masterTbl().tagA if (#tagA < 2) then return end local masterTbl = masterTbl() ReportAllResults:summarize(masterTbl) local totalTime = os.date("!%T", masterTbl.span.totalTime) local e = string.format("%.2f", masterTbl.span.totalTime - math.floor(masterTbl.span.totalTime)) local _, _, extra = e:find("0.(.*)") totalTime = totalTime .. "." .. extra local date = os.date("%c", masterTbl.currentEpoch) local spanSummary = masterTbl.span.Summary local HumanDataA = {} local targetA = masterTbl.targetA local width = TermWidth() - 1 local HDR = string.rep("*", width) local STR = "*** Span Test Results" local TS = "*** Test Summary " local TSl = width - TS:len() - 3 STR = STR .. string.rep(" ",TRl) .. "***" TS = TS .. string.rep(" ",TRl) .. "***" table.insert(HumanDataA, 0) table.insert(HumanDataA, HDR) table.insert(HumanDataA, STR) table.insert(HumanDataA, HDR) table.insert(HumanDataA, " ") table.insert(HumanDataA, 0) table.insert(HumanDataA, 2) table.insert(HumanDataA, {"ProjectDir:", masterTbl.packageDir}) table.insert(HumanDataA, {"Date:", date}) table.insert(HumanDataA, {"TM Version:", Version}) table.insert(HumanDataA, {"Tag:", masterTbl.tagString}) table.insert(HumanDataA, {"Hermes Version:", masterTbl.HermesVersion}) table.insert(HumanDataA, {"Lua Version:", _G._VERSION}) table.insert(HumanDataA, {"Total Test Time:", totalTime}) table.insert(HumanDataA, -2) table.insert(HumanDataA, 0) table.insert(HumanDataA, " ") table.insert(HumanDataA, HDR) table.insert(HumanDataA, TS) table.insert(HumanDataA, HDR) table.insert(HumanDataA, " ") table.insert(HumanDataA, 0) table.insert(HumanDataA, 2) table.insert(HumanDataA, {"Total: ", spanSummary.total}) for v in pairs(spanSummary) do local count = spanSummary[v] if (v ~= "total" and count > 0) then table.insert(HumanDataA, { v..":", count}) end end table.insert(HumanDataA, -2) table.insert(HumanDataA, 0) table.insert(HumanDataA, "") table.insert(HumanDataA, 0) if (masterTbl.full) then table.insert(HumanDataA, 7) table.insert(HumanDataA, {"*******","*","****","***","******","*********","***************"}) table.insert(HumanDataA, {"Results","R","Time","Tag","Target","Test Name","version/message"}) table.insert(HumanDataA, {"*******","*","****","***","******","*********","***************"}) local resultTbl = {} for tag in pairs(masterTbl.tagTbl) do for target in pairs(masterTbl.tagTbl[tag].targetTbl) do local tbl = masterTbl.tagTbl[tag].targetTbl[target] local rptTbl = tbl.rptTbl local testresultsTbl = tbl.testresultsTbl for id in pairs(rptTbl) do local tst = rptTbl[id] local aFlag = " " if (tst:get("active")) then aFlag = "R" end local result = tst:get('result') local runtime = tst:get('strRuntime') local txt = tst:get('ProgVersion') local message = tst:get('message') if (message:len() > 0) then txt = message end if (testresultsTbl[result]) then table.insert(resultTbl, {result, aFlag, runtime, tag, target, id, txt}) end end end end table.sort(resultTbl, function (a, b) if (a[1] == b[1]) then return (b[4] > a[4]) else return (a[1] > b[1]) end end) for i, v in ipairs(resultTbl) do table.insert(HumanDataA,v) end table.insert(HumanDataA, -7) table.insert(HumanDataA, 0) table.insert(HumanDataA, "") table.insert(HumanDataA, 0) end table.insert(HumanDataA, 2) table.insert(HumanDataA, {"*******","***"}) table.insert(HumanDataA, {"Results","Tag"}) table.insert(HumanDataA, {"*******","***"}) local testresultsTbl = masterTbl.testresultsTbl for tag in pairs(masterTbl.tagTbl) do local status = masterTbl.tagTbl[tag].status if (testresultsTbl[status]) then table.insert(HumanDataA, {status, tag}) end end table.insert(HumanDataA, -2) local HumanData = ReportResults:FormatHumanData(HumanDataA) if (masterTbl.span.totalTime > 0 or masterTbl.AnalyzeFlag) then print(HumanData) end end function ReportAllResults:summarize(masterTbl) local span = {} local totalTime = 0 local numRpt = 0 local currentEpoch = 0 local origEpoch = 0 local numTests = 0 local testValues = Tst:testresultValues() local tstSummary local status span.Summary = {} for tag in pairs(masterTbl.tagTbl) do status = "passed" for target in pairs(masterTbl.tagTbl[tag].targetTbl) do local tbl = masterTbl.tagTbl[tag].targetTbl[target] if (testValues[tbl.status] < testValues[status]) then status = tbl.status end numRpt = numRpt + countEntries(tbl.rptTbl) numTests = numTests + countEntries(tbl.tstTbl) totalTime = totalTime + tbl.totalTestTime currentEpoch = math.max(currentEpoch, tbl.currentEpoch) origEpoch = math.max(origEpoch, tbl.origEpoch) tstSummary = tbl.tstSummary for v in pairs(tstSummary) do span.Summary[v] = (span.Summary[v] or 0) + tstSummary[v] end end masterTbl.tagTbl[tag].status = status end span.currentEpoch = currentEpoch span.origEpoch = origEpoch span.numRpt = numRpt span.numTests = numTests span.totalTime = totalTime masterTbl.span = span end Hermes-0.0.20180315/tm/ReportResults.lua000066400000000000000000000146671325256533400175040ustar00rootroot00000000000000require("strict") require("Tst") require("common") require("serializeTbl") require("TermWidth") ReportResults = BaseTask:new() function ReportResults:execute(myTable) local width = TermWidth() - 1 local masterTbl = myTable.masterTbl local tstTbl = masterTbl.tstTbl local rptTbl = masterTbl.rptTbl local HumanDataA = {} local tstSummary = masterTbl.tstSummary local totalTime = os.date("!%T", math.floor(masterTbl.totalTestTime)) local e = string.format("%.2f", masterTbl.totalTestTime - math.floor(masterTbl.totalTestTime)) local _, _, extra = e:find("0.(.*)") totalTime = totalTime .. "." .. extra local testresultsTbl = masterTbl.testresultsTbl local icount = 0 for id in pairs(rptTbl) do local tst = rptTbl[id] local result = tst:get('result') if (testresultsTbl[result]) then icount = icount + 1 end end local HDR = string.rep("*", width) local TR = "*** Test Results" local TS = "*** Test Summary" local TRl = width - TR:len() - 3 TR = TR .. string.rep(" ", TRl) .. "***" TS = TS .. string.rep(" ", TRl) .. "***" table.insert(HumanDataA, 0) table.insert(HumanDataA, HDR) table.insert(HumanDataA, TR) table.insert(HumanDataA, HDR) table.insert(HumanDataA, " ") table.insert(HumanDataA, 0) table.insert(HumanDataA, 2) table.insert(HumanDataA, {"Date:", masterTbl.date}) table.insert(HumanDataA, {"TARGET:", masterTbl.target}) table.insert(HumanDataA, {"Tag:", masterTbl.tag}) table.insert(HumanDataA, {"TM Version:", Version}) table.insert(HumanDataA, {"Hermes Version:", masterTbl.HermesVersion}) table.insert(HumanDataA, {"Lua Version:", _G._VERSION}) table.insert(HumanDataA, {"Total Test Time:", totalTime}) table.insert(HumanDataA, -2) table.insert(HumanDataA, 0) table.insert(HumanDataA, " ") table.insert(HumanDataA, HDR) table.insert(HumanDataA, TS) table.insert(HumanDataA, HDR) table.insert(HumanDataA, " ") table.insert(HumanDataA, 0) table.insert(HumanDataA, 2) table.insert(HumanDataA, {"Total: ", tstSummary.total}) for v in pairs(tstSummary) do local count = tstSummary[v] if (v ~= "total" and count > 0) then table.insert(HumanDataA, { v..":", count}) end end table.insert(HumanDataA, -2) table.insert(HumanDataA, 0) table.insert(HumanDataA, "") table.insert(HumanDataA, 0) table.insert(HumanDataA, 5) table.insert(HumanDataA, {"*******","*","****","*********","***************"}) table.insert(HumanDataA, {"Results","R","Time","Test Name","version/message"}) table.insert(HumanDataA, {"*******","*","****","*********","***************"}) local resultTbl = {} for id in pairs(rptTbl) do local tst = rptTbl[id] local aFlag = " " if (tst:get("active")) then aFlag = "R" end local result = tst:get('result') local runtime = tst:get('strRuntime') local txt = tst:get('ProgVersion') local message = tst:get('message') if (message:len() > 0) then txt = message end if (testresultsTbl[result]) then table.insert(resultTbl, {result, aFlag, runtime, id, txt}) end end table.sort(resultTbl, function (a, b) if (a[1] == b[1]) then return (b[4] > a[4]) else return (a[1] > b[1]) end end) for i, v in ipairs(resultTbl) do table.insert(HumanDataA,v) end table.insert(HumanDataA, -5) table.insert(HumanDataA, 0) table.insert(HumanDataA, "") table.insert(HumanDataA, 0) if (tstSummary.total ~= tstSummary.passed) then table.insert(HumanDataA, 2) table.insert(HumanDataA, {"*******", "****************"}) table.insert(HumanDataA, {"Results", "Output Directory"}) table.insert(HumanDataA, {"*******", "****************"}) resultTbl = {} for id in pairs(rptTbl) do local tst = rptTbl[id] local result = tst:get('result') if (result ~= "passed" and testresultsTbl[result]) then table.insert(resultTbl, {result, fullFn(tst:get('outputDir'))}) end end table.sort(resultTbl, function (a, b) if (a[1] == b[1]) then return (b[2] > a[2]) else return (b[1] > a[1]) end end) for i, v in ipairs(resultTbl) do table.insert(HumanDataA,v) end table.insert(HumanDataA, -2) end local HumanData = ReportResults:FormatHumanData(HumanDataA) if (masterTbl.totalTestTime > 0 and not masterTbl.spanning and icount > 0) then print(HumanData) end if (icount > 0) then local testresultT = buildTestReportTable(HumanData, masterTbl) serializeTbl{name="testresults", value=testresultT, fn=masterTbl.tstReportFn, indent=true} end end function ReportResults:FormatHumanData(HumanDataA) local tbl = {} local numCols = HumanDataA[1] local HumanData = '' local method if (numCols == 0) then method = "strings" else method = "column" end table.remove(HumanDataA,1) for i,v in ipairs(HumanDataA) do if (type(v) == 'number') then if (numCols == -v) then -- Time to write HumanData = HumanData .. ReportResults[method](ReportResults, tbl, numCols) numCols = -10 tbl = {} else numCols = v if (numCols == 0) then method = "strings" else method = "columns" end end else table.insert(tbl, v) end end return HumanData end function ReportResults:strings(tbl, numCols) return table.concat(tbl, "\n") .. "\n" end function ReportResults:columns(tbl, numCols) local w local widths = {} for icol = 1, numCols do w = 0 for i,v in ipairs(tbl) do if (type(v[icol]) ~= "string") then v[icol] = tostring(v[icol]) end w = math.max(w, v[icol]:len()) end widths[icol] = w + 2 end for icol = 1, numCols-1 do w = widths[icol] for i,v in ipairs(tbl) do local blankLen = w - v[icol]:len() v[icol] = v[icol] .. string.rep(" ", blankLen) end end local s = {} for i,v in ipairs(tbl) do table.insert(s, table.concat(v)) end return table.concat(s,"\n") .. "\n" end Hermes-0.0.20180315/tm/ReportSpanResults.lua000066400000000000000000000165421325256533400203200ustar00rootroot00000000000000require("strict") require("serializeTbl") require("ReportResults") require("fileOps") require("TermWidth") ReportSpanResults = BaseTask:new() function ReportSpanResults:execute(myTable) local tag = myTable.tag local tagA = masterTbl().tagA local origEpoch = masterTbl().origEpoch if (not masterTbl().spanning) then return end local masterTbl = masterTbl().tagTbl[tag] ReportSpanResults:summarize(masterTbl) local totalTime = os.date("!%T", masterTbl.span.totalTime) local e = string.format("%.2f", masterTbl.span.totalTime - math.floor(masterTbl.span.totalTime)) local _, _, extra = e:find("0.(.*)") totalTime = totalTime .. "." .. extra local date = os.date("%c", masterTbl.currentEpoch) local spanSummary = masterTbl.span.Summary local HumanDataA = {} local width = TermWidth() - 1 local HDR = string.rep("*", width) local STR = "*** Span Test Results" local TS = "*** Test Summary " local TSl = width - TS:len() - 3 STR = STR .. string.rep(" ",TRl) .. "***" TS = TS .. string.rep(" ",TRl) .. "***" table.insert(HumanDataA, 0) table.insert(HumanDataA, HDR) table.insert(HumanDataA, STR) table.insert(HumanDataA, HDR) table.insert(HumanDataA, " ") table.insert(HumanDataA, 0) table.insert(HumanDataA, 2) table.insert(HumanDataA, {"ProjectDir:", masterTbl.packageDir}) table.insert(HumanDataA, {"Date:", date}) table.insert(HumanDataA, {"TM Version:", Version}) table.insert(HumanDataA, {"Tag:", masterTbl.tag}) table.insert(HumanDataA, {"Hermes Version:", masterTbl.HermesVersion}) table.insert(HumanDataA, {"Lua Version:", _G._VERSION}) table.insert(HumanDataA, {"Total Test Time:", totalTime}) table.insert(HumanDataA, -2) table.insert(HumanDataA, 0) table.insert(HumanDataA, " ") table.insert(HumanDataA, HDR) table.insert(HumanDataA, TS) table.insert(HumanDataA, HDR) table.insert(HumanDataA, " ") table.insert(HumanDataA, 0) table.insert(HumanDataA, 2) table.insert(HumanDataA, {"Total: ", spanSummary.total}) for v in pairs(spanSummary) do local count = spanSummary[v] if (v ~= "total" and count > 0) then table.insert(HumanDataA, { v..":", count}) end end table.insert(HumanDataA, -2) table.insert(HumanDataA, 0) table.insert(HumanDataA, "") table.insert(HumanDataA, 0) if (masterTbl.full) then table.insert(HumanDataA, 6) table.insert(HumanDataA, {"*******","*","****","******","*********","***************"}) table.insert(HumanDataA, {"Results","R","Time","Target","Test Name","version/message"}) table.insert(HumanDataA, {"*******","*","****","******","*********","***************"}) local resultTbl = {} for target in pairs(masterTbl.targetTbl) do local rptTbl = masterTbl.targetTbl[target].rptTbl local testresultsTbl = masterTbl.targetTbl[target].testresultsTbl for id in pairs(rptTbl) do local tst = rptTbl[id] local aFlag = " " if (tst:get("active")) then aFlag = "R" end local result = tst:get('result') local runtime = tst:get('strRuntime') local txt = tst:get('ProgVersion') local message = tst:get('message') if (message:len() > 0) then txt = message end if (testresultsTbl[result]) then table.insert(resultTbl, {result, aFlag, runtime, target, id, txt}) end end end table.sort(resultTbl, function (a, b) if (a[1] == b[1]) then return (b[4] > a[4]) else return (a[1] > b[1]) end end) for i, v in ipairs(resultTbl) do table.insert(HumanDataA,v) end table.insert(HumanDataA, -6) table.insert(HumanDataA, 0) table.insert(HumanDataA, "") table.insert(HumanDataA, 0) end table.insert(HumanDataA, 2) table.insert(HumanDataA, {"*******","******"}) table.insert(HumanDataA, {"Results","TARGET"}) table.insert(HumanDataA, {"*******","******"}) local testresultsTbl = masterTbl.testresultsTbl for target in pairs(masterTbl.targetTbl) do local status = masterTbl.targetTbl[target].status if (testresultsTbl[status]) then table.insert(HumanDataA, {status,target}) end end table.insert(HumanDataA, -2) local HumanData = ReportResults:FormatHumanData(HumanDataA) if (#tagA == 1 and (masterTbl.span.totalTime > 0 or masterTbl.AnalyzeFlag)) then print(HumanData) end local epoch = masterTbl.origEpoch if (masterTbl.span.numTests > 0) then epoch = masterTbl.currentEpoch end local uuid = UUIDString(epoch) .. "-" .. masterTbl.os_mach masterTbl.tstSpanReportFn = pathJoin(masterTbl.testRptDirRoot,".span",masterTbl.tag, uuid .. masterTbl.testRptExt) if (masterTbl.span.numRpt > 0) then local testresultT = ReportSpanResults:buildTestReportTable(HumanData,masterTbl) serializeTbl{name="testresults", value=testresultT, fn=masterTbl.tstSpanReportFn, indent=true} end end function ReportSpanResults:summarize(masterTbl) local span = {} local totalTime = 0 local numRpt = 0 local numTests = 0 local tstSummary span.Summary = {} for target in pairs(masterTbl.targetTbl) do local tbl = masterTbl.targetTbl[target] numRpt = numRpt + countEntries(tbl.rptTbl) numTests = numTests + countEnties(tbl.tstTbl) totalTime = totalTime + tbl.totalTestTime tstSummary = tbl.tstSummary for v in pairs(tstSummary) do span.Summary[v] = (span.Summary[v] or 0) + tstSummary[v] end end span.numRpt = numRpt span.numTests = numTests span.totalTime = totalTime masterTbl.span = span end function ReportSpanResults:buildTestReportTable(HumanData, masterTbl) local testresults = { HumanData = HumanData, date = masterTbl.date, currentUUid = masterTbl.currentUUid, origUUid = masterTbl.origUUid, currentEpoch = masterTbl.currentEpoch, origEpoch = masterTbl.origEpoch, machType = masterTbl.os_mach, hostname = masterTbl.hostname, Targ = masterTbl.targ, tag = masterTbl.tag, ntimes = masterTbl.ntimes, TotalTestTime = masterTbl.totalTestTime, TM_Version = masterTbl.TM_Version, Hermes_Version = masterTbl.HermesVersion, Lua_Version = _G._VERSION, tests = {}, } testresults.tests.targetTbl = {} local testfields = Tst:testfields() for target in pairs(masterTbl.targetTbl) do local rptTbl = masterTbl.targetTbl[target].rptTbl local tests = {} for id in pairs(rptTbl) do local tst = rptTbl[id] local testData = {} for i,v in ipairs(testfields) do testData[v] = tst:get(v) end tests[#tests + 1] = testData end testresults.tests.targetTbl[target] = tests end return testresults end Hermes-0.0.20180315/tm/ResetMasterTbl.lua000066400000000000000000000003751325256533400175360ustar00rootroot00000000000000require("strict") ResetMasterTbl = BaseTask:new() function ResetMasterTbl:execute(myTable) local masterTbl = masterTbl() local mtblFunc = masterTbl.mtblFunc masterTbl = mtblFunc() _G.masterTbl = function() return masterTbl end end Hermes-0.0.20180315/tm/RunActiveTests.lua000066400000000000000000000123021325256533400175520ustar00rootroot00000000000000_DEBUG = false local posix = require("posix") require("strict") require("common") require("JobSubmitBase") require("serializeTbl") require("CleanEnv") require("findInPath") local dbg = require("Dbg"):dbg() RunActiveTests = BaseTask:new() comment = [[ Test Results: 'notfinished': means that the test has started but not completed. 'failed': means that the test has started but not completed. 'notrun': test has not started running. 'diff' : Test has run but is different from gold copy. 'passed': Test has run and matches gold copy.]] resultTbl = { started = { testresult = 'notfinished', comment = comment }, notrun = { testresult = 'notrun', comment = comment }, } local function MakeDir(path) local paths = {} local myPath = fixFileName(path) while (1) do local i, j if (isDir(myPath)) then break end table.insert(paths, 1, myPath) i, j, myPath = myPath:find("^(.*)/") if (not i) then break end end for _,v in ipairs(paths) do posix.mkdir(v) end end function RunActiveTests:execute(myTable) local masterTbl = masterTbl() masterTbl.passed = 0 masterTbl.failed = 0 local numTests = 0 local rptTests = 0 for tag in pairs(masterTbl.tagTbl) do for target in pairs(masterTbl.tagTbl[tag].targetTbl) do numTests = numTests + countEntries(masterTbl.tagTbl[tag].targetTbl[target].tstTbl) rptTests = rptTests + countEntries(masterTbl.tagTbl[tag].targetTbl[target].rptTbl) end end masterTbl.rptTests = rptTests if (numTests > 0) then print("\nStarting Tests:\n") end cleanEnv() local i = 0 for tag in pairs(masterTbl.tagTbl) do for target in pairs(masterTbl.tagTbl[tag].targetTbl) do local mTbl = masterTbl.tagTbl[tag].targetTbl[target] _G.masterTbl = function() return mTbl end local cwd = posix.getcwd() local tstTbl = mTbl.tstTbl mTbl.passed = masterTbl.passed mTbl.failed = masterTbl.failed RunActiveTests:makeOutputDirs(tstTbl) for id in pairs(tstTbl) do i = i+1 RunActiveTests:runTest(mTbl, tstTbl[id], i, numTests) end posix.chdir(cwd) masterTbl.passed = masterTbl.passed + mTbl.passed masterTbl.failed = masterTbl.failed + mTbl.failed end end _G.masterTbl = function() return masterTbl end masterTbl = _G.masterTbl() if (numTests > 0) then print("\nFinished Tests\n") end end function RunActiveTests.makeOutputDirs(self, tstTbl) local runtime = { start_time = -1, end_time = -1 } for id in pairs(tstTbl) do local tst = tstTbl[id] local outputDir = tst:get('outputDir') MakeDir(fullFn(outputDir)) end for id in pairs(tstTbl) do local tst = tstTbl[id] local resultFn = fullFn(tst:get('resultFn') ) local runtimeFn = fullFn(tst:get('runtimeFn') ) serializeTbl{name="myResult", value=resultTbl.notrun, fn=resultFn , indent=true} serializeTbl{name="runtime", value=runtime, fn=runtimeFn, indent=true} end end function RunActiveTests:runTest(masterTbl, tst, iTest, numTests) local fn_envA = {'testDir', 'outputDir', 'resultFn', 'testdescriptFn', 'cmdResultFn', 'messageFn', 'runtimeFn'} local envA = {'idTag', 'testName', 'packageName', 'packageDir', 'TARGET', 'target', 'tag',} local envTbl = {} for _,v in ipairs(fn_envA) do envTbl[v] = fixFileName(fullFn(tst:get(v))); end for _,v in ipairs(envA) do envTbl[v] = tst:get(v); end envTbl.projectDir = masterTbl.projectDir ------------------------------------------------------------ -- Find job submit method local jobSubmitMethod = tst:get("job_submit_method") or "INTERACTIVE" if (masterTbl.BatchFlag) then jobSubmitMethod = "BATCH" elseif (masterTbl.InteractiveFlag) then jobSubmitMethod = "INTERACTIVE" end local job = JobSubmitBase:build(jobSubmitMethod, masterTbl) local runScript = tst:expandRunScript(envTbl, job) local cwd = posix.getcwd() posix.chdir(envTbl.outputDir) posix.unlink(fullFn(tst:get('cmdResultFn'))) local resultFn = fullFn(tst:get('resultFn')) serializeTbl{name='myResult', value=resultTbl.started, fn=resultFn, indent=true} local t = epoch() local stime = { start_time = t, end_time = -1 } tst:set('start_epoch', t) serializeTbl{name="runtime", value=stime, fn=fullFn(tst:get('runtimeFn')), indent=true} local idTag = envTbl.idTag local scriptFn = idTag .. ".script" local f = assert(io.open(scriptFn,"w")) f:write(tst:topOfScript(),"\n") f:write(runScript) f:close() posix.chmod(scriptFn,"rwx------") local id = tst:get('id') local background = tst:get('background') or (jobSubmitMethod == "BATCH") tst:set('runInBackground',background) job:Msg('Started', iTest, numTests, id, envTbl.resultFn, background) job:runtest{scriptFn = scriptFn, idTag = idTag, background = background} job:Msg('Finished', iTest, numTests, id, envTbl.resultFn, background) posix.chdir(cwd) end Hermes-0.0.20180315/tm/SelectTests.lua000066400000000000000000000020551325256533400170750ustar00rootroot00000000000000require("strict") require("Gauntlet") SelectTests = BaseTask:new() function SelectTests:execute(myTable) local masterTbl = masterTbl() local target = myTable.target -- Run the gauntlet on the candidate tests. if (masterTbl.minNP or masterTbl.maxNP ) then local procA = {} table.insert(procA, masterTbl.minNP) table.insert(procA, masterTbl.maxNP) masterTbl.gauntlet:add('NP', procA) end masterTbl.gauntlet:add('keywords', masterTbl.keywords) masterTbl.gauntlet:add('restart', masterTbl.restart) masterTbl.gauntlet:apply(masterTbl.candidateTsts) local analyzeFlag = masterTbl.analyzeFlag masterTbl.tstTbl = {} masterTbl.rptTbl = {} masterTbl.resultMaxLen = 12 for id in pairs(masterTbl.candidateTsts) do local tst = masterTbl.candidateTsts[id] if (analyzeFlag or tst:get('report')) then masterTbl.rptTbl[id] = tst elseif (tst:get('active')) then masterTbl.tstTbl[id] = tst masterTbl.rptTbl[id] = tst end end end Hermes-0.0.20180315/tm/SpecializeMasterTbl.lua000066400000000000000000000011541325256533400205400ustar00rootroot00000000000000require("strict") SpecializeMasterTbl = BaseTask:new() require("fileOps") function SpecializeMasterTbl:execute(myTable) local tag = myTable.tag local target = myTable.target local masterTbl = masterTbl() local origTbl = masterTbl.mtblFunc() local tbl = origTbl.tagTbl[tag].targetTbl[target] local prefix = "" if (target ~= "") then prefix = target .. "-" end tbl.testRptDir = pathJoin(tbl.projectDir, tbl.testRptLoc, target) tbl.tag = tag tbl.target = target _G.masterTbl = function() return origTbl.tagTbl[tag].targetTbl[target] end end Hermes-0.0.20180315/tm/TAGS000066400000000000000000000064011325256533400146100ustar00rootroot00000000000000 AnalyzeTests.lua,37 function AnalyzeTests:execute(9,218 Batch.lua,52 function M.queue(12,241 function M.runtest(22,447 BuildMasterTbl.lua,38 function BuildMasterTbl:execute(4,92 CmdLineOptions.lua,102 local function vname(11,223 function CmdLineOptions:execute(16,277 function expandOptions(189,5158 CreateTestReport.lua,41 function CreateTestReport:execute(8,145 FindTests.lua,338 function FindTests:execute(10,217 function FindTests:buildCandidateTsts(67,1949 function FindTests:readTestDescriptFn(88,2543 function FindTests:readTMfile(128,4188 function FindTests:readTestList(169,5911 function FindTests:buildCandidateTsts_id(202,7206 function FindTests:search(231,8061 function FindTests:findLastTM(260,8773 Gauntlet.lua,90 function Gauntlet.new(6,74 function Gauntlet.add(18,312 function Gauntlet.apply(31,634 GauntletData.lua,279 function GauntletData.setupNP(6,96 function GauntletData.setupList(11,252 function GauntletData.applyNP(15,335 function GauntletData.applyKeyword(25,607 function GauntletData.setupRestart(34,856 function GauntletData.applyRestart(51,1316 function GauntletData:new(67,1732 Initialize.lua,206 local function processTag(16,297 function Initialize:execute(56,1409 function Initialize:build_targetA(130,4188 function Initialize:processTargFiles(147,4619 function Initialize:readTargFile(162,4984 Interactive.lua,52 function M.runtest(19,467 function M.queue(33,749 JobSubmitBase.lua,284 function M.name(17,258 function M.tableMerge(21,308 function M.Msg(40,716 function M.formatMsg(58,1359 function M.findcmd(72,1867 local function findFileInPackagePath(78,2009 function M.mpr(90,2259 function M.CWD(98,2454 function M.submit(102,2533 function M.build(108,2736 ReportAllResults.lua,87 function ReportAllResults:execute(9,168 function ReportAllResults:summarize(142,5076 ReportResults.lua,170 function ReportResults:execute(10,174 function ReportResults:FormatHumanData(160,5140 function ReportResults:strings(198,5868 function ReportResults:columns(202,5960 ReportSpanResults.lua,148 function ReportSpanResults:execute(10,193 function ReportSpanResults:summarize(153,5535 function ReportSpanResults:buildTestReportTable(181,6291 ResetMasterTbl.lua,38 function ResetMasterTbl:execute(5,97 RunActiveTests.lua,162 local function MakeDir(30,722 function RunActiveTests:execute(46,1065 function RunActiveTests:makeOutputDirs(99,2501 function RunActiveTests:runTest(125,3396 SelectTests.lua,35 function SelectTests:execute(4,50 SpecializeMasterTbl.lua,44 function SpecializeMasterTbl:execute(6,126 Tst.lua,432 function buildTstTbl(8,141 function Tst:initFmt(24,503 function Tst.new(34,725 function Tst.topOfScript(117,3099 function Tst.validName(121,3167 function Tst.setup_outputDir(130,3452 function Tst.expandRunScript(148,4208 function Tst.testfields(191,5190 function Tst.testresultValues(202,5552 function Tst.get(210,5715 function Tst.set(218,5867 function Tst.hasAnyKeywords(226,6039 function Tst.hasAllKeywords(238,6265 WriteTests.lua,35 function WriteTests:execute(6,131 common.lua,92 function countEntries(7,101 function buildTestReportTable(16,222 function fullFn(51,1294 task.lua,24 function :execute(5,73 version.lua,0 BatchSystemDefault.lua,0 BatchSystem.lua,0 Hermes-0.0.20180315/tm/Tst.lua000066400000000000000000000145101325256533400154040ustar00rootroot00000000000000require("strict") require("fileOps") require("string_utils") local Stencil = require("Stencil") Tst = {} function buildTstTbl(fileName, testdescript, target, epoch, ntimes) local tstTbl = {} Tst:initFmt(ntimes) for _,v in ipairs(testdescript.tests) do for i = 1, ntimes do local tst = Tst:new(v, fileName, testdescript, target, epoch, i) local id = tst:get('id') tstTbl[id] = tst end end return tstTbl end function Tst:initFmt(ntimes) local fmt = nil if (ntimes > 1) then local numplaces = math.floor(math.log10(ntimes)) + 1 fmt = "_%0" .. tostring(numplaces) .. "d" end self.fmt = fmt end function Tst.new(self, testparams, fileName, testdescript, target, epoch, i) local o = {} setmetatable(o,self) self.__index = self local masterTbl = masterTbl() masterTbl.date = os.date("%c", math.floor(masterTbl.currentEpoch)) local projectDir = masterTbl.projectDir local pattern = projectDir:gsub("%-","%%-") pattern = pattern:gsub("%.","%%.") pattern = "^".. pattern .. "/" .. "(.*)%.tdesc$" local _, _, baseId = fileName:find(pattern ) local _, _, tstDir = baseId:find("^(.*)/") if (tstDir == nil) then tstDir = "./" end local extra = '' if (self.fmt) then extra = string.format(self.fmt,i) end local id = testparams.id .. extra o:validName("id", id) o:validName("testName", testdescript.testName) o.testdescript = testdescript o.test = testparams o.id = pathJoin(baseId, id) o.idTag = id o.start_epoch = -1 o.runtime = -1 o.job_submit_method = o.testdescript.job_submit_method or false o.strRuntime = "***" o.result = 'notrun' o.active = 1 o.epoch = epoch o.report = false o.testDir = tstDir o.testdescriptFn = baseId .. ".tdesc" o.testName = o.testdescript.testName o.packageName = masterTbl.packageName o.packageDir = masterTbl.packageDir o.tag = masterTbl.tag o.parentDir = pathJoin(o.testDir,o.idTag) o.ProgVersion = '' o.message = '' o.osName = '' o.machName = '' o.hostName = '' o.os_mach = '' o.runInBackground = false o.target = target o.TARGET = target o.start_time = 0 o.end_time = 0 o.background = testdescript.background or false o.at_top_of_script = testdescript.topOfScript or [[#!/bin/bash # -*- shell-script -*- ]] o:setup_outputDir(epoch,target) if (o.testdescript.active ~= nil) then o.active = o.testdescript.active if (o.active == 0) then o.active = false end end o.keywords = {} for _,key in ipairs(o.testdescript.keywords) do o.keywords[key] = 1 end o.np = 1 if (o.test.np) then o.np = o.test.np end return o end function Tst.topOfScript(self) return self.at_top_of_script end function Tst.validName(self, stringName, name) local i, j = name:find('[ ?/*"\']') if (i) then Error(stringName,": \"",name,"\" has an illegal character: '",name:sub(i,j),"'", "\nIllegal characters are: \" ?/*\" and the quote characters: ' and '\"'") end end function Tst.setup_outputDir(self,epoch, target) local masterTbl = masterTbl() local prefix = '' if (target and target:len() > 0) then prefix = target .. "-" end local UUid = prefix .. UUIDString(epoch) .. "-" .. masterTbl.os_mach self.UUid = UUid self.outputDir = pathJoin(self.parentDir,UUid .. '-' .. self.testName) self.resultFn = pathJoin(self.outputDir,self.idTag .. ".result") self.runtimeFn = pathJoin(self.outputDir,self.idTag .. ".runtime") self.cmdResultFn = pathJoin(self.outputDir, "results.lua") self.versionFn = pathJoin(self.outputDir, "version.lua") self.messageFn = pathJoin(self.outputDir, "message.lua") end function Tst.expandRunScript(self, envTbl, funcTbl) local stencil = Stencil:new{tbl=self.test, envTbl=envTbl, funcTbl=funcTbl} local runScript = stencil:expand(self.testdescript.runScript) runScript = runScript:gsub("^%s+#","#") runScript = runScript:gsub("\n%s+#","\n#") local aa = {} for k in pairs(envTbl) do aa[#aa + 1] = k .. "=\"" .. envTbl[k] .. "\"; export "..k end local mark = 0 local icount = 0 local a = {} local aaa = {} for line in runScript:split("\n") do icount = icount + 1 if (not line:find("^#") and mark == 0) then mark = icount end if (mark == 0) then a[#a+1] = line else aaa[#aaa+1] = line end end local t = {} for _,v in ipairs(a) do t[#t+1] = v end for _,v in ipairs(aa) do t[#t+1] = v end for _,v in ipairs(aaa) do t[#t+1] = v end runScript = table.concat(t,"\n") return runScript end function Tst.testfields(self) local tbl = { "id", "idTag", "start_epoch", "runtime", "result", "active", "report" , "strRuntime", "outputDir", "testName", "reason", "UUid", "resultFn", "runtimeFn", "cmdResultFn", "versionFn","osName","machName","hostName","target","ProgVersion","message","tag", "userActive", } return tbl end function Tst.testresultValues(self) local tbl = { notrun = 1, notfinished = 2, failed = 3, diff = 4 , passed = 5, inactive = 6, } return tbl end function Tst.get(self, key) local result = self[key] if (result == nil) then result = self.testdescript[key] end return result end function Tst.set(self, key, value) local result = self[key] if (result == nil) then Error('Tst.set: Unknown key: "'..key..'"') end self[key] = value end function Tst.hasAnyKeywords(self, keyInA) local keyTbl = self:get('keywords') local result = false for _,v in ipairs(keyInA) do if (keyTbl[v]) then result = true break end end return result end function Tst.hasAllKeywords(self, keyInA) local keyTbl = self:get('keywords') local result = true for _,v in ipairs(keyInA) do if (not keyTbl[v]) then result = false break end end return result end Hermes-0.0.20180315/tm/WriteTests.lua000066400000000000000000000010001325256533400167350ustar00rootroot00000000000000require("strict") WriteTests = BaseTask:new() require("fileOps") require("serializeTbl") function WriteTests:execute(myTable) local masterTbl = masterTbl() local testlistFn = pathJoin(masterTbl.projectDir, masterTbl.testlistFn) local testlist = {} local icount = 0 for id in pairs(masterTbl.tstTbl) do icount = icount + 1 table.insert(testlist, id) end print ("Found " .. icount .. " tests") serializeTbl{name="testlist", value=testlist, fn=testlistFn, indent=true} end Hermes-0.0.20180315/tm/batch_runtest.txt000066400000000000000000000011661325256533400175400ustar00rootroot00000000000000Batch Steps * build RunScript in string * Save Current Directory * cd to outputDir * Write initial resultFn and runtimeFn * Create scriptFn * Report scriptFn submitted no pass/fail count * The scriptFn must convert cmdResultFn and Generate resultFn and runtimeFn (Auto generated?) * Done ------------------------------------------------------------------------ Q: 1) Where do scripts run? If a runscript runs make should it work? 2) Is there any way to be signaled if a job times out? 3) Do I require that all test have alarms? 4) Can alarms be implemented in shell scripts? 5) Should runscript be in lua? Hermes-0.0.20180315/tm/common.lua000066400000000000000000000034101325256533400161170ustar00rootroot00000000000000require("strict") require("fileOps") function countEntries(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end function buildTestReportTable(HumanData, masterTbl) local testresults = { HumanData = HumanData, date = masterTbl.date, currentUUid = masterTbl.currentUUid, origUUid = masterTbl.origUUid, currentEpoch = masterTbl.currentEpoch, origEpoch = masterTbl.origEpoch, machType = masterTbl.os_mach, hostname = masterTbl.hostname, Targ = masterTbl.targ, target = masterTbl.target, TotalTestTime = masterTbl.totalTestTime, TM_Version = masterTbl.TM_Version, Hermes_Version = masterTbl.HermesVersion, tag = masterTbl.tag, ntimes = masterTbl.ntimes, Lua_Version = _G._VERSION, tests = {}, } local testfields = Tst:testfields() for id in pairs(masterTbl.rptTbl) do local tst = masterTbl.rptTbl[id] local testData = {} for i,v in ipairs(testfields) do testData[v] = tst:get(v) end table.insert(testresults.tests,testData) end return testresults end function fullFn(f) return fixFileName(pathJoin(masterTbl().projectDir, f)) end function UUIDString(epoch) local ymd = os.date("*t", math.floor(epoch)) -- y m d h m s local uuid = string.format("%d_%02d_%02d_%02d_%02d_%02d", ymd.year, ymd.month, ymd.day, ymd.hour, ymd.min, ymd.sec) return uuid end function ymdString(epoch) local ymd = os.date("*t", math.floor(epoch)) -- y m d return string.format("%d_%02d_%02d", ymd.year, ymd.month, ymd.day) end Hermes-0.0.20180315/tm/doc/000077500000000000000000000000001325256533400146735ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/.gitignore000066400000000000000000000000261325256533400166610ustar00rootroot00000000000000*.o diffprog testprog Hermes-0.0.20180315/tm/doc/Hermes.db000066400000000000000000000000001325256533400164130ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/Makefile000066400000000000000000000005341325256533400163350ustar00rootroot00000000000000CC := gcc CFLAGS := -g -O0 SRC := testprog.c diffprog.c OBJ := $(patsubst %.c, %.o, $(SRC)) EXEC := testprog diffprog all: $(EXEC) testprog : testprog.o $(LINK.c) -o $@ $< diffprog : diffprog.o $(LINK.c) -o $@ $< -lm neat: $(RM) *~ clean: neat $(RM) *.o clobber: clean $(RM) $(EXEC) testprog.o: testprog.c diffprog.o: diffprog.c Hermes-0.0.20180315/tm/doc/diffprog.c000066400000000000000000000052741325256533400166470ustar00rootroot00000000000000#include #include #include #include enum {false = 0, true}; typedef enum { iPASSED = 0, iDIFF = 1, iFAILED = 2 } Status; const char * STbl [] = { "passed", "diff", "failed" }; Status compare(char* argv[]); void write_results(Status s, const char * fn); /*====================================================================== * This is a simple compare program. It reads two files and report * whether the two file are close enough ======================================================================*/ int main(int argc, char* argv[]) { FILE* fp_results; Status status; if (argc < 5) { fprintf(stderr,"Usage: %s results.lua value gold test\n", argv[0]); return 1; } status = compare(argv); fp_results = fopen(argv[1],"w"); write_results(status, argv[1]); return status; } Status compare(char *argv[] ) { FILE* fp_gold; FILE* fp_test; Status status = iDIFF; int nx, ny, n, i; double x, y, eps; double sumDiff, diff, norm, diffMax, relDiff; int relFlag = false; int absFlag = false; /* Parse command line options for eps and file names*/ eps = strtod(argv[2],(char **) NULL); fp_gold = fopen(argv[3],"r"); /* Gold file */ fp_test = fopen(argv[4],"r"); /* Test file */ /* Report failure if either file does not exist. */ if (fp_gold == NULL || fp_test == NULL) return iFAILED; /* Read in size of vector */ fscanf(fp_test,"%d", &nx); fscanf(fp_gold,"%d", &ny); /* Quit if sizes do not match */ if (nx != ny) { return iDIFF; } /* Loop over values computing norm */ n = nx; norm = 0.0; sumDiff = 0.0; diffMax = 0.0; for (i = 1; i < n; ++i) { fscanf(fp_test, "%lf", &x); fscanf(fp_gold, "%lf", &y); diff = fabs(x - y); norm += y*y; sumDiff += diff*diff; if (diff > diffMax) diffMax = diff; } fclose(fp_test); fclose(fp_gold); sumDiff = sqrt(sumDiff); norm = sqrt(norm); /* Check to see if difference pass or not */ if (norm > 1.0e-20) { relDiff = sumDiff/ norm; if (relDiff < eps) relFlag = true; } if (sumDiff < eps) absFlag = true; if (relFlag || absFlag) status = iPASSED; /* Print results */ printf("Relative Norm\tAbsolute Norm\tMax Diff\n"); printf("%e\t%e\t%e\n",relDiff, sumDiff, diffMax); return status; } void write_results(Status s, const char * fn) { const int bufSize = 1024; char buf[bufSize]; time_t t; struct tm stm; FILE* fp = fopen(fn,"w"); t = time(NULL); strftime(buf, bufSize, "%c", localtime(&t)); fprintf(fp,"# %s\n%s\n", buf,STbl[s]); } Hermes-0.0.20180315/tm/doc/getting_started_with_tm.txt000066400000000000000000000473211325256533400223650ustar00rootroot00000000000000 TM - Testing Manager by Robert McLay ---------------------------------------------------------------------- Getting Started. ---------------------------------------------------------------------- This document describes how to get started with the TM testing manager. This document is split up into two parts. The first part describes how to install the lua scripting language and how to install the Hermes package of which "tm" is a part of. The second part explains how to use the tool by way of an example. What tm provides is a way to run tests and easily know what tests passed, failed or diffed. It is easy to run all tests, one test or select a subset of tests. Having an easy way to run tests means that refactoring is much easier. It also completely captures inputs and outputs and how to run your program. This is a convenient way to pass on knowledge of how your program works to others or yourself six months to a year later when you can't remember how things work. ---------------------------------------------------------------------- Installing Lua and TM. ---------------------------------------------------------------------- The Hermes package is a collection of tools. The main part is "tm" the testing manager and the rest of the tools necessary to run it. This package is written in the Lua programming language. Lua is a scripting language similar to Perl, Python and Ruby. Lua is designed to be a scripting language as well as library to be a configuration language to be embedded with other applications. See www.lua.org for more details. To use lua in this context we need some libraries that do not come from the standard distribution. $ wget http://downloads.sourceforge.net/project/lmod/lua-5.1.4.5.tar.gz Change to the lua directory and follow the INSTALL file directions. The hermes package is much simplier to install. Take the attached tar ball and untar it where you wish it installed: $ tar xzf hermes-x.y.z.tar.gz then add hermes-x.y.z/bin to your PATH environment variable, where x.y.z is the version number such as 1.9.1 ---------------------------------------------------------------------- General Principles for TM ---------------------------------------------------------------------- The idea behind tm is to provide a general testing manager that independent of the program(s) under test. There is a test description file (*.tdesc) that contains the information required to run each test. In that file there is a section which contains a (Bourne) shell script that runs your test. In order for "tm" to know if your test passed or not, your script will have to write to a particular file on how your test did. ---------------------------------------------------------------------- Example on how to use tm. ---------------------------------------------------------------------- Probably the best way to explain tm is by way of an example. In the hermes-x.y.z/tm/doc directory is where this example lives. So change your directory to there and lets start. $ cd hermes-x.y.z/tm/doc $ make The make command will build two programs: testprog and diffprog. The testprog program is there to represent a program under test and the diffprog is there as an example of a program to compute the difference between a "gold" solution file and a test one. The testprog.c file shows a very simple program that writes a file containing the numbers 0 to 99 with a little random noise added. The diffprog.c file takes two files and compares them. The diffprog takes several arguments: $ diffprog result.lua 1.0e-6 gold_file test_file The first argument is the name of the lua file that is required to tell tm how your program did. The second argument is the norm test value. The final two arguments are the gold file that has the known good solution and test file. The results.lua file looks something like this: -- -*- lua -*- -- Fri Feb 19 16:39:18 2015 myTbl = { { ["result"] = "passed", }, } This is actually a simple lua program. In lua lines that have two minus signs in a row are a comment so the first two line are comment lines and are not required. Your diff program should generate something similar. It is important that you have all the commas that are shown above. Obviously, the "passed" line should be either "passed", "failed" or "diff" depending on how your program did. ---------------------------------------------------------------------- Test Directory Structure ---------------------------------------------------------------------- The test directory structure can be quite flexible. I usually create a directory named "rt" for regression tests and place the tests under "rt". I place each test in a separate directory although that is not required. The test directories can nested. This way similar tests can be grouped together. Generally, I recommend that tests live in leaf and not branch directories. As an example, the test directory structure given here is: .: Hermes.db diffprog.c rt/ Makefile getting_started_with_tm.txt testprog.c ./rt: diff_test/ fail_test/ simple_test/ multiple_tests/ ./rt/diff_test: diff_test.tdesc testprog.gold ./rt/fail_test: fail_test.tdesc testprog.gold ./rt/simple_test: simple_test.tdesc testprog.gold ./rt/multiple_tests: multiple_tests.tdesc testprog.gold In the top level directory we have the Makefile and the two .c programs along with the rt directory. There is also a file called "Hermes.db" which is necessary for tm to work. You need to create a zero length file with that name above the directory that contains the tests. ---------------------------------------------------------------------- Test Description file (*.tdesc) ---------------------------------------------------------------------- So here we have four test directories underneath the rt directory, each with a test description file (*.tdesc) and a gold results file (testprog.gold). Each of the .tdesc files are similar so lets look at the simple_test.tdesc file in detail. -- -*- lua -*- testdescript = { -- An optional description description = [[ A long description over many lines ]], -- An optional list of key words keywords = { "simple", "other", "key", "words"}, -- Mark the test as active. active = 1, -- The test name (required) testName = "simple_test", -- The script to run the test case runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog $(cmdResultFn) $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -c $(cmdResultFn) -r $(resultFn) -t $(runtimeFn) ]], -- The list of tests to run tests = { { id='t1', tol = 1.01e-6, }, }, } The .tdesc file is a valid lua program. Here we are setting key value pairs that describe the test for the table "testdescript". As you can see there are several keyword that are specified so that tm can run the test. In lua upper and lower case variables are distinct, so your test files need to match the case and spelling used here. The file shown here has some required and optional key and values. Below is a table describing each: Key Required Description ------------------------------------------------------------------------ description no An optional place to descibe the test. keywords no A list keywords so that a test can be selected. active yes Tells if test is active. Set value to "false" (w/o quotes) to mark as inactive. testname yes A unique test name. runScript yes A parameterized shell script for running the test. tests yes An array of 1 or more tests. Each array entry must set the "id" key. ------------------------------------------------------------------------ How individual tests are run ------------------------------------------------------------------------ Later I'll describe the complete features on how to run tm with all its power. For the moment lets see how a single test is run. By changing your directory to "simple_test" we can run that individual test: $ tm . The period says run tm by looking for all the test descriptions files from the current directory on down. In this case there is only the simple_test.tdesc file. The output will look like this: TM Version: 1.5 Starting Tests: Started : 10:16:49 tst: 1/1 P/F: 0:0, rt/simple_test/simple_test/t1 passed : 10:16:49 tst: 1/1 P/F: 1:0, rt/simple_test/simple_test/t1 Finished Tests ************************************************************************ *** Test Results *** ************************************************************************ Date: Mon Feb 22 10:16:49 2010 Tag: 2010_02_22 TM Version: 1.5 Hermes Version: 1.9.1 Lua Version: Lua 5.1 Total Test Time: 00:00:00.09 ************************************************************************ *** Test Summary *** ************************************************************************ Total: 1 passed: 1 ******* * **** ***************** ********************* Results R Time Test Name version/message ******* * **** ***************** ********************* passed R 0.0881 rt/simple_test/simple_test/t1 The output is has two parts. The first part is from the "Starting Tests" to "Finished Tests". For each test it reports the start and end times, a record of the current number of pass/failed test and the test name. The test name looks like a path but it is not. It is the relative path name from the directory that contains the "Hermes.db" directory. So that is the "rt/simple_test". It is followed by the name of the test file base name (simple_test from simple_test.tdesc) and the id tag, in this case "t1". The result is "rt/simple_test/simple_test/t1" The second part is the report of results. There is header information about the time the test was run and version information. Finally there is a report of the individual tests. If any tests fail/diff then a list of them is given. I'll show that later. The way the an individual *.tdesc file is run is as follows. The id value is used to name the test. If there are any other keyword listed on the entry then they are added to the list of parameters that are used in the substitution process (i.e. tol = 1.01e-6). The lines given for the runScript keyword are used to build the actual script used. Actual step to run an individual *.tdesc file is as follows: 1) The id value is used to name the test. 2) The output directory for running the test is created as a subdirectory to the tdesc file. Its name is $id/$date_name where $id is the id value and $date_name is the date_os_arch_testName: (e.g. "t1/2010_02_22_14_58_04-Linux-x86_64-simple_test") 3) The runScript value is converted to an actual shell script with the parameter substituted. A table below gives the list of predefined names. 4) The generated script is run in the output directory. 5) The output directory is checked for a the result file and the runtime file to report the status of the test. There is a list of predefined parameters that are used in the expansion of the runScript value into the script: Key Value ----------- ---------- cmdResultFn The absolute path to the "results.lua" file idTag The id value messageFn The absolute path to the "message.lua" file outputDir The absolute path to the output directory projectDir The absolute path to the directory that has Hermes.db in it. resultFn The absolute path to the results file ($id.results) runtimeFn The absolute path to the runtime file ($id.runtime) testDir The absolute path to the directory that has the *.tdesc file in it. testName The testName value given in the .tdesc file. testdescriptFn the absolute path to the .tdesc file. ---------------------------------------------------------------------- Comments on runScript ---------------------------------------------------------------------- The runScript value is repeated here: runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog $(cmdResultFn) $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -c $(cmdResultFn) -r $(resultFn) -t $(runtimeFn) ]], The script given here should now be clear what is happening. Line 1 adds the project directory which has the testprog and diffprog programs. Line 2 runs the test program (testprog). Line 3 runs the "diffprog" to compare the results from "testprog" with the gold file in the $(testDir). Line 4 is important for tm to know what happens. The testFinish program converts the $(cmdResults) file, into the results file that tm needs. All of your runScripts MUST end with that program, otherwise tm will assume that the test program was not run. ------------------------------------------------------------------------ Running more than one test at a time. ------------------------------------------------------------------------ So running "tm ." in the simple_test directory ran one test. If we change our directory up one to the rt directory we can run all the tests by: $ tm . You should see output similar to this: TM Version: 1.5 Starting Tests: Started : 16:23:08 tst: 1/5 P/F: 0:0, rt/multiple_tests/multiple_tests/t2 diff : 16:23:08 tst: 1/5 P/F: 0:1, rt/multiple_tests/multiple_tests/t2 Started : 16:23:08 tst: 2/5 P/F: 0:1, rt/fail_test/fail_test/t1 failed : 16:23:08 tst: 2/5 P/F: 0:2, rt/fail_test/fail_test/t1 Started : 16:23:08 tst: 3/5 P/F: 0:2, rt/diff_test/diff_test/t1 diff : 16:23:08 tst: 3/5 P/F: 0:3, rt/diff_test/diff_test/t1 Started : 16:23:08 tst: 4/5 P/F: 0:3, rt/simple_test/simple_test/t1 passed : 16:23:08 tst: 4/5 P/F: 1:3, rt/simple_test/simple_test/t1 Started : 16:23:08 tst: 5/5 P/F: 1:3, rt/multiple_tests/multiple_tests/t1 passed : 16:23:08 tst: 5/5 P/F: 2:3, rt/multiple_tests/multiple_tests/t1 Finished Tests ************************************************************************ *** Test Results *** ************************************************************************ Date: Mon Feb 22 16:23:08 2010 TARGET: x86_64_dbg_intel_openmpi Tag: 2010_02_22 TM Version: 1.5 Hermes Version: 1.9.1 Lua Version: Lua 5.1 Total Test Time: 00:00:00.23 ************************************************************************ *** Test Summary *** ************************************************************************ Total: 5 diff: 2 failed: 1 passed: 2 ******* * **** ***************** *********************************** Results R Time Test Name version/message ******* * **** ***************** *********************************** passed R 0.0306 rt/multiple_tests/multiple_tests/t1 passed R 0.0307 rt/simple_test/simple_test/t1 failed R 0.0347 rt/fail_test/fail_test/t1 diff R 0.0959 rt/diff_test/diff_test/t1 diff R 0.0386 rt/multiple_tests/multiple_tests/t2 ******* *********************************************************** Results Output Directory ******* *********************************************************** diff /home/mclay/w/hermes/tm/doc/rt/diff_test/t1/x86_64_dbg_intel_openmpi-2010_02_22_16_23_08-Linux-x86_64-diff_test diff /home/mclay/w/hermes/tm/doc/rt/multiple_tests/t2/x86_64_dbg_intel_openmpi-2010_02_22_16_23_08-Linux-x86_64-multiple_tests failed /home/mclay/w/hermes/tm/doc/rt/fail_test/t1/x86_64_dbg_intel_openmpi-2010_02_22_16_23_08-Linux-x86_64-fail_test We see that two of the five tests passed. We see that one test failed and two tests diffed. Let's look at the three problem children. The diff test has a very similar .tdesc file but if we look at the at the testprog.gold file we see that the first value that should be a 0 has been changed to 123. This is a large difference between the "gold" and the "test" values so it "diff'ed". The fail_test.tdesc shows that I've removed the output file from "testprog" so the "diffprog" program states that the test failed: runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln rm $(outputDir)/testprog.soln diffprog $(cmdResultFn) 1.e-6 $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -c $(cmdResultFn) -r $(resultFn) -t $(runtimeFn) ]], Finally the multiple_tests programs shows that the "t1" test passed and the "t2" test failed. We can see why by looking at the runScript and tests parts: runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog $(cmdResultFn) $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -c $(cmdResultFn) -r $(resultFn) -t $(runtimeFn) ]], tests = { { id='t1', tol=1.01e-6}, { id='t2', tol=1.01e-12}, }, So the "t1" test has a resonable tolerance of 1.01e-6 where as the "t2" test has an impossible tolerance of 1.01e-12 so that test fails. ------------------------------------------------------------------------ Cleanup ------------------------------------------------------------------------ One you have run test you'll wish to cleanup the results. In order to make that simple you can run the command: $ testcleanup and it will remove all the generated files and directories. ------------------------------------------------------------------------ Advance Features: Restarting, Keywords ------------------------------------------------------------------------ If you find that there are "diff's" and "failed" tests you can rerun only these tests. You can run $ tm -r wrong to get both the failed and diff'ed tests. You can run only test that have a certain keyword given so: $ tm -k multiple . will run the multiple_tests.tdesc file (assuming that you are in the "rt" directory), because only multiple_tests.tdesc file has the multiple keyword defined. Where as: $ tm -k single . will run simple_test.tdesc, diff_test.tdesc and fail_test.tdesc files because each have the "single" keyword defined. Note that the keywords are case sensitive so "Single" and "single" and "SINGLE" are different keys. ---------------------------------------------------------------------- Conclusions ---------------------------------------------------------------------- This discussion covers the basic uses of "tm". If you have questions then please send them to mclay@tacc.utexas.edu. Hermes-0.0.20180315/tm/doc/rt/000077500000000000000000000000001325256533400153205ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/rt/diff_test/000077500000000000000000000000001325256533400172675ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/rt/diff_test/diff_test.tdesc000066400000000000000000000007711325256533400222670ustar00rootroot00000000000000-- -*- lua -*- testdescript = { description = [[ A long description over many lines ]], keywords = { "single", "other", "key", "words"}, active = 1, testName = "diff_test", runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog results.csv 1.e-6 $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -r $(resultFn) -t $(runtimeFn) results.csv ]], tests = { { id='t1'}, }, } Hermes-0.0.20180315/tm/doc/rt/diff_test/testprog.gold000066400000000000000000000044001325256533400220030ustar00rootroot00000000000000100 123 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Hermes-0.0.20180315/tm/doc/rt/fail_test/000077500000000000000000000000001325256533400172725ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/rt/fail_test/fail_test.tdesc000066400000000000000000000010321325256533400222640ustar00rootroot00000000000000-- -*- lua -*- testdescript = { description = [[ A long description over many lines ]], keywords = { "single", "other", "key", "words"}, active = 1, testName = "fail_test", runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln rm $(outputDir)/testprog.soln diffprog result.csv 1.e-6 $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -r $(resultFn) -t $(runtimeFn) result.csv ]], tests = { { id='t1'}, }, } Hermes-0.0.20180315/tm/doc/rt/fail_test/testprog.gold000066400000000000000000000044001325256533400220060ustar00rootroot00000000000000100 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Hermes-0.0.20180315/tm/doc/rt/multiple_tests/000077500000000000000000000000001325256533400203755ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/rt/multiple_tests/multiple_tests.tdesc000066400000000000000000000012001325256533400244670ustar00rootroot00000000000000-- -*- lua -*- testdescript = { description = [[ A long description over many lines ]], keywords = { "multiple", "other", "key", "words"}, active = 1, testName = "multiple_tests", runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog r1.csv $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln diffprog r2.csv $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -r $(resultFn) -t $(runtimeFn) r1.csv r2.csv ]], tests = { { id='t1', tol=1.01e-6}, { id='t2', tol=1.01e-12}, }, } Hermes-0.0.20180315/tm/doc/rt/multiple_tests/testprog.gold000066400000000000000000000044001325256533400231110ustar00rootroot00000000000000100 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Hermes-0.0.20180315/tm/doc/rt/queue_test/000077500000000000000000000000001325256533400175035ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/rt/queue_test/qtest.tdesc000066400000000000000000000011541325256533400216700ustar00rootroot00000000000000-- -*- lua -*- testdescript = { description = [[ A long description over many lines ]], keywords = { "queue", "qtest"}, active = true, testName = "simple_test", runScript = [[ $(submit JOBNAME="$(testName)-$(id)", NP=$(np), NODES=$(nodes), QUEUE="normal", TIME=00:15:00) PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog result.csv $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -r $(resultFn) -t $(runtimeFn) result.csv ]], tests = { { id='t1', tol=1.01e-6, np=1, nodes=1}, }, } Hermes-0.0.20180315/tm/doc/rt/queue_test/testprog.gold000066400000000000000000000044001325256533400222170ustar00rootroot00000000000000100 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Hermes-0.0.20180315/tm/doc/rt/simple_test/000077500000000000000000000000001325256533400176505ustar00rootroot00000000000000Hermes-0.0.20180315/tm/doc/rt/simple_test/simple_test.tdesc000066400000000000000000000010071325256533400232220ustar00rootroot00000000000000-- -*- lua -*- testdescript = { description = [[ A long description over many lines ]], keywords = { "single", "other", "key", "words"}, active = 1, testName = "simple_test", runScript = [[ PATH=$(projectDir):$PATH; export PATH testprog $(outputDir)/testprog.soln diffprog result.csv $(tol) $(testDir)/testprog.gold $(outputDir)/testprog.soln testFinish -r $(resultFn) -t $(runtimeFn) result.csv ]], tests = { { id='t1', tol=1.01e-6}, }, } Hermes-0.0.20180315/tm/doc/rt/simple_test/testprog.gold000066400000000000000000000044001325256533400223640ustar00rootroot00000000000000100 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Hermes-0.0.20180315/tm/doc/testprog.c000066400000000000000000000006461325256533400167140ustar00rootroot00000000000000#include #include #define SZ 100 int main(int argc, char* argv[]) { FILE* fp; int i; double x; if (argc < 2) { fprintf(stderr,"Usage %s file.name\n",argv[0]); return 1; } fp = fopen(argv[1], "w"); fprintf(fp,"%d\n",SZ); for (i = 0; i < SZ; ++i) { x = ((double) i) + 1.e-8*drand48(); fprintf(fp,"%22.15g\n", x); } fclose(fp); return 0; } Hermes-0.0.20180315/tm/interactive_runtest.txt000066400000000000000000000005031325256533400207660ustar00rootroot00000000000000Interactive Steps * build Run Script in string * Save Current Directory * cd to outputDir * Write initial resultFn and runtimeFn * Create scriptFn * Report Script started and Pass/Fail count * submit script * Read cmdResultFn => Generate resultFn * Update runtimeFn * Report Script Finish and Pass/Fail count Hermes-0.0.20180315/tm/task.lua000066400000000000000000000001271325256533400155730ustar00rootroot00000000000000 = BaseTask:new() function :execute(myTable) local masterTbl = masterTbl() end Hermes-0.0.20180315/tm/tm.tasks000066400000000000000000000037301325256533400156200ustar00rootroot00000000000000-- -*- lua -*- require("strict") require("build_epoch") function taskMain() build_epoch() task{"CmdLineOptions"} task{"ReadProject"} -- Project file shows top of dir tree task{"Initialize"} task{"FindTests", spanning=true} -- Get all tests task{"BuildMasterTbl"} -- initialize tagTbl and targetTbl print("TM Version: "..Version) local masterTbl = masterTbl() for tag in pairs(masterTbl.tagTbl) do for target in pairs(masterTbl.tagTbl[tag].targetTbl) do task{"SpecializeMasterTbl", target=target,tag=tag} task{"FindTests",spanning=false} -- Get all tests for given tag, target task{"SelectTests"} -- Run the gauntlet (create rptTbl, tstTbl) if (masterTbl.generate) then task{"WriteTests"} -- Create "my.tests" return 0 end task{"CreateTestReport",target=target} -- Create initial report end end task{"ResetMasterTbl"} task{"RunActiveTests"} -- Run all active tests (if any) if (masterTbl.rptTests == 0) then print("\n*** No tests found! ***\n") return -1 end for tag in pairs(masterTbl.tagTbl) do for target in pairs(masterTbl.tagTbl[tag].targetTbl) do local mTbl = masterTbl.tagTbl[tag].targetTbl[target] task{"AnalyzeTests", masterTbl=mTbl} -- Review rptTbl task{"ReportResults", masterTbl=mTbl} -- Report result, human, voucher masterTbl.errors = masterTbl.errors + mTbl.errors masterTbl.diffCnt = masterTbl.diffCnt + mTbl.diffCnt masterTbl.failCnt = masterTbl.failCnt + mTbl.failCnt end end for tag in pairs(masterTbl.tagTbl) do task{"ReportSpanResults",tag=tag} -- Report result, human, voucher end task{"ReportAllResults"} -- Report human local rtn = 0 if (masterTbl.diffCnt > 0) then rtn = rtn + 2 end if (masterTbl.failCnt > 0) then rtn = rtn + 4 end return rtn end Hermes-0.0.20180315/tm/version.lua000066400000000000000000000000201325256533400163060ustar00rootroot00000000000000Version = "1.7" Hermes-0.0.20180315/tools/000077500000000000000000000000001325256533400146465ustar00rootroot00000000000000Hermes-0.0.20180315/tools/BeautifulTbl.lua000066400000000000000000000222251325256533400177360ustar00rootroot00000000000000-------------------------------------------------------------------------- -- This class is responsible for taking column data and produce left or -- right justified columns. The interface is: -- -- local bt = BeautifulTbl:new{tbl = a, -- column = TermWidth() - 1, -- wrap = true, -- justify = "LRR", -- length = } -- -- io.stderr:write(bt:build_tbl()) -- -- Basic architecture of this class is: -- -- 1. The new member function computes the maximum size of every column -- in the input table. It sets up the justifyT table. Finally the -- input table is copied over to an interal table (self.tbl) and -- the correct left or right justification is added to the table. -- 2. The build_tbl() member function produces an output string of the -- complete table. -- 3. If wrap is true then it checks to see if the table will fit the -- available space (specified by the variable "column"). If it does -- then the table is declared to be "simple" and the table is written -- to the string. -- 4. If the table is too big (and wrap is true) then the last column -- is word wrapped. -- -- Here are ways this class can be used: -- -- 1. Present a column of words and numbers. Here you might want to -- left justify the columns with words and right justify the column -- of numbers -- 2. Use the wrap=true option to word wrap the last column (note that -- the last column will be left justified no matter what justifyT says). -- 3. The Help message for Lmod shows one other feature. For a particular -- row, if there is only one column in a multi-column table, that 1st -- column is not used to count the maximum size of the column. In -- other words, these one column entries are allowed to span more than -- one column. Execute "module help" to see its effect. -- -- @classmod BeautifulTbl require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- require("string_utils") local dbg = require("Dbg"):dbg() local concatTbl = table.concat local max = math.max local min = math.min local strlen = string.len local stdout = io.stdout local M = { gap = 2} local blank = ' ' -------------------------------------------------------------------------- -- Ctor for this class. This member function calls M.\_build\_tbl -- to do the heavy lifting. -- @param self BeautifulTbl object. -- @param t Input Table. function M.new(self, t) local tbl = t local o = {} if (t.tbl) then tbl = t.tbl o = t end setmetatable(o, self) self.__index = self o.length = o.len or strlen o.justify = t.justify or concatTbl(t.justifyT or {}, "") o.tbl = o:_build_tbl(tbl) o.column = o.column or 0 o.wrapped = o.wrapped or false return o end -------------------------------------------------------------------------- -- This is a private member function that client codes should not use. -- It figures out the max size of each column. Then adds spaces to -- make each column be justified. By default all columns are -- left-justified. To get write right-justified, the client code must -- pass a "justifyT" array to specify. -- -- Each entry in the table is copied to an internal table and left or -- right justified (depending on justifyT). -- @param self BeautifulTbl object -- @param tblIn Input Table from new ctor. -- @return formatted table. function M._build_tbl(self, tblIn) local length = self.length local columnCnt = {} local tbl = {} local justifyT = {} -- find max column size. Ignore one column rows. for irow = 1, #tblIn do local a = tblIn[irow] local numC = #a for icol = 1, numC do local v = a[icol] if (numC > 1) then columnCnt[icol] = max(length(v), columnCnt[icol] or 0) end end end -- Build justifyT local maxnc = #columnCnt self.maxnc = maxnc local justify = self.justify justify = justify .. string.rep("l", maxnc - length(justify)) justify = justify:lower() for icol = 1, maxnc do justifyT[icol] = (justify:sub(icol,icol) == "r") and "r" or "l" end self.justifyT = justifyT -- Left or right justify every entry in tbl, except for -- single column rows. local gap = self.gap for irow = 1, #tblIn do local a = tblIn[irow] local numC = #a local b = {} for icol = 1, #a do local v = tostring(a[icol]) if (numC == 1) then b[icol] = v else local nspaces = columnCnt[icol] - length(v) if (justifyT[icol] == "l") then b[icol] = v .. blank:rep(nspaces+gap) else b[icol] = blank:rep(nspaces) .. v .. blank:rep(gap) end end tbl[irow] = b end end self.columnCnt = columnCnt return tbl end -------------------------------------------------------------------------- -- Build "Beautiful Table" from internal table. -- @param self BeautifulTbl object function M.build_tbl(self) local length = self.length local justifyT = self.justifyT local width = 0 local colgap = self.gap local simple = true if (self.wrapped and self.column > 0) then for i = 1, #self.columnCnt-1 do width = width + self.columnCnt[i] + colgap end local last = self.columnCnt[#self.columnCnt] simple = (width > self.column-20) or (width + last < self.column) end local a = {} local tt = self.tbl if (next(tt) == nil) then return nil end -- If the table fits, then remove any trailing spaces in last -- column and build string of table. if (simple) then for j = 1,#tt do local t = tt[j] t[#t] = t[#t]:gsub("%s+$","") a[j] = concatTbl(t,"") end return concatTbl(a,"\n") end -- If here then the last column must be wrapped. It removes any -- trailing spaces. Note that the last column is the only column -- that is word wrapped. Any short rows are copied straight -- across. local column = self.column - 1 local gap = column - width local fill = string.rep(" ",width) local line = "" -- printing a wrapped last column local maxnc = self.maxnc local maxnc1 = maxnc - 1 for irow = 1, #tt do local aa = {} local t = tt[irow] local nc = #t local nc1 = min(nc, maxnc1) -- For the current row copy every column but last. for i = 1, nc1 do aa[#aa+1] = t[i] end -- Now word wrap last column. local aaa = {} if (nc == maxnc) then local icnt = width local s = t[#t] or "" for word in s:split("%s+") do local wlen = length(word)+1 if (word == "") then wlen = 0 elseif (icnt + wlen < column or wlen > gap) then aaa[#aaa+1] = word .. " " else aaa[#aaa] = aaa[#aaa]:gsub("%s+$","") line = concatTbl(aaa,"") if (justifyT[#justifyT] == "r") then aa[#aa+1] = string.rep(" ",gap - length(line)) end aa[#aa+1] = line aa[#aa+1] = "\n" a[#a + 1] = concatTbl(aa,"") aa = {} aaa = {} aa[1] = fill aaa[1] = word .. " " icnt = width end icnt = icnt + wlen end end aaa[#aaa] = (aaa[#aaa] or ""):gsub("%s+$","") line = concatTbl(aaa,"") if (justifyT[#justifyT] == "r") then aa[#aa+1] = string.rep(" ",gap - length(line)) end aa[#aa+1] = line aa[#aa+1] = "\n" a[#a + 1] = concatTbl(aa,"") end return concatTbl(a,"") end ---- finis ----- return M Hermes-0.0.20180315/tools/Dbg.lua000066400000000000000000000255101325256533400160500ustar00rootroot00000000000000------------------------------------------------------------------------- -- This is a debug printing class. The point is to add these debug print -- statement permanently and use command line options to turn these print -- stmts on when necessary. -- -- Test code for using Dbg.lua -- require("strict") -- local dbg = require("Dbg"):dbg() -- function a() -- dbg.start{2,"a"} -- dbg.print{"In a","\n"} -- b() -- dbg.fini() -- end -- -- function b() -- dbg.start{2,"b"} -- dbg.print{"In b","\n"} -- c() -- dbg.fini() -- end -- -- function c() -- dbg.start{3,"c"} -- dbg.print{1,"In c","\n"} -- dbg.fini() -- end -- -- function main() -- local level = 10 -- dbg:activateDebug(level) -- -- dbg.start{2,"main"} -- a() -- dbg.fini() -- end -- -- main() -- -- @classmod Dbg require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- local blank = " " local huge = math.huge local max = math.max local remove = table.remove local M = {} s_dbg = nil s_warningCalled = false s_indentString = "" s_indentLevel = 0 s_vpl = 1 s_currentLevel = huge s_levelA = {} s_isActive = false s_prefix = "" local function prtTbl(a) io.stderr:write("table:\n") for _,v in ipairs(a) do if (type(a) == "table") then prtTbl(v) else io.stderr:write(v) end end end local function argsPack(...) local arg = { n = select ("#", ...), ...} return arg end local pack = (_VERSION == "Lua 5.1") and argsPack or table.pack local function changeIndentLevel(i) s_indentLevel = s_indentLevel + i s_indentString = blank:rep(s_indentLevel*2) end local function new(self) local o = {} setmetatable(o,self) self.__index = self o.print = M._quiet o.printA = M._quiet o.textA = M._quiet o.start = M._quiet o.fini = M._quiet o.warning = M._warning o.error = M._error o.quiet = M._quiet o.indent = M._zeroIndent o.is_active = false return o end -------------------------------------------------------------------------- -- Singleton ctor for class -- @param self Dbg object. function M.dbg(self) if (s_dbg == nil) then s_dbg = new(self) end return s_dbg end -------------------------------------------------------------------------- -- Add a name (e.g. a program name) to the warning and error routines. -- This is a class static function. -- @param prefix the input name to prefix the error or warning message. function M.set_prefix(prefix) s_prefix = prefix .. " " end -------------------------------------------------------------------------- -- Activate debug print statements. -- @param self Dbg object. -- @param[opt] level A zero means printing start and end of routines w/o prints -- A one or greater include printing. -- @param[opt] indentLevel indent level. Mainly used when passing indent level -- to a subprogram. function M.activateDebug(self, level, indentLevel) level = tonumber(level) or 1 if (level == 0) then self.start = M._start self.fini = M._fini elseif (level > 0) then self.print = M._print self.printA = M._printA self.textA = M._textA self.start = M._start self.fini = M._fini self.indent = M._indent s_isActive = true s_currentLevel = level s_levelA[#s_levelA+1] = level s_indentLevel = tonumber(indentLevel) or s_indentLevel if (s_indentLevel > 0) then s_indentString = blank:rep(s_indentLevel*2) end else self.print = M._quiet self.printA = M._quiet self.textA = M._quiet self.start = M._quiet self.fini = M._quiet self.warning = M._warning self.error = M._error self.quiet = M._quiet self.indent = M._zeroIndent self.is_active = false end end -------------------------------------------------------------------------- -- Returns indent level function M.indentLevel() return s_indentLevel end -------------------------------------------------------------------------- -- Returns is active flag function M.active() return s_isActive end -------------------------------------------------------------------------- -- Returns current level function M.currentLevel(level) s_currentLevel = level or 1 end -------------------------------------------------------------------------- -- Deactivate Warings function M.deactivateWarning(self) self.warning = M._quiet end -------------------------------------------------------------------------- -- Activate Warings function M.activateWarning(self) self.warning = M._warning end -------------------------------------------------------------------------- -- Quiet function function M._quiet() end -------------------------------------------------------------------------- -- extract the verbosity level local function extractVPL(t) local vpl = t.level or s_vpl return vpl end local function startExtractVPL(t) local vpl = t.level or s_vpl s_levelA[#s_levelA+1] = vpl return vpl end -------------------------------------------------------------------------- -- Start of a routine function M._start(t) s_vpl = startExtractVPL(t) if (s_vpl > s_currentLevel) then return end io.stderr:write(s_indentString) for i = 1, #t do io.stderr:write(tostring(t[i])) end io.stderr:write("{\n") changeIndentLevel(1) end -------------------------------------------------------------------------- -- Zero indent. function M._zeroIndent() return "" end -------------------------------------------------------------------------- -- Return the current indent string. function M._indent() return blank:rep(s_indentLevel*2) end -------------------------------------------------------------------------- -- End of a routine function M._fini(s) local vpl = s_vpl if (vpl <= s_currentLevel) then s_indentLevel = max(0, s_indentLevel - 1) s_indentString = blank:rep(s_indentLevel*2) if (s) then io.stderr:write(s_indentString,"} ",s,"\n") else io.stderr:write(s_indentString,"}\n") end end if (#s_levelA > 1) then remove(s_levelA) -- remove last entry in table end s_vpl = s_levelA[#s_levelA] end -------------------------------------------------------------------------- -- Print a warning message and mark class static variable to remember that -- a warning was called. function M._warning(...) io.stderr:write("\n",s_prefix,"Warning: ") local arg = pack(...) for i = 1, arg.n do io.stderr:write(arg[i]) end s_warningCalled = true end -------------------------------------------------------------------------- -- Print error message and quit. function M._error(...) io.stderr:write("\n",s_prefix,"Error: ") local arg = pack(...) for i = 1, arg.n do io.stderr:write(arg[i]) end io.stderr:write("\n") errorExit() end -------------------------------------------------------------------------- -- Error exit function M.errorExit() io.stdout:write("false\n") os.exit(1) end -------------------------------------------------------------------------- -- Report true if a warning was called. function M.warningCalled() return s_warningCalled end ------------------------------------------------------------------------ -- The debug print statement -- @param t input table. function M._print(t) local vpl = extractVPL(t) if (vpl > s_currentLevel) then return end io.stderr:write(s_indentString) for i = 1, #t do local v = t[i] if (type(v) == "table") then prtTbl(v) else if (type(v) ~= "string") then v = tostring(v) elseif ( v == "") then v = "''" end local idx = v:find("\n") if (idx == nil or v:len() == idx) then io.stderr:write(v) else local s = v:sub(1,idx) io.stderr:write(s) M._print{v:sub(idx+1)} end end end end -------------------------------------------------------------------------- -- Write a indented text block. -- @param t input string table array. t.name is the string name t.a -- is the array of strings. function M._textA(t) local a = t.a io.stderr:write(s_indentString) if (#a == 0) then io.stderr:write(t.name,": (empty)\n") return else io.stderr:write(t.name,":\n") end changeIndentLevel(1) for i = 1, #a do io.stderr:write(s_indentString, a[i]) end changeIndentLevel(-1) end -------------------------------------------------------------------------- -- Print an array -- @param t input array. function M._printA(t) local a = t.a if (type(a[1]) == "table") then M._print2D(t) return end io.stderr:write(s_indentString) io.stderr:write(t.name) for i = 1,#a do io.stderr:write(" \"",a[i],"\"") end io.stderr:write("\n") end -------------------------------------------------------------------------- -- Print 2d array. -- @param t input 2-D array. function M._print2D(t) local name = t.name local A = t.a for j = 1,#A do io.stderr:write(s_indentString) io.stderr:write(name,"[",j,"]:") local a = A[j] for i = 1,#a do io.stderr:write(" ",a[i]) end io.stderr:write("\n") end end -------------------------------------------------------------------------- -- flush the output to stderr. function M.flush() io.stderr:flush() end ---- finis ----- return M Hermes-0.0.20180315/tools/Optiks.lua000066400000000000000000000360641325256533400166330ustar00rootroot00000000000000------------------------------------------------------------------------ -- Command line options parsing class -- @classmod Optiks require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- local function argsPack(...) local arg = { n = select ("#", ...), ...} return arg end local pack = (_VERSION == "Lua 5.1") and argsPack or table.pack -------------------------------------------------------------------------- -- Error routine for when option parsing fails function Optiks_Error(...) io.stderr:write("\n",ProgName,"Error: ") local arg = pack(...) for i = 1, arg.n do io.stderr:write(arg[i]) end io.stderr:write("\n") os.exit(1) end function Optiks_Exit(v) os.exit(v) end require("TermWidth") require("declare") local M = {} local BeautifulTbl = require("BeautifulTbl") local Error = Optiks_Error local Exit = Optiks_Exit local Option = require("Optiks_Option") local ProgName = "" local arg = arg local concatTbl = table.concat local io = io local ipairs = ipairs local os = os local pairs = pairs local print = print local require = require local require = require local setmetatable = setmetatable local systemG = _G local table = table local tonumber = tonumber local tostring = tostring local type = type local stdout = io.stdout local function Prt(...) stdout:write(...) end local function PrtEnd() end icnt = 0 -------------------------------------------------------------------------- -- Ctor for option parsing class. -- @param self Optiks object -- @param t input table function M.new(self, t) local o = {} setmetatable(o, self) self.__index = self self.argNames = {} self.optA = {} local envArg = nil local usage = t local version = nil if (type(t) == "table") then usage = t.usage ProgName = t.progName version = t.version envArg = t.envArg Error = t.error or Error Prt = t.prt or Prt PrtEnd = t.prtEnd or PrtEnd Exit = t.exit or Exit end if (not isDefined("ProgName") or not ProgName or ProgName == "") then declare("ProgName","") else ProgName = ProgName .. " " end o.exit = Exit o.prt = Prt o.prtEnd = PrtEnd o.usage = usage o.version = version o.envArg = envArg if (usage == nil) then local cmd = arg[0] local i,j = cmd:find(".*/") if (i) then cmd = cmd:sub(j+1) end o.usage = "Usage: " .. cmd .. " [options]" end o.dispTbl = { append = M.display_store, count = M.display_count, store = M.display_store, store_true = M.display_flag, store_false = M.display_flag, } return o end -------------------------------------------------------------------------- -- Add an option. -- @param self Optiks object -- @param myTable table of argument to construct option. function M.add_option(self, myTable) local opt = Option:new(myTable) local names = opt:optionNames() local systemDefault = opt.table.system local safeToAdd = true for i,v in ipairs(names) do local _, _, dash, key = v:find("^(%-%-?)([^=-][^=]*)") local exists = self.argNames[key] if (not exists) then self.argNames[key] = opt.table else safeToAdd = false if (not systemDefault) then Error("duplicate option: \"" .. v .. "\"\n") end end end if (safeToAdd) then table.insert(self.optA, opt) end end -------------------------------------------------------------------------- -- Get the value from command line (private). If the *eq\_arg* is non-nil -- then use it. (--foo=eq\_arg). Otherwise get the next argument and remove -- it from *argIn*. If the type is number then convert it. Otherwise store -- a string. -- @param self Optiks object -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param o Optiks_Option object. -- @param optName the option name. -- @return the command line value. function M._getValue(self, eq_arg, argIn, o, optName) local result if (eq_arg) then result = eq_arg else result = argIn[1] if (result == nil) then Error("No value given for option: \"" .. optName .. "\"\n") end table.remove(argIn,1) end if (o.type == "number" ) then result = tonumber(result) end return result end -------------------------------------------------------------------------- -- Store the value from command line -- @param self Optiks object -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param argTbl The table results of parsing the command line. -- @param o Optiks_Option object. -- @param optName the option name. -- @return the value from command line. function M.store(self, eq_arg, argIn, argTbl, o, optName) return self:_getValue(eq_arg,argIn, o, optName) end -------------------------------------------------------------------------- -- Store true from command line -- @param self Optiks object -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param argTbl The table results of parsing the command line. -- @param o Optiks_Option object. -- @param optName the option name. -- @return true function M.store_true(self, eq_arg, argIn, argTbl, o, optName) return true end -------------------------------------------------------------------------- -- Append the command line argument to array. -- @param self Optiks object -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param argTbl The table results of parsing the command line. -- @param o Optiks_Option object. -- @param optName the option name. -- @return the value from command line. function M.append(self, eq_arg, argIn, argTbl, o, optName) local result = self:_getValue(eq_arg, argIn, o, optName) table.insert(argTbl[o.dest], result) return argTbl[o.dest] end -------------------------------------------------------------------------- -- Store false from command line -- @param self Optiks object -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param argTbl The table results of parsing the command line. -- @param o Optiks_Option object. -- @param optName the option name. -- @return false function M.store_false(self, eq_arg, argIn, argTbl, o, optName) return false end -------------------------------------------------------------------------- -- Count the number of times this argument has been given. -- @param self Optiks object -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param argTbl The table results of parsing the command line. -- @param o Optiks_Option object. -- @param optName the option name. -- @return the count. function M.count(self, eq_arg, argIn, argTbl, o, optName) return argTbl[o.dest] + 1 end -------------------------------------------------------------------------- -- Display a store option -- @param self Optiks object -- @param opt Optiks_Option object. -- @return string description of option. function M.display_store(self, opt) local a = {} local dest = opt.dest or "" local s = "" for _,v in ipairs(opt.name) do if (v:len() < 3) then s = v .. " " .. dest else s = v .. "=" .. dest end a[#a + 1] = s end return table.concat(a," ") end -------------------------------------------------------------------------- -- Display a flag option -- @param self Optiks object -- @param opt Optiks_Option object. -- @return string description of option. function M.display_flag(self, opt) local a = {} for _,v in ipairs(opt.name) do a[#a + 1] = v end return table.concat(a," ") end -------------------------------------------------------------------------- -- Display a count option -- @param self Optiks object -- @param opt Optiks_Option object. -- @return string description of option. function M.display_count(self, opt) return self:display_flag(opt) end -------------------------------------------------------------------------- -- Set the defaults for -- @param self Optiks object. -- @param argTbl The table results of parsing the command line. function M.setDefaults(self, argTbl) for i,v in ipairs(self.optA) do v:setDefault(argTbl) end end -------------------------------------------------------------------------- -- This routine is the Big Kahuna. This does all the work of parsing -- Append the command line argument to array. -- @param self Optiks object -- @param optName the option name. -- @param eq_arg The equal arg. (i.e. --foo=eq\_arg) -- @param argIn The current list of command line arguments -- @param argTbl The table results of parsing the command line. function M.parseOpt(self, optName, eq_arg, argIn, argTbl) local o = self.argNames[optName] if (o ~= nil) then argTbl[o.dest] = self[o.action](self, eq_arg, argIn, argTbl, o, optName) else Error("Unknown Option: \"" .. optName .. "\"\n") end end -------------------------------------------------------------------------- -- Build the help message. -- @param self Optiks object -- @return the string result of the help message. function M.buildHelpMsg(self) local term_width = TermWidth() local b = {} b[#b+1] = self.usage b[#b+1] = "\n\nOptions:\n" local a = {} for _,v in ipairs(self.optA) do local opt = v.table a[#a + 1] = { " " .. self.dispTbl[opt.action](self, opt), opt.help or " " } end local bt = BeautifulTbl:new{tbl=a, wrapped=true, column=term_width-1} b[#b+1] = bt:build_tbl() b[#b+1] = "\n" return concatTbl(b,"") end -------------------------------------------------------------------------- -- Print the help message via the *prt* routine. -- @param self Optiks object function M.printHelp(self) self.prt(self:buildHelpMsg()) self.exit(0) end -------------------------------------------------------------------------- -- Parse an environment variable before parsing the command line. -- @param self Optiks object. -- @return an array of options. function M.parseEnvArg(self) local optA = {} local optStr = self.envArg if (optStr == nil) then return optA end local done = false local idx = 1 local len = optStr:len() local i, j, k, q, c while (not done) do while (true) do -- remove leading spaces j, k = optStr:find("%s+",idx) if (k) then idx = k + 1 end if (idx > len) then done = true break end -- look for a quoted string c = optStr:sub(idx,idx) if (c == "\"" or c == "'") then q = c j = optStr:find(q,idx+1) or 0 optA[#optA+1] = optStr:sub(idx+1, j-1) done = (j == 0) break end -- find end of argument i = optStr:find("%s",idx) or 0 optA[#optA+1] = optStr:sub(idx, i-1) if (i == 0) then done = true break end idx = i end end return optA end -------------------------------------------------------------------------- -- Parse the command line arguments. -- @param self Optiks object -- @param argIn The command line arguments. -- @return the argTbl results of parsing the command line options -- @return the positional arguments. function M.parse(self, argIn) ------------------------------------------------------------ -- add these options if the client has not already set them. self:add_option{ name = {"-h", "-?", "--help"}, dest = "Optiks_help", action = "store_true", help = "Show this help message and exit", system = true, } if (self.version) then self:add_option{ name = {"--version"}, dest = "Optiks_version", action = "store_true", help = "Output version info and exit", system = true, } end ------------------------------------------------------------------------ -- Copy env var string and command line args into a local argA = self:parseEnvArg() for i = 1,#argIn do argA[#argA+1] = argIn[i] end local noProcess = nil local parg = {} local argTbl = {[0] = argA[0]} self:setDefaults(argTbl) while (argA[1]) do local key = argA[1] table.remove(argA,1) ------------------------------------------------------------------- -- split any single letter options grouped together. So "-tdw=60" -- becomes: "-t -d -w=60" if (not noProcess and key:find("^%-%w+")) then local a = {} local keyLen = key:len() local current = key:sub(2,2) for j = 2,keyLen do local nxt = key:sub(j+1,j+1) if (nxt ~= "=") then a[#a+1] = "-"..current else a[#a+1] = "-"..key:sub(j,-1) break end current = nxt end key = a[1] for i = #a,2,-1 do table.insert(argA,1,a[i]) end end local _, _, dash, optName = key:find("^(%-%-?)([^=-][^=]*)") local _, _, eq_arg = key:find("=(.*)") if (key == "--") then noProcess = 1 elseif (dash == nil or noProcess) then table.insert(parg, key) noProcess = 1 else self:parseOpt(optName, eq_arg, argA, argTbl) end end if (argTbl.Optiks_help) then self:printHelp() end if (argTbl.Optiks_version) then self.prt(self.version .. "\n") self.exit() end return argTbl, parg end return M Hermes-0.0.20180315/tools/Optiks_Option.lua000066400000000000000000000107721325256533400201610ustar00rootroot00000000000000------------------------------------------------------------------------ -- This class contains the Option objects. There is one of these objects -- for each option specified by Optiks:add_option. -- @classmod Optiks_Option require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- -- Option.lua local Optiks_Error=Optiks_Error local M = {} validTable = { name = "required", dest = "required", action = "required", type = "optional", default = "optional", help = "optional", system = "optional", } validActions = { append = 1, count = 1, store = 1, store_true = 1, store_false = 1, } validTypes = { number = 1, string = 1, } -------------------------------------------------------------------------- -- Find all the option names associated with this option. -- Treat option with underscores the same as ones with dashes. -- @param self Optiks_option object. -- @return an array of option names function M.optionNames(self) local a = self.table.name local b = {} for i = 1,#a do b[#b+1] = a[i] if (a[i]:find("_")) then b[#b+1] = a[i]:gsub("_","-") end end return b end -------------------------------------------------------------------------- -- Test newly build option to see if it is valid. -- @param self Optiks_option object. -- @return non-zero means an error -- @return error message. function M.bless(self) local errStr = "" local ierr = 0 for key in pairs(self.table) do if (not validTable[key] ) then errStr = errStr .. "Unknown Key: " .. key .. "\n" ierr = ierr + 1 end end for key in pairs(validTable) do if (validTable[key] == "required" and not self.table[key]) then errStr = errStr .. "Required Key missing: " .. key .. "\n" ierr = ierr + 1 end end if ( not validActions[self.table.action] ) then errStr = errStr .. "Unknown action: " .. self.table.action .. "\n" ierr = ierr + 1 end if (self.table.type == nil) then self.table.type = "string" end if (not validTypes[self.table.type]) then errStr = errStr .. "Unknown type: " .. self.table.type .. "\n" ierr = ierr + 1 end return ierr, errStr end -------------------------------------------------------------------------- -- Set the default for each option -- @param self Optiks_option object. -- @param argTbl The argument table. function M.setDefault(self, argTbl) local t = self.table if (t.action == "store_true" ) then argTbl[t.dest] = false elseif (t.action == "store_false") then argTbl[t.dest] = true elseif (t.action == "count" ) then argTbl[t.dest] = 0 elseif (t.action == "append" ) then argTbl[t.dest] = {} elseif (t.default ~= nil ) then argTbl[t.dest] = t.default end end -------------------------------------------------------------------------- -- Ctor for class -- @param self Optiks_option object. -- @param myTable option table. function M.new(self, myTable) local o = {} setmetatable(o, self) self.__index = self o.table = myTable local ierr , errStr = o:bless(); if (ierr > 0) then Optiks_Error(errStr) end return o end return M Hermes-0.0.20180315/tools/Stencil.lua000066400000000000000000000115221325256533400167530ustar00rootroot00000000000000------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- -- Stencil: This class takes several kinds of tables and a string with -- with $() in it. The expand function uses the tables to -- replace the keys with values from the tables. require("strict") require("string_utils") local concatTbl = table.concat local dbg = require("Dbg"):dbg() local M = {} function M.new(self, t) local tbl = t local o = {} setmetatable(o, self) self.__index = self o.__tbl = t.tbl or {} o.__envT = t.envTbl or {} o.__funcT = t.funcTbl or {} return o end local function findCmd(s) local ja, jb = s:find("%$%(") if (ja == nil) then return nil, nil end local idx = 1 local q = "" local iparen = 1 idx = jb + 1 while(true) do local jc, jd = s:find("[()]",idx) if (jc == nil) then Error("unequal number of parens") end local c = s:sub(jc,jd) if ( c == "(") then iparen = iparen + 1 end if ( c == ")") then iparen = iparen - 1 if (iparen == 0) then return ja, jd end end idx = jd + 1 end end local function assignOneArg(s,tbl) local ja = s:find("=") if (ja == nil) then tbl[#tbl + 1] = s:trim() else local key = s:sub(1,ja-1):trim() local value = s:sub(ja+1,-1) tbl[key] = value end return tbl end local function findKeyArgs(sIn) local tbl = {} local s = sIn:trim() local ja = s:find("%s") if (ja == nil) then return s, tbl end local key = s:sub(1,ja-1) s = s:sub(ja,-1) local srchlist = '[' .. "'" .. '"' .. ',' .. ']' local ss local r = {} local q = nil local qIdx = nil local idx = 1 while (true) do ja = s:find(srchlist,idx) if (ja == nil) then r[#r + 1] = s:sub(idx, -1) ss = concatTbl(r,"") tbl = assignOneArg(ss,tbl) break end local c = s:sub(ja,ja) if (c == '"' or c == "'") then if (q == nil) then r[#r + 1] = s:sub(idx, ja - 1) qIdx = ja q = c elseif (c == q) then r[#r + 1] = s:sub(qIdx+1, ja - 1) qIdx = nil q = nil end elseif ( c == ',' and q == nil) then r[#r + 1] = s:sub(idx, ja - 1) ss = concatTbl(r,"") tbl = assignOneArg(ss,tbl) r = {} else r[#r + 1] = s:sub(idx, ja - 1) end idx = ja + 1 end return key, tbl end function M.expand(self, s) local result = '' local tbl = self.__tbl local envTbl = self.__envT local funcTbl = self.__funcT local a = {} while (true) do local ja, jb = findCmd(s) if (ja == nil) then a[#a+1] = s break end a[#a+1] = s:sub(1, ja-1) local q = s:sub(ja+2, jb-1) local key,args = findKeyArgs(self:expand(q)) local v = '' if (funcTbl[key] ~= nil) then v = funcTbl[key](args, envTbl, funcTbl) else v = tbl[key] or envTbl[key] or os.getenv(key) if ((not v)) then local entry = funcTbl.batchTbl[key] if (type(entry) == "function") then v = entry(args, envTbl, funcTbl) else v = entry end end end if (v == nil) then Error("No replacement value for key: \""..key.."\" found") end s = v .. s:sub(jb+1,-1) end return concatTbl(a,"") end return M Hermes-0.0.20180315/tools/TermWidth.lua000066400000000000000000000061421325256533400172630ustar00rootroot00000000000000-------------------------------------------------------------------------- -- Use tput cols to find the number of columns. Then check -- stderr to see if it is connected to a tty. If not then -- use 80 columns wide as default. -- -- @module TermWidth require("strict") ----------------------------------------------------------------------- -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- require("capture") local capture = capture or function (s) return nil end local getenv = os.getenv local term = false local s_width = false local min = math.min local s_DFLT = 80 if (pcall(require,"term")) then term = require("term") end ------------------------------------------------------------------------ -- Ask system for width. local function askSystem(width) -- try stty size local r_c = capture("stty size 2> /dev/null") local i, j, rows, columns = r_c:find('(%d+)%s+(%d+)') if (i) then return tonumber(columns) end -- Try env var COLUMNS columns = getenv("COLUMNS") if (columns) then return tonumber(columns) end -- Try tput cols local result = os.execute("tput cols 2> /dev/null") if (result) then return tonumber(capture("tput cols")) end return width end -------------------------------------------------------------------------- -- Return true/false if the *term* interface exists. function haveTermSupport() return (not (not term)) end -------------------------------------------------------------------------- -- Returns the number of columns to use as the terminal width. function TermWidth() if (s_width) then return s_width end s_DFLT = tonumber(getenv("LMOD_TERM_WIDTH")) or s_DFLT s_width = s_DFLT if (getenv("TERM") and term and term.isatty(io.stderr)) then s_width = askSystem(s_width) end local maxW = tonumber(getenv("LMOD_TERM_WIDTH")) or math.huge s_width = min(maxW, s_width) s_width = (s_width > 30) and s_width or 30 return s_width end Hermes-0.0.20180315/tools/capture.lua000066400000000000000000000040311325256533400170120ustar00rootroot00000000000000-------------------------------------------------------------------------- -- use io.popen to open a pipe to collect the output of a command. -- @module capture _DEBUG = false local posix = require("posix") require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- local dbg = require("Dbg"):dbg() -------------------------------------------------------------------------- -- Capture stdout from *cmd* -- @param cmd a string that contains a unix command. function capture(cmd) dbg.start{"capture(",cmd,")"} dbg.print{"cwd: ",posix.getcwd(),"\n",level=2} local p = io.popen(cmd) if p == nil then return nil end local ret = p:read("*all") p:close() dbg.start{"capture output()",level=2} dbg.print{ret} dbg.fini("capture output") dbg.fini("capture") return ret end Hermes-0.0.20180315/tools/declare.lua000066400000000000000000000036471325256533400167620ustar00rootroot00000000000000-------------------------------------------------------------------------- -- These functions allow us to define or check a global variable -- inside a function. -- @module declare ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- -- Declares a string whos value becomes a global variable. -- @param name A string -- @param initval initial value function declare(name, initval) rawset(_G, name, initval or false) end -------------------------------------------------------------------------- -- Is the value of the string a global variable. -- @param name A string. function isDefined(name) return (rawget(_G, name) ~= nil) end Hermes-0.0.20180315/tools/fetch.sh000077500000000000000000000007151325256533400163010ustar00rootroot00000000000000#!/bin/bash # -*- shell-script -*- # Fetch tools from luatools directory: LUATOOLS=( BeautifulTbl.lua Dbg.lua Optiks.lua Optiks_Option.lua Stencil.lua TermWidth.lua capture.lua declare.lua fileOps.lua inherits.lua pairsByKeys.lua serializeTbl.lua string_utils.lua strict.lua ) LUATOOLS_DIR=$HOME/w/luatools/modules HERMES_TOOLS_DIR=$HOME/w/hermes/tools for i in "${LUATOOLS[@]}"; do cp $LUATOOLS_DIR/$i $HERMES_TOOLS_DIR done Hermes-0.0.20180315/tools/fileOps.lua000066400000000000000000000213321325256533400167530ustar00rootroot00000000000000-------------------------------------------------------------------------- -- A collection of useful file operations. -- @module fileOps _DEBUG = false local posix = require("posix") require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- require("string_utils") local lfs = require("lfs") local concatTbl = table.concat -------------------------------------------------------------------------- -- find the absolute path to an executable. -- @param exec Name of executable -- @param path The path to use. If nil then use env PATH. function findInPath(exec, path) local result = "unknown_path_for_" .. (exec or "unknown") if ( exec == nil) then return result end exec = exec:trim() local i = exec:find(" ") local cmd = exec local tail = "" if (i) then cmd = exec:sub(1,i-1) tail = exec:sub(i) end if (cmd:find("/")) then if (posix.access(cmd,"x")) then return exec else return result end end path = path or os.getenv("PATH") for dir in path:split(":") do local fullcmd = pathJoin(dir, cmd) if (posix.access(fullcmd,"x")) then result = fullcmd .. tail break end end return result end ------------------------------------------------------------------------ -- Return true if path is a directory. Note that a symlink to a -- directory is not a directory. -- @param d A file path function isDir(d) if (d == nil) then return false end local t = posix.stat(d,"type") local result = (t == "directory") return result end -------------------------------------------------------------------------- -- Return true if file exists is and is a file or link. -- @param fn A file path function isFile(fn) if (fn == nil) then return false end local t = posix.stat(fn,"type") local result = ((t == "regular") or (t == "link")) return result end -------------------------------------------------------------------------- -- Returns true if file is readable and executable. -- @param fn A file path function isExec(fn) if (fn == nil) then return false end local result = posix.access(fn,"rx") return result end -------------------------------------------------------------------------- -- Return the directory part of path. Will return "./" if path is without a directory. -- @param path A file path function dirname(path) if (path == nil) then return nil end local result local i,j = path:find(".*/") if (i == nil) then result = "./" else result = path:sub(1,j) end return result end -------------------------------------------------------------------------- --- Return the extension of a file or "" if there is none. -- @param path A file path function extname(path) if (path == nil) then return nil end local result local i,j = path:find(".*/") i,j = path:find(".*%.",j) if (i == nil) then result = "" else result = path:sub(j,-1) end return result end -------------------------------------------------------------------------- -- Remove extension from path. -- @param path A file path function removeExt(path) if (path == nil) then return nil end local result local i,j = path:find(".*/") i,j = path:find(".*%.",j) if (i == nil) then result = path else result = path:sub(1,j-1) end return result end -------------------------------------------------------------------------- -- return the file name w/o any directory part. -- @param path A file path function barefilename(path) if (path == nil) then return nil end local result local i,j = path:find(".*/") if (i == nil) then result = path else result = path:sub(j+1,-1) end return result end -------------------------------------------------------------------------- -- split a path into a directory and a file. -- @param path A file path -- @return d A directory path -- @return f a barefilename function splitFileName(path) if (path == nil) then return nil, nil end local d, f local i,j = path:find(".*/") if (i == nil) then d = './' f = path else d = path:sub(1,j) f = path:sub(j+1,-1) end return d, f end -------------------------------------------------------------------------- -- Join argument into a path that has single slashes between directory -- names and no trailing slash. -- @return a file path with single slashes between directory names -- and no trailing slash. function pathJoin(...) local a = {} local arg = { n = select('#', ...), ...} for i = 1, arg.n do local v = arg[i] if (v and v ~= '') then local vType = type(v) if (vType ~= "string") then local msg = "bad argument #" .. i .." (string expected, got " .. vType .. " instead)\n" assert(vType ~= "string", msg) end v = v:trim() if (v:sub(1,1) == '/' and i > 1) then if (v:len() > 1) then v = v:sub(2,-1) else v = '' end end v = v:gsub('//+','/') if (v:sub(-1,-1) == '/') then if (v:len() > 1) then v = v:sub(1,-2) elseif (i == 1) then v = '/' else v = '' end end if (v:len() > 0) then a[#a + 1] = v end end end local s = concatTbl(a,"/") s = path_regularize(s) return s end -------------------------------------------------------------------------- -- Create a new directory recursively. -- @param path A file path function mkdir_recursive(path) local absolute if (path:sub(1,1) == '/') then absolute = true path = path:sub(2,-1) end local a = {} if (absolute) then a[#a + 1] = "/" end local d for v in path:split('/') do a[#a + 1] = v d = concatTbl(a,'/') if (not isDir(d)) then lfs.mkdir(d) end end end -------------------------------------------------------------------------- -- find true path through symlinks. -- @param path Input path -- @param[opt] localDir If true then do not leave the current directory -- when following symlinks -- @return A absolute path. function abspath (path, localDir) if (path == nil) then return nil end local cwd = lfs.currentdir() path = path:trim() if (path:sub(1,1) ~= '/') then path = pathJoin(cwd,path) end local dir = dirname(path) local ival = lfs.chdir(dir) local cdir = lfs.currentdir() if (cdir == nil) then dbg.print{"lfs.currentdir(): is nil"} end dir = cdir or dir path = pathJoin(dir, barefilename(path)) local result = path local attr = lfs.symlinkattributes(path) if (attr == nil) then lfs.chdir(cwd) return nil elseif (attr.mode == "link") then local rl = posix.readlink(path) if (not rl) then lfs.chdir(cwd) return nil end if (localDir and (rl:sub(1,1) == "/" or rl:sub(1,3) == "../")) then lfs.chdir(cwd) return result end result = abspath(rl, localDir) end lfs.chdir(cwd) return result end -------------------------------------------------------------------------- -- Remove leading and trail spaces and extra slashes. -- @param value A path -- @return A clean canonical path. function path_regularize(value) if value == nil then return nil end value = value:gsub("^%s+","") value = value:gsub("%s+$","") value = value:gsub("//+","/") value = value:gsub("/%./","/") value = value:gsub("/$","") if (value == '') then value = ' ' end return value end Hermes-0.0.20180315/tools/inherits.lua000066400000000000000000000050301325256533400171740ustar00rootroot00000000000000------------------------------------------------------------------------ -- Create a new class that inherits from a [[baseClass]] -- @module inherits require("strict") ------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- -- Inherit from Base Class. -- @param baseClass A lua base class object. -- @return derived class object function inheritsFrom( baseClass ) -- The following lines are equivalent to the SimpleClass example: -- Create the table and metatable representing the class. local new_class = {} local class_mt = { __index = new_class } -- Note that this function uses class_mt as an upvalue, so every instance -- of the class will share the same metatable. -- function new_class:create() local newinst = {} setmetatable( newinst, class_mt ) return newinst end -- The following is the key to implementing inheritance: -- The __index member of the new class's metatable references the -- base class. This implies that all methods of the base class will -- be exposed to the sub-class, and that the sub-class can override -- any of these methods. -- if baseClass then setmetatable( new_class, { __index = baseClass } ) end return new_class end Hermes-0.0.20180315/tools/pairsByKeys.lua000066400000000000000000000021641325256533400176210ustar00rootroot00000000000000-------------------------------------------------------------------------- -- Return an iterator where the keys are sorted. -- @module pairsByKeys -------------------------------------------------------------------------- -- This function is described in the book: Programming in Lua by -- Roberto Ierusalimschy. It has been updated for Lua 5.1. -- distributed under the Lua license: http://www.lua.org/license.html -------------------------------------------------------------------------- require("strict") local sort = table.sort ------------------------------------------------------------------------ -- Return an iterator where the keys are sorted. -- @param t input table -- @param[opt] f sort function function pairsByKeys (t, f) local a = {} local n = 0 for k in pairs(t) do n = n + 1 a[n] = k end sort(a, f) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end Hermes-0.0.20180315/tools/serializeTbl.lua000066400000000000000000000145661325256533400200160ustar00rootroot00000000000000------------------------------------------------------------------------ -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- -- serializeTbl: This collection of routines are used to convert a -- table into a string. This string is valid lua code. -- Note that this will only work for "DAG" and not loops. -- There are more general solutions available but the -- output less attractive. Since Lmod tables are DAG's -- this works fine. -- -- Typical usage: -- Write to a file: -- serializeTbl{indent=true, name="SomeName", value=luaTable, -- fn = "/path/to/file"} -- Generate String: -- s = serializeTbl{indent=true, name="SomeName", value=luaTable} -- require("strict") require("fileOps") require("pairsByKeys") require("TermWidth") -------------------------------------------------------------------------- -- nsformat(): Convert the string value into a quoted string of some kind -- and boolean into true/false. local function nsformat(value) if (type(value) == 'string') then if (value:find("\n")) then value = "[[\n" .. value .. "\n]]" else value = value:gsub('"','\\"') value = "\"" .. value .. "\"" end elseif (type(value) == 'boolean') then if (value) then value = 'true' else value = 'false' end end return value end -------------------------------------------------------------------------- -- outputTblHelper(): This is the work-horse for this collections. It is -- used recursively for subtables. It also ignores -- keys that start with "_". local function outputTblHelper(indentIdx, name, T, a, level) ------------------------------------------------- -- Remove all keys in table that start with "_" local t = {} for key in pairs(T) do if (type(key) == "number" or key:sub(1,1) ~= '_') then t[key] = T[key] end end -------------------------------------------------- -- Set initial indent local indent = '' if (indentIdx > 0) then indent = string.rep(" ",indentIdx) end -------------------------------------------------- -- Form name: Wrap name in [] if it has special -- characters or it start with a number. local str if (type(name) == 'string') then if (name:find("[-+:./]") or name == "local" or name == "nil" or name:sub(1,1):find("[0-9]")) then str = indent .. "[\"" .. name .. "\"] = {\n" else str = indent .. name .. " = {\n" end else str = indent .. "{\n" end a[#a+1] = str -------------------------------------------------- -- Update indent local origIndentIdx = indentIdx local origIndent = indent if (indentIdx >= 0) then indentIdx = indentIdx + 2 indent = string.rep(" ",indentIdx) end -- verify if is an array with no tables in it. local isArray = true for key, value in pairs(t) do if (type(value) == "table" or type(key) == "string") then isArray = false break end end local twidth = TermWidth() local w = 0 if (isArray) then a[#a+1] = indent w = w + indent:len() for i = 1,#t-1 do a[#a+1] = nsformat(t[i]) w = w + a[#a]:len() a[#a+1] = ", " w = w + a[#a]:len() if ( w > twidth) then table.insert(a,#a-2,"\n" .. indent) w = a[#a-1]:len()+2+indent:len() end end if (#t > 0) then a[#a+1] = nsformat(t[#t]) a[#a+1] = ",\n" end else for key, value in pairsByKeys(t) do if (type(value) == 'table') then outputTblHelper(indentIdx, key, t[key], a, level+1) else if (type(key) == "string") then str = indent .. '[\"'..key ..'\"] = ' else str = indent end a[#a+1] = str a[#a+1] = nsformat(t[key]) a[#a+1] = ",\n" end end end indent = origIndent indentIdx = origIndentIdx if (level == 0) then a[#a+1] = indent .. '}\n' else a[#a+1] = indent .. "},\n" end end -------------------------------------------------------------------------- -- serializeTbl(): The interface routine for this file. Note that -- it returns a string if no file name is given. function serializeTbl(options) local a = {} local n = options.name local level = 0 local value = options.value local indentIdx = -1 if (options.indent) then indentIdx = 0 end if (type(value) == "table") then outputTblHelper(indentIdx, options.name, options.value, a, level) else a[#a+1] = n a[#a+1] = " = " a[#a+1] = nsformat(value) a[#a+1] = "\n" end local s = table.concat(a,"") if (options.fn == nil) then return s end local fn = options.fn local d = dirname(fn) if (not isDir(d)) then os.execute('mkdir -p ' .. d) end local f = assert(io.open(fn, "w")) f:write("-- -*- lua -*-\n") f:write("-- created: ",os.date()," --\n") f:write(s) f:close() end Hermes-0.0.20180315/tools/strict.lua000066400000000000000000000017401325256533400166630ustar00rootroot00000000000000-- strict.lua -- checks uses of undeclared global variables -- All global variables must be 'declared' through a regular assignment -- (even assigning nil will do) in a main chunk before being used -- anywhere or assigned to inside a function. -- distributed under the Lua license: http://www.lua.org/license.html local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget local mt = getmetatable(_G) if mt == nil then mt = {} setmetatable(_G, mt) end mt.__declared = {} local function what () local d = getinfo(3, "S") return d and d.what or "C" end mt.__newindex = function (t, n, v) if not mt.__declared[n] then local w = what() if w ~= "main" and w ~= "C" then error("assign to undeclared variable '"..n.."'", 2) end mt.__declared[n] = true end rawset(t, n, v) end mt.__index = function (t, n) if not mt.__declared[n] and what() ~= "C" then error("variable '"..n.."' is not declared", 2) end return rawget(t, n) end Hermes-0.0.20180315/tools/string_utils.lua000066400000000000000000000120321325256533400200750ustar00rootroot00000000000000-------------------------------------------------------------------------- -- More string utilities. -- @classmod string require("strict") -------------------------------------------------------------------------- -- -- Copyright (C) 2008-2014 Robert McLay -- -- Permission is hereby granted, free of charge, to any person obtaining -- a copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject -- to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- -- remove leading and trailing spaces. -- @param self input string function string.trim(self) local ja = self:find("%S") if (ja == nil) then return "" end local jb = self:find("%s+$") or 0 local self = self:sub(ja,jb-1) return self end -------------------------------------------------------------------------- -- An iterator to loop split a pieces. This code is from the -- lua-users.org/lists/lua-l/2006-12/msg00414.html -- @param self input string -- @param pat pattern to split on. function string.split(self, pat) pat = pat or "%s+" local st, g = 1, self:gmatch("()("..pat..")") local function getter(self, segs, seps, sep, cap1, ...) st = sep and seps + #sep return self:sub(segs, (seps or 0) - 1), cap1 or sep, ... end local function splitter(self) if st then return getter(self, st, g()) end end return splitter, self end -------------------------------------------------------------------------- -- Form a case independent search string pattern. -- @param self input string -- @return case independent search string pattern. function string.caseIndependent(self) local slen = self:len() local a = {} for i = 1, slen do local c = self:sub(i,i) if (c:find("%a")) then a[#a+1] = '['..c:upper()..c:lower()..']' elseif (c:find('[%-%.%+%[%]%(%)%$%^%%%?%*]')) then a[#a+1] = '%'..c else a[#a+1] = c end end return concatTbl(a,"") end -------------------------------------------------------------------------- -- Wrap input string with double quotes -- @param self Input string -- @return A string surrounded with double quotes internal double quotes backslashed function string.doubleQuoteString(self) if (type(self) ~= 'string') then self = tostring(self) else self = ('%q'):format(self) end return self end -------------------------------------------------------------------------- -- Escape @ character in input string. -- @param self Input string. -- @return An escaped @ in output. function string.atSymbolEscaped(self) if (self == nil) then return self end self = self:gsub('@','\\@') return self end isLua51 = _VERSION:match('5%.1$') -------------------------------------------------------------------------- -- Convert a search string that may have special regular expression and -- quote them. This is very useful when trying to match version numbers -- like "2.4-1" where you want "." and "-" to treated as normal characters -- and not regular expression ones. -- @param self Input string. -- @return escaped string. function string.escape(self) local res = self:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1') if isLua51 then res = res:gsub('%z','%%z') end return res end -------------------------------------------------------------------------- -- Pass in *line* and convert text to fit space. -- @param self Input string -- @param indent A number of spaces use to indent each line -- @param width terminal width. -- @return filled and wrap block of lines. function string.fillWords(self, indent, width) local a = {} local ia = 0 local len = 0 ia = ia + 1; a[ia] = indent; len = len + indent:len() for word in self:split("[ \n]+") do local wlen = word:len() if (wlen + len >= width) then a[ia] = a[ia]:trim() ia = ia + 1; a[ia] = "\n"; ia = ia + 1; a[ia] = indent; len = indent:len() end ia = ia + 1; a[ia] = word; ia = ia + 1; a[ia] = " "; len = len + wlen + 1 end a[ia] = a[ia]:trim() return concatTbl(a,"") end Hermes-0.0.20180315/updateProjectDataVersion/000077500000000000000000000000001325256533400204575ustar00rootroot00000000000000Hermes-0.0.20180315/updateProjectDataVersion/CmdLineOptions.lua000066400000000000000000000015701325256533400240540ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "updateProjectDataVersion [options]" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'--new_version'}, dest = 'new_version', action = 'store', type = 'string', default = false, } cmdlineParser:add_option{ name = {'--version'}, dest = 'version', action = 'store_true', type = 'string', } cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count' } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/updateProjectDataVersion/GetVersion.lua000066400000000000000000000002321325256533400232440ustar00rootroot00000000000000GetVersion = BaseTask:new() function GetVersion:execute(myTable) local masterTbl = masterTbl() print (masterTbl.projectData.HermesVersion) end Hermes-0.0.20180315/updateProjectDataVersion/WriteProjectData.lua000066400000000000000000000006451325256533400244020ustar00rootroot00000000000000require("serializeTbl") WriteProjectData = BaseTask:new() function WriteProjectData:execute(myTable) local masterTbl = masterTbl() masterTbl.projectData.HermesVersion = masterTbl.new_version masterTbl.projectData.HermesVersionDate = os.date("%c") print ('version: ', masterTbl.new_version) serializeTbl{name="ProjectData",value=masterTbl.projectData, fn=masterTbl.projectFn, indent=true} end Hermes-0.0.20180315/updateProjectDataVersion/updateProjectDataVersion.tasks000066400000000000000000000003611325256533400264770ustar00rootroot00000000000000-- -*- lua -*- function taskMain() task{"ReadProject"} task{"CmdLineOptions"} local masterTbl = masterTbl() if (masterTbl.version) then task{"GetVersion"} else task{"WriteProjectData"} end return 0 end Hermes-0.0.20180315/wrapperDiff/000077500000000000000000000000001325256533400157575ustar00rootroot00000000000000Hermes-0.0.20180315/wrapperDiff/CmdLineOptions.lua000066400000000000000000000015621325256533400213550ustar00rootroot00000000000000CmdLineOptions = BaseTask:new() function CmdLineOptions:execute(myTable) local masterTbl = masterTbl() local usage = "Usage: wrapperDiff [options] gold.file trial.file" local Optiks = require("Optiks") local cmdlineParser = Optiks:new{usage=usage, error = Error} cmdlineParser:add_option{ name = {'-r', '--resultfile'}, dest = 'resultFn', action = 'store' } cmdlineParser:add_option{ name = {'--csv'}, dest = 'csvFn', action = 'store' } cmdlineParser:add_option{ name = {'-v','--verbose'}, dest = 'verbosityLevel', action = 'count', help = 'Increasing the level of verbosity help output', } local optionTbl, pargs = cmdlineParser:parse(arg) for v in pairs(optionTbl) do masterTbl[v] = optionTbl[v] end masterTbl.pargs = pargs end Hermes-0.0.20180315/wrapperDiff/DiffWrapper.lua000066400000000000000000000044501325256533400206760ustar00rootroot00000000000000 require("serializeTbl") require("fileOps") myTbl = {} concatTbl = table.concat local load = (_VERSION == "Lua 5.1") and loadstring or load DiffWrapper = BaseTask:new() function DiffWrapper:execute(myTable) local masterTbl = masterTbl() local origA = { masterTbl.pargs[1], masterTbl.pargs[2] } local modA = { '_' .. removeExt(barefilename(origA[1])) .. ".left", '_' .. removeExt(barefilename(origA[2])) .. ".right",} local cmdA = {} local cmdLine for i = 1,2 do cmdA[#cmdA + 1 ] = "sed -e 's/Lua: Version.*/Lua: Version/g' -e 's/suite: Version.*//g' <" cmdA[#cmdA + 1 ] = origA[i] cmdA[#cmdA + 1 ] = ">" cmdA[#cmdA + 1 ] = modA[i] cmdLine = concatTbl(cmdA," ") print (cmdLine) os.execute(cmdLine) cmdA = {} end cmdA[#cmdA + 1] = "diff -c " cmdA[#cmdA + 1] = modA[1] cmdA[#cmdA + 1] = modA[2] cmdA[#cmdA + 1] = "> diff.log 2>&1" local cmdline = concatTbl(cmdA," ") print (cmdline) local status = os_execute(cmdline) masterTbl.status = status local result = "diff" if (status == 0) then result = "passed" else cmdA = {} cmdA[#cmdA + 1] = 'grep -q "lua: error"' cmdA[#cmdA + 1] = modA[2] cmdA[#cmdA + 1] = "> diff.log 2>&1" cmdline = concatTbl(cmdA," ") status = os_execute(cmdline) result = (status == 0) and "failed" or "diff" end os.remove("diff.log") --os.remove(modA[1]) --os.remove(modA[2]) local resultFn = masterTbl.resultFn local csvFn = masterTbl.csvFn if (csvFn) then local f = io.open(csvFn,"a") f:write(result,", ",modA[2],", wrapperDiff\n") f:close() end if (resultFn) then local f = io.open(resultFn,"r") if (f) then local s = f:read("*all") assert(load(s))() end myTbl[#myTbl+1] = { result=result, program="wrapperDiff"} serializeTbl{name="myTbl", value=myTbl, fn=resultFn, indent=true} end end local function execute51(s) return os.execute(s) end local function execute52(s) local success, flag, status = os.execute(s) return status end local version = _VERSION:gsub("^Lua%s+","") os_execute = execute52 if (version == "5.1") then os_execute = execute51 end Hermes-0.0.20180315/wrapperDiff/wrapperDiff.tasks000066400000000000000000000002301325256533400212720ustar00rootroot00000000000000-- -*- lua -*- function taskMain() local masterTbl = masterTbl() task{"CmdLineOptions"} task{"DiffWrapper"} return masterTbl.status end