Icon representing a recipe

Recipe: Safe Fun 1.4

created by LociOiling

Profile


Name
Safe Fun 1.4
ID
104212
Shared with
Public
Parent
Safe Fun 1.3
Children
None
Created on
December 15, 2020 at 03:36 AM UTC
Updated on
December 15, 2020 at 03:36 AM UTC
Description

Safe Fun demonstrates the use of the pcall function to trap errors. SafeFun tests many of the Foldit Lua functions for parameter errors, such as segment out of range. SafeFun allows testing functions by group, such as band, behavior, selection, and structure. Version 1.2 adds a dialog to allow control over which tests run. Version 1.3 refines error testing. Version 1.4 adds new recent functions, and a few older ones, too.

Best for


Code


--[[ Safe Fun "Safe" wrappers for functions which may crash your recipe. Many of the foldit LUA functions terminate the recipe if called with an invalid parameter. For example, selection.Select terminates the recipe if the segment specified is outside of the valid range of segments. The wrapper functions are prefixed with "Safe" and added to the same namespace (table) as the original problem function. For example, selection.SafeSelect can be used in place of selection.Select. The wrapper functions catch the error using the LUA pcall function, and return an error code and an error message if the underlying function failed. A return code of zero indicate the underlying function was successful. The return values from the underlying function are returned after the return code. For example, structure.IsHydrophobic returns a boolean, so structure.SafeIsHydrophobic returns an number and a boolean: local rc local isPhobic rc, isPhobic = structure.SafeIsHydrophobic ( segIdx ) if rc ~= 0 then print ( "IsHydrophobic ( " .. segidx .. " ), rc = " .. rc .. ", errmsg = \"" .. errmsg .. "\"" ) else if isPhobic then ... end end A negative return code indicates the underlying function encountered an error. A return code of -1 is commonly used to indicate a bad segment index. Large negative return codes indicate a general error: * -997 = argument type error * -998 = argument count error * -999 = other unspecifed error For example, the call rc, errmsg = behavior.SafeSetClashImportance ( "very" ) would return rc = -997, and errmsg = "(number expected, got string)". On the other hand, with a otherwise valid numeric argument, the call rc, errmsg = behavior.SafeSetClashImportance ( 19 ) would return rc = -1, and errmsg = "(clashing importance value outside valid range - between 0 and 1))". Calling scripts should at least check for a zero return code, and possibly log information for debugging purposes. In most cases, scripts should be able to continue, perhaps after skipping the current work item. The most common errors seem to be a bad segment number, bad band parameters, and a bad rotamer number. This recipe consists of a "safe functions" section and a test routine. The safe functions can be copied into other recipes, in whole or in part. The safefun table and the CommonError function are required for the other functions to work. The test routine is table-driven, and tests each safe function. The test table includes the expected return code for each test. An error message is printed if the actual return code does not match the expected return code. The test cases generally cover specific error cases and one or more successful rc = 0 cases. In particular, one band.SafeAddBetweenSegments case should be successful. The band from this test case, which should have band index 1, is then used in later tests. version history 1.1 LociOiling 2020/02/23 + added dialog, break down tests by group 1.2 LociOiling 2020/02/24 + added "test all" option + more tests and functions: * band.SafeAddBetweenSegments - test added for new symmetric chain option * structure.InsertResidue and structure.DeleteResidue added 1.3 LociOiling 2020/02/25 + minor cosmetic fixes + add parameter type error as a test type + rework error checking, use CommonError instead of ParseError * new return code -997 for argument type error * new return code -998 for argument count error 1.4 LociOiling 2020/12/12 + whole lotta new functions: * band.GetAtomBase * band.GetAtomEnd * band.GetResidueBase * band.GetResidueBase * band.IsRecipeBand * behavior.SetBackboneHBondImportance * behavior.SetSidechainHBondImportance * behavior.SetDensityImportance * behavior.SetHidingImportance * behavior.SetPackingImportance * behavior.SetPairwiseImportance * all save functions + add TTCRASHY type for tests which causes crashes or hangs + default to running all types except TTCRASHY + selecting one group of functions now overrides "select all" ]]-- Recipe = "Safe Fun" Version = "1.4" ReVersion = Recipe .. " " .. Version -- -- options -- local opts = {} opts.runall = true -- test all groups if true opts.ttpasses = true -- run all tests which are expected to pass opts.ttsegrng = true -- run all tests for segment range errors opts.ttpvalue = true -- run all tests for parameter value errors opts.ttargcnt = true -- run all tests for argument count errors opts.ttargtyp = true -- run all tests for argument type errors opts.ttcrashy = false -- run all tests which may end the client -- -- safe functions v 1.0 -- -- safe functions use pcall to invoke functions which -- may unexpectedly terminate the script -- -- safe functions are added to the existing Foldit psuedo-classes -- -- -- common section used by all safe functions -- safefun = {} -- -- CommonError -- common routine used by safe functions, -- checks for common errors -- -- checks for errors like bad segment and bad band index -- even for functions where they don't apply -- efficiency -- not a key concern here -- -- any error that appears more than once gets tested here -- -- first return codes may not be unique -- safefun.CommonError = function ( errmsg ) local BADSEG = "segment index out of bounds" local ARGCNT = "Expected %d+ arguments." local BADARG = "bad argument #%d+ to '%?' (%b())" local EXPECT = "expected, got" local BADATOM = "atom number out of bounds" local BADBAND = "band index out of bounds" local BADSYMM = "symmetry index out of bounds" local BADACID = "invalid argument, unknown aa code" local errp, errq = errmsg:find ( BADSEG ) if errp ~= nil then return -1, errmsg end -- -- "bad argument" messages include argument type errors -- and some types of argument value errors -- trap only the argument type errors here -- local errp, errq, errd = errmsg:find ( BADARG ) if errp ~= nil then local errp2 = errd:find ( EXPECT ) if errp2 ~= nil then return -997, errmsg -- argument type error end end local errp, errq = errmsg:find ( ARGCNT ) if errp ~= nil then return -998, errmsg end local errp, errq = errmsg:find ( BADATOM ) if errp ~= nil then return -2, errmsg end local errp, errq = errmsg:find ( BADBAND ) if errp ~= nil then return -3, errmsg end local errp, errq = errmsg:find ( BADACID ) if errp ~= nil then return -2, errmsg end local errp, errq = errmsg:find ( BADSYMM ) if errp ~= nil then return -3, errmsg end return 0, errmsg end -- -- end of common section used by all safe functions -- -- -- band.SafeAdd uses pcall -- to call band.Add, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the band index of the added band (number). -- -1 - bad segment number -- -2 - reserved -- -3 - reserved -- -4 - bad rho -- -5 - bad theta -- -6 - bad phi -- -99x - other error -- band.SafeAdd = function ( ... ) -- -- error messages -- local BADRHO = "rho must be" local BADTHETA = "theta must be" local BADPHI = "phi must be" -- local good, errmsg = pcall ( band.Add, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADRHO ) if errp ~= nil then return -4, err2 end local errp = err2:find ( BADTHETA ) if errp ~= nil then return -5, err2 end local errp = err2:find ( BADPHI ) if errp ~= nil then return -6, err2 end return -999, err2 end end -- -- band.SafeAddBetweenSegments uses pcall -- to call band.AddBetweenSegments, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the band index of the added band (number). -- -1 - bad segment number -- -2 - bad atom number -- -3 - bad symmetric chain number -- -99x - other error -- band.SafeAddBetweenSegments = function ( ... ) local good, errmsg = pcall ( band.AddBetweenSegments, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeAddToBandEndpoint uses pcall -- to call band.ToBandEndpoint, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the band index of the added band (number). -- -1 - bad segment number -- -2 - bad atom number -- -3 - bad band number -- -99x - other error -- band.SafeAddToBandEndpoint = function ( ... ) local good, errmsg = pcall ( band.AddToBandEndpoint, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeDelete uses pcall -- to call band.Delete, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -3 - bad band number -- -99x - other error -- band.SafeDelete = function ( ... ) local good, errmsg = pcall ( band.Delete, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeDisable uses pcall -- to call band.Disable, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -3 - bad band number -- -99x - other error -- band.SafeDisable = function ( ... ) local good, errmsg = pcall ( band.Disable, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeGetGoalLength uses pcall -- to call band.GetGoalLength, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the goal length -- of the specifed band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetGoalLength = function ( ... ) local good, errmsg = pcall ( band.GetGoalLength, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeGetLength uses pcall -- to call band.GetLength, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the current length -- of the specifed band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetLength = function ( ... ) local good, errmsg = pcall ( band.GetLength, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeGetStrength uses pcall -- to call band.GetStrength, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the strength -- of the specified band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetStrength = function ( ... ) local good, errmsg = pcall ( band.GetStrength, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- -- band.SafeSetGoalLength uses pcall -- to call band.SetGoalLength, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful -- -1 - reserved -- -2 - reserved -- -3 - bad band number -- -4 - bad band length -- -99x - other error -- band.SafeSetGoalLength = function ( ... ) -- -- error messages -- local BADLEN = "band length out of bounds" -- local good, errmsg = pcall ( band.SetGoalLength, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADLEN ) if errp ~= nil then return -4, err2 end return -999, err2 end end -- -- band.SafeSetStrength uses pcall -- to call band.SetStrength, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful -- -1 - reserved -- -2 - reserved -- -3 - bad band number -- -4 - bad band strength -- -99x - other error -- band.SafeSetStrength = function ( ... ) -- -- error messages -- local BADSTREN = "band strength out of bounds" -- local good, errmsg = pcall ( band.SetStrength, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADSTREN ) if errp ~= nil then return -4, err2 end return -999, err2 end end -- -- band.SafeGetAtomBase uses pcall -- to call band.GetAtomBase, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the atom number for the start -- of the specifed band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetAtomBase = function ( ... ) local good, errmsg = pcall ( band.GetAtomBase, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeGetAtomEnd uses pcall -- to call band.GetAtomEnd, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the atom number for the end -- of the specifed band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetAtomEnd = function ( ... ) local good, errmsg = pcall ( band.GetAtomEnd, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeGetResidueBase uses pcall -- to call band.GetResidueBase, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the residue number for the start -- of the specifed band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetResidueBase = function ( ... ) local good, errmsg = pcall ( band.GetResidueBase, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeGetResidueEnd uses pcall -- to call band.GetResidueEnd, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the residue number for the end -- of the specifed band (number). -- -3 - bad band number -- -99x - other error -- band.SafeGetResidueEnd = function ( ... ) local good, errmsg = pcall ( band.GetResidueEnd, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- band.SafeIsRecipeBand uses pcall -- to call band.IsRecipeBand, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -99x - other error -- band.SafeIsRecipeBand = function ( ... ) -- local good, errmsg = pcall ( band.IsRecipeBand, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- behavior.SafeSetClashImportance uses pcall -- to call behavior.SetClashImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad CI -- -99x - other error -- behavior.SafeSetClashImportance = function ( ... ) -- -- error message -- local BADCLASH = "clashing importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetClashImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADCLASH ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- behavior.SafeSetBackboneHBondImportance uses pcall -- to call behavior.SetBackboneHBondImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad hbond importance value -- -99x - other error -- behavior.SafeSetBackboneHBondImportance = function ( ... ) -- -- error message -- local BADIMP = "backbone hbond importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetBackboneHBondImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADIMP ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- behavior.SafeSetSidechainHBondImportance uses pcall -- to call behavior.SetSidechainHBondImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad hbond importance value -- -99x - other error -- behavior.SafeSetSidechainHBondImportance = function ( ... ) -- -- error message -- local BADIMP = "sidechain hbond importance value outside valid range " -- local good, errmsg = pcall ( behavior.SetSidechainHBondImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADIMP ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- behavior.SafeSetDensityImportance uses pcall -- to call behavior.SetDensityImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad density importance value -- -99x - other error -- behavior.SafeSetDensityImportance = function ( ... ) -- -- error message -- local BADIMP = "density importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetDensityImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADIMP ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- behavior.SafeSetHidingImportance uses pcall -- to call behavior.SetHidingImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad density importance value -- -99x - other error -- behavior.SafeSetHidingImportance = function ( ... ) -- -- error message -- local BADIMP = "hiding importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetHidingImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADIMP ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- behavior.SafeSetPackingImportance uses pcall -- to call behavior.SetPackingImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad density importance value -- -99x - other error -- behavior.SafeSetPackingImportance = function ( ... ) -- -- error message -- local BADIMP = "packing importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetPackingImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADIMP ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- behavior.SafeSetPairwiseImportance uses pcall -- to call behavior.SetHidingImportance, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad density importance value -- -99x - other error -- behavior.SafeSetPairwiseImportance = function ( ... ) -- -- error message -- local BADIMP = "pairwise importance value outside valid range" -- local good, errmsg = pcall ( behavior.SetPairwiseImportance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADIMP ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- contactmap.SafeIsContact uses pcall -- to call contactmap.IsContact, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the contact status -- of the specified segments (boolean). -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- contactmap.SafeIsContact = function ( ... ) local good, errmsg = pcall ( contactmap.IsContact, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- freeze.SafeFreeze uses pcall -- to call freeze.Freeze, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- freeze.SafeFreeze = function ( ... ) local good, errmsg = pcall ( freeze.Freeze, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- freeze.SafeIsFrozen uses pcall -- to call freeze.IsFrozen, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the freeze status -- of the specified segment (boolean). -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- freeze.SafeIsFrozen = function ( ... ) local good, errmsg = pcall ( freeze.IsFrozen, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- freeze.SafeUnfreeze uses pcall -- to call freeze.Unfreeze, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- freeze.SafeUnfreeze = function ( ... ) local good, errmsg = pcall ( freeze.Unfreeze, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- metric.SafeGetBonus uses pcall -- to call metric.GetBonus, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad metric name -- -99x - other error -- metric.SafeGetBonus = function ( ... ) -- -- error messages -- local BADMET = "not a valid metric" -- local good, errmsg = pcall ( metric.GetBonus, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADMET ) if errp ~= nil then return -1, err2 end return -999, err2 end end -- -- metric.SafeGetBonusTotal uses pcall -- to call metric.GetBonusTotal, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- metric.SafeGetBonusTotal = function ( ... ) local good, errmsg = pcall ( metric.GetBonusTotal, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- metric.SafeGetNames uses pcall -- to call metric.GetNames, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- metric.SafeGetNames = function ( ... ) local good, errmsg = pcall ( metric.GetNames, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- metric.SafeGetNames uses pcall -- to call metric.GetNames, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- metric.SafeGetNames = function ( ... ) local good, errmsg = pcall ( metric.GetNames, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeGetSolutions uses pcall -- to call save.GetSolutions, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the table of saved solutions -- -99x - other error -- save.SafeGetSolutions = function ( ... ) local good, errmsg = pcall ( save.GetSolutions, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeLoadSolution uses pcall -- to call save.LoadSolution, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeLoadSolution = function ( ... ) local good, errmsg = pcall ( save.LoadSolution, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeLoadSolutionByName uses pcall -- to call save.LoadSolutionByName, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeLoadSolutionByName = function ( ... ) local good, errmsg = pcall ( save.LoadSolutionByName, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeSaveSolution uses pcall -- to call save.SaveSolution, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeSaveSolution = function ( ... ) local good, errmsg = pcall ( save.SaveSolution, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeQuicksave uses pcall -- to call save.Quicksave, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeQuicksave = function ( ... ) local good, errmsg = pcall ( save.Quicksave, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeQuickload uses pcall -- to call save.Quickload, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeQuickload = function ( ... ) local good, errmsg = pcall ( save.Quickload, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeQuicksaveEmpty uses pcall -- to call save.QuicksaveEmpty, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeQuicksaveEmpty = function ( ... ) local good, errmsg = pcall ( save.QuicksaveEmpty, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeSaveSecondaryStructure uses pcall -- to call save.SaveSecondaryStructure, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeSaveSecondaryStructure = function ( ... ) local good, errmsg = pcall ( save.SaveSecondaryStructure, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- save.SafeLoadSecondaryStructure uses pcall -- to call save.LoadSecondaryStructure, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, the error msg is nil -- -99x - other error -- save.SafeLoadSecondaryStructure = function ( ... ) local good, errmsg = pcall ( save.LoadSecondaryStructure, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- rotamer.SafeGetCount uses pcall -- to call rotamer.GetCount, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the rotamer count -- of the specified segment (boolean). -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- rotamer.SafeGetCount = function ( ... ) local good, errmsg = pcall ( rotamer.GetCount, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- rotamer.SafeSetRotamer uses pcall -- to call rotamer.SetRotamer, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad rotamer index -- -99x - other error -- rotamer.SafeSetRotamer = function ( ... ) -- -- error messages -- local BADSNAP = "snap index out of bounds" -- local good, errmsg = pcall ( rotamer.SetRotamer, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADSNAP ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- selection.SafeIsSelected uses pcall -- to call selection.IsSelected, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the selection status -- of the specified segment (boolean). -- -1 - bad segment index -- -99x - other error -- selection.SafeIsSelected = function ( ... ) local good, errmsg = pcall ( selection.IsSelected, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- -- selection.SafeSelect uses pcall -- to call selection.Select, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- selection.SafeSelect = function ( ... ) local good, errmsg = pcall ( selection.Select, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- selection.SafeSelectRange uses pcall -- to call selection.SelectRange, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- selection.SafeSelectRange = function ( ... ) local good, errmsg = pcall ( selection.SelectRange, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeCanMutate uses pcall -- to call structure.CanMutate, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the mutability status -- of the specified segment (boolean). -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- structure.SafeCanMutate = function ( ... ) local good, errmsg = pcall ( structure.CanMutate, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeDeleteCut uses pcall -- to call structure.DeleteCut, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- structure.SafeDeleteCut = function ( ... ) local good, errmsg = pcall ( structure.DeleteCut, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeDeleteResidue uses pcall -- to call structure.DeleteResidue, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- structure.SafeDeleteResidue = function ( ... ) local good, errmsg = pcall ( structure.DeleteResidue, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeGetAminoAcid uses pcall -- to call structure.GetAminoAcid, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the one-letter amino acid code -- of the specified segment (string). -- -1 - bad segment index -- -99x - other error -- structure.SafeGetAminoAcid = function ( ... ) local good, errmsg = pcall ( structure.GetAminoAcid, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeGetAtomCount uses pcall -- to call structure.GetAtomCount, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the atom count -- of the specified segment (number). -- -1 - bad segment index -- -99x - other error -- structure.SafeGetAtomCount = function ( ... ) local good, errmsg = pcall ( structure.GetAtomCount, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeGetDistance uses pcall -- to call structure.GetDistance, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned -- value is the distance -- 0 - successful, second returned value is -- the distance between -- the specified segments (number). -- -1 - bad segment index -- -99x - other error -- structure.SafeGetDistance = function ( ... ) local good, errmsg = pcall ( structure.GetDistance, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeGetNote uses pcall -- to call structure.GetNote, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the note text -- for the specified segment (string). -- -1 - bad segment index -- -99x - other error -- structure.SafeGetNote = function ( ... ) local good, errmsg = pcall ( structure.GetNote, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeGetSecondaryStructure uses pcall -- to call structure.GetSecondaryStructure, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the one-letter secondary structure code -- of the specified segment (string). -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- structure.SafeGetSecondaryStructure = function ( ... ) local good, errmsg = pcall ( structure.GetSecondaryStructure, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeInsertCut uses pcall -- to call structure.InsertCut, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- structure.SafeInsertCut = function ( ... ) local good, errmsg = pcall ( structure.InsertCut, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeInsertResidue uses pcall -- to call structure.InsertResidue, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- structure.SafeInsertResidue = function ( ... ) local good, errmsg = pcall ( structure.InsertResidue, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeIsHydrophobic uses pcall -- to call structure.IsHydrophobic, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the hydrophobicity status -- of the specified segment (boolean). -- -1 - bad segment index -- -99x - other error -- structure.SafeIsHydrophobic = function ( ... ) local good, errmsg = pcall ( structure.IsHydrophobic, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeIsLocked uses pcall -- to call structure.IsLocked, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the locked status -- of the specified segment (boolean). -- -1 - bad segment index -- -99x - other error -- structure.SafeIsLocked = function ( ... ) local good, errmsg = pcall ( structure.IsLocked, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeIsMutable uses pcall -- to call structure.IsMutable, returning -- a numeric return code. -- -- If the return code is non-zero, -- an error message is also returned. -- -- The return codes are: -- -- 0 - successful, second returned value is -- the mutability status -- of the specified segment (boolean). -- -1 - bad segment index -- -99x - other error -- structure.SafeIsMutable = function ( ... ) local good, errmsg = pcall ( structure.IsMutable, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeSetAminoAcid uses pcall -- to call structure.SetAminoAcid, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad amino acid code -- -99x - other error -- structure.SafeSetAminoAcid = function ( ... ) local good, errmsg = pcall ( structure.SetAminoAcid, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeSetAminoAcidSelected uses pcall -- to call structure.SetAminoAcidSelected, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -2 - bad amino acid code -- -99x - other error -- structure.SafeSetAminoAcidSelected = function ( ... ) local good, errmsg = pcall ( structure.SetAminoAcidSelected, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeSetNote uses pcall -- to call structure.SetNote, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -99x - other error -- structure.SafeSetNote = function ( ... ) local good, errmsg = pcall ( structure.SetNote, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end return -999, err2 end end -- -- structure.SafeSetSecondaryStructure uses pcall -- to call structure.SetSecondaryStructure, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -1 - bad segment index -- -2 - bad secondary structure code -- -99x - other error -- structure.SafeSetSecondaryStructure = function ( ... ) -- -- error messages -- local BADCODE = "invalid argument" local good, errmsg = pcall ( structure.SetSecondaryStructure, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADCODE ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- structure.SafeSetSecondaryStructureSelected uses pcall -- to call structure.SetSecondaryStructureSelected, returning -- a numeric return code and an error message. -- -- The return codes are: -- -- 0 - successful, error message is nil -- -2 - bad secondary structure code -- -99x - other error -- structure.SafeSetSecondaryStructureSelected = function ( ... ) -- -- error message for an invalid secondary structure code -- local BADCODE = "invalid argument" local good, errmsg = pcall ( structure.SetSecondaryStructureSelected, unpack ( arg ) ) if good then return 0, errmsg else local crc, err2 = safefun.CommonError ( errmsg ) if crc ~= 0 then return crc, err2 end local errp = err2:find ( BADCODE ) if errp ~= nil then return -2, err2 end return -999, err2 end end -- -- end of safe functions v 1.0 -- -- -- try to terminate the recipe -- function main () print ( ReVersion ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) save.Quicksave ( 3 ) save.SaveSecondaryStructure () band.DeleteAll () local segCnt = structure.GetCount () print ( "Segment count = " .. segCnt ) -- -- many functions use segment indexes, -- define some useful ones -- local SEGOUT = segCnt + 1 local SEGFOO1 = -1 local SEGFOO2 = -999 local SEGFOO3 = 999 local SEGMID = math.floor ( segCnt / 2 ) print ( "Middle segment = " .. SEGMID ) -- -- assorted other bad values -- local HIATOM = 99 -- atom number local HIROTA = 999 -- rotamer number local HIBAND = 999 local LOBAND = -1 local LNGBND = 11000 local SHRTBND= -1 local STRNGBND = 12 local WEAKBND = -1 local HIRHO = 11000 -- you take the high rho local LORHO = -39 -- and I'll take the low rho local OKRHO = 20 -- and this one is just right local HITHETA = 4.0 local LOTHETA = -1.0 local OKTHETA = 3.14 / 2 local HIPHI = 3.14 * 3 local LOPHI = -1.0 local OKPHI = 3.14 local HISYM = 36 -- when does an oligomer become a polymer? -- -- function table - one entry per function to be tested -- -- somewhat repetitive and repetitious, but Foldit does -- not allow access to the Lua "debug" functions -- local FUNCNAME = 1 local FUNCCALL = 2 local func = { Add = { "band.SafeAdd", band.SafeAdd, }, AddBetweenSegments = { "band.SafeAddBetweenSegments", band.SafeAddBetweenSegments, }, AddToBandEndpoint = { "band.SafeAddToBandEndpoint", band.SafeAddToBandEndpoint, }, Delete = { "band.SafeDelete", band.SafeDelete, }, Disable = { "band.SafeDisable", band.SafeDisable, }, GetGoalLength = { "band.SafeGetGoalLength", band.SafeGetGoalLength, }, GetLength = { "band.SafeGetLength", band.SafeGetLength, }, GetStrength = { "band.SafeGetStrength", band.SafeGetStrength, }, SetGoalLength = { "band.SafeSetGoalLength", band.SafeSetGoalLength, }, SetStrength = { "band.SafeSetStrength", band.SafeSetStrength, }, GetAtomBase = { "band.SafeGetAtomBase", band.SafeGetAtomBase, }, GetAtomEnd = { "band.SafeGetAtomEnd", band.SafeGetAtomEnd, }, GetResidueBase = { "band.SafeGetResidueBase", band.SafeGetResidueBase, }, GetResidueEnd = { "band.SafeGetResidueEnd", band.SafeGetResidueEnd, }, IsRecipeBand = { "band.SafeIsRecipeBand", band.SafeIsRecipeBand, }, SetClashImportance = { "behavior.SafeSetClashImportance", behavior.SafeSetClashImportance, }, SetBackboneHBondImportance = { "behavior.SafeSetBackboneHBondImportance", behavior.SafeSetBackboneHBondImportance, }, SetSidechainHBondImportance = { "behavior.SafeSetSidechainHBondImportance", behavior.SafeSetSidechainHBondImportance, }, SetDensityImportance = { "behavior.SafeSetDensityImportance", behavior.SafeSetDensityImportance, }, SetHidingImportance = { "behavior.SafeSetHidingImportance", behavior.SafeSetHidingImportance, }, SetPackingImportance = { "behavior.SafeSetPackingImportance", behavior.SafeSetPackingImportance, }, SetPairwiseImportance = { "behavior.SafeSetPairwiseImportance", behavior.SafeSetPairwiseImportance, }, IsContact = { "contactmap.SafeIsContact", contactmap.SafeIsContact, }, Freeze = { "freeze.SafeFreeze", freeze.SafeFreeze, }, IsFrozen = { "freeze.SafeIsFrozen", freeze.SafeIsFrozen, }, Unfreeze = { "freeze.SafeUnfreeze", freeze.SafeUnfreeze, }, MGetNames = { "metric.SafeGetNames", metric.SafeGetNames, }, MGetBonus= { "metric.SafeGetBonus", metric.SafeGetBonus, }, MGetBonusTotal= { "metric.SafeGetBonusTotal", metric.SafeGetBonusTotal, }, GetSolutions = { "save.SafeGetSolutions", save.SafeGetSolutions, }, LoadSolution = { "save.SafeLoadSolution", save.SafeLoadSolution, }, LoadSolutionByName = { "save.SafeLoadSolutionByName", save.SafeLoadSolutionByName, }, SaveSolution = { "save.SafeSaveSolution", save.SafeSaveSolution, }, SaveSecondaryStructure = { "save.SafeSaveSecondaryStructure", save.SafeSaveSecondaryStructure, }, LoadSecondaryStructure = { "save.SafeLoadSecondaryStructure", save.SafeLoadSecondaryStructure, }, Quicksave = { "save.SafeSaveQuicksave", save.SafeQuicksave, }, Quickload = { "save.SafeQuickload", save.SafeQuickload, }, QuicksaveEmpty = { "save.SafeSaveQuicksaveEmpty", save.SafeQuicksaveEmpty, }, GetCount = { "rotamer.SafeGetCount", rotamer.SafeGetCount, }, SetRotamer = { "rotamer.SafeSetRotamer", rotamer.SafeSetRotamer, }, Select = { "selection.SafeSelect", selection.SafeSelect, }, IsSelected = { "selection.SafeIsSelected", selection.SafeIsSelected, }, SelectRange = { "selection.SafeSelectRange", selection.SafeSelectRange, }, CanMutate = { "structure.SafeCanMutate", structure.SafeCanMutate, }, DeleteCut = { "structure.SafeDeleteCut", structure.SafeDeleteCut, }, DeleteResidue = { "structure.SafeDeleteResidue", structure.SafeDeleteResidue, }, GetAminoAcid = { "structure.SafeGetAminoAcid", structure.SafeGetAminoAcid, }, GetAtomCount = { "structure.SafeGetAtomCount", structure.SafeGetAtomCount, }, GetDistance = { "structure.SafeGetDistance", structure.SafeGetDistance, }, GetNote = { "structure.SafeGetNote", structure.SafeGetNote, }, GetSecondaryStructure = { "structure.SafeGetSecondaryStructure", structure.SafeGetSecondaryStructure, }, InsertCut = { "structure.SafeInsertCut", structure.SafeInsertCut, }, InsertResidue = { "structure.SafeInsertResidue", structure.SafeInsertResidue, }, IsHydrophobic = { "structure.SafeIsHydrophobic", structure.SafeIsHydrophobic, }, IsLocked = { "structure.SafeIsLocked", structure.SafeIsLocked, }, IsMutable = { "structure.SafeIsMutable", structure.SafeIsMutable, }, SetAminoAcid = { "structure.SafeSetAminoAcid", structure.SafeSetAminoAcid, }, SetAminoAcidSelected = { "structure.SafeSetAminoAcidSelected", structure.SafeSetAminoAcidSelected, }, SetNote = { "structure.SafeSetNote", structure.SafeSetNote, }, SetSecondaryStructure = { "structure.SafeSetSecondaryStructure", structure.SafeSetSecondaryStructure, }, SetSecondaryStructureSelected = { "structure.SafeSetSecondaryStructureSelected", structure.SafeSetSecondaryStructureSelected, }, } -- -- test table - one entry per test, grouped by function -- -- first column is a reference to the function table -- second column is the expected return code from the "safe" function -- third "column" is a table containing the arguments passed to the function -- local TESTFUNC = 1 -- function table entry local TESTEXRC = 2 -- expected return code local TESTARGZ = 3 -- argument array local TESTTYPE = 4 -- test type -- -- test types - intended to be bit flags, but Lua 5.1 doesn't support them -- TTPASSES = 0x01 -- expected to succeed TTSEGRNG = 0x02 -- segment range error TTPVALUE = 0x04 -- parameter value error TTARGCNT = 0x08 -- argument count error TTARGTYP = 0x10 -- argument type error TTCRASHY = 0x11 -- likely to cause a catastrophe -- -- band functions -- local bandtest = { { func.Add, -1, { 1, SEGMID, SEGOUT, OKRHO, OKTHETA, OKPHI }, TTSEGRNG, }, { func.Add, -4, { 1, SEGMID, segCnt, HIRHO, OKTHETA, OKPHI }, TTPVALUE, }, { func.Add, -4, { 1, SEGMID, segCnt, LORHO, OKTHETA, OKPHI }, TTPVALUE, }, { func.Add, -5, { 1, SEGMID, segCnt, OKRHO, HITHETA, OKPHI }, TTPVALUE, }, { func.Add, -5, { 1, SEGMID, segCnt, OKRHO, LOTHETA, OKPHI }, TTPVALUE, }, { func.Add, -6, { 1, SEGMID, segCnt, OKRHO, OKTHETA, HIPHI }, TTPVALUE, }, { func.Add, -6, { 1, SEGMID, segCnt, OKRHO, OKTHETA, LOPHI }, TTPVALUE, }, { func.AddBetweenSegments, -1, { 1, SEGOUT, }, TTSEGRNG, }, { func.AddBetweenSegments, -1, { SEGFOO1, segCnt, }, TTSEGRNG, }, { func.AddBetweenSegments, -1, { SEGFOO2, SEGFOO2 }, TTSEGRNG, }, { func.AddBetweenSegments, -997, { "foo", "bar", }, TTARGTYP, }, { func.AddBetweenSegments, -2, { 1, SEGMID, HIATOM, HIATOM }, TTPVALUE, }, { func.AddBetweenSegments, -3, { 1, 10, nil, nil, HISYM, }, TTPVALUE, }, { func.AddBetweenSegments, 0, { 1, 10, }, TTPASSES, },--used below { func.AddBetweenSegments, 0, { 2, 10, }, TTPASSES, },--used below { func.AddToBandEndpoint, 0, { 1, 1, }, TTPASSES, },--uses band { func.AddToBandEndpoint, -2, { 1, 1, HIATOM, }, TTPVALUE, },--uses band { func.AddToBandEndpoint, -1, { SEGFOO1, 1, }, TTSEGRNG, }, { func.AddToBandEndpoint, -3, { 5, 13, }, TTPVALUE, }, { func.AddToBandEndpoint, -1, { SEGFOO3, 1, }, TTSEGRNG, }, { func.AddToBandEndpoint, -997, { "foo", "bar", }, TTARGTYP, }, { func.Delete, 0, { 2, }, TTPASSES, },--uses band { func.Delete, -3, { HIBAND, }, TTPVALUE, }, { func.Delete, -3, { LOBAND, }, TTPVALUE, }, { func.Disable, 0, { 1, }, TTPASSES, },--uses band { func.Disable, -3, { HIBAND, }, TTPVALUE, }, { func.Disable, -3, { LOBAND, }, TTPVALUE, }, { func.GetGoalLength, 0, { 1, }, TTPASSES, },--uses band { func.GetGoalLength, -3, { HIBAND, }, TTPVALUE, }, { func.GetGoalLength, -3, { LOBAND, }, TTPVALUE, }, { func.GetLength, 0, { 1, }, TTPASSES, },--uses band { func.GetLength, -3, { HIBAND, }, TTPVALUE, }, { func.GetLength, -3, { LOBAND, }, TTPVALUE, }, { func.GetStrength, 0, { 1, }, TTPASSES, },--uses band { func.GetStrength, -3, { HIBAND, }, TTPVALUE, }, { func.GetStrength, -3, { LOBAND, }, TTPVALUE, }, { func.SetGoalLength, 0, { 1, 1, }, TTPASSES, },--uses band { func.SetGoalLength, -3, { HIBAND, 1, }, TTPVALUE, }, { func.SetGoalLength, -3, { LOBAND, 1, }, TTPVALUE, }, { func.SetGoalLength, -4, { 1, LNGBND, }, TTPVALUE, },--uses band { func.SetGoalLength, -4, { 1, SHRTBND, }, TTPVALUE, },--uses band { func.SetStrength, 0, { 1, 1, }, TTPASSES, },--uses band { func.SetStrength, -3, { HIBAND, 1, }, TTPVALUE, }, { func.SetStrength, -3, { LOBAND, 1, }, TTPVALUE, }, { func.SetStrength, -4, { 1, STRNGBND, }, TTPVALUE, },--uses band { func.SetStrength, -4, { 1, WEAKBND, }, TTPVALUE, },--uses band { func.GetAtomBase, -3, { HIBAND, }, TTPVALUE, }, { func.GetAtomBase, -3, { LOBAND, }, TTPVALUE, }, { func.GetAtomEnd, -3, { HIBAND, }, TTPVALUE, }, { func.GetAtomEnd, -3, { LOBAND, }, TTPVALUE, }, { func.GetResidueBase, -3, { HIBAND, }, TTPVALUE, }, { func.GetResidueBase, -3, { LOBAND, }, TTPVALUE, }, { func.GetResidueEnd, -3, { HIBAND, }, TTPVALUE, }, { func.GetResidueEnd, -3, { LOBAND, }, TTPVALUE, }, { func.IsRecipeBand, 0, { 1, }, TTPASSES, },--uses band { func.IsRecipeBand, -3, { HIBAND, }, TTPVALUE, }, { func.IsRecipeBand, -3, { LOBAND, }, TTPVALUE, }, } -- -- behavior functions -- local bhavtest = { { func.SetClashImportance, -997, { "foo", }, TTARGTYP, }, { func.SetClashImportance, -1, { -1, }, TTPVALUE, }, { func.SetClashImportance, -1, { SEGFOO3, }, TTPVALUE, }, { func.SetClashImportance, 0, { 1, }, TTPASSES, }, { func.SetClashImportance, -997, { "foo", }, TTARGTYP, }, { func.SetClashImportance, -1, { -1, }, TTPVALUE, }, { func.SetClashImportance, -1, { SEGFOO3, }, TTPVALUE, }, { func.SetClashImportance, 0, { 1, }, TTPASSES, }, { func.SetBackboneHBondImportance, 0, { 1, }, TTPASSES, }, { func.SetBackboneHBondImportance, -1, { -1, }, TTPVALUE, }, { func.SetBackboneHBondImportance, -1, { 99, }, TTPVALUE, }, { func.SetSidechainHBondImportance, 0, { 1, }, TTPASSES, }, { func.SetSidechainHBondImportance, -1, { -1, }, TTPVALUE, }, { func.SetSidechainHBondImportance, -1, { 99, }, TTPVALUE, }, { func.SetDensityImportance, 0, { 1, }, TTPASSES, }, { func.SetDensityImportance, -1, { -1, }, TTPVALUE, }, { func.SetDensityImportance, -1, { 99, }, TTPVALUE, }, { func.SetHidingImportance, 0, { 1, }, TTPASSES, }, { func.SetHidingImportance, -1, { -1, }, TTPVALUE, }, { func.SetHidingImportance, -1, { 99, }, TTPVALUE, }, { func.SetPackingImportance, 0, { 1, }, TTPASSES, }, { func.SetPackingImportance, -1, { -1, }, TTPVALUE, }, { func.SetPackingImportance, -1, { 99, }, TTPVALUE, }, { func.SetPairwiseImportance, 0, { 1, }, TTPASSES, }, { func.SetPairwiseImportance, -1, { -1, }, TTPVALUE, }, { func.SetPairwiseImportance, -1, { 99, }, TTPVALUE, }, } -- -- contactmap functions -- local conttest = { { func.IsContact, 0, { 1, segCnt, }, TTPASSES, }, { func.IsContact, -1, { 1, SEGOUT, }, TTSEGRNG, }, { func.IsContact, -1, { SEGFOO1, segCnt, }, TTSEGRNG, }, } -- -- freeze functions -- local frzetest = { { func.Freeze, 0, { 1, true, true, }, TTPASSES, }, { func.Freeze, -1, { SEGOUT, true, true, }, TTSEGRNG, }, { func.Freeze, -1, { SEGFOO1, true, true, }, TTSEGRNG, }, { func.Freeze, -998, { 1, true, }, TTARGCNT, }, { func.Freeze, -998, { 1, true, }, TTARGCNT, }, { func.IsFrozen, 0, { 1, }, TTPASSES, }, { func.IsFrozen, -1, { SEGOUT, }, TTSEGRNG, }, { func.IsFrozen, -1, { SEGFOO1, }, TTSEGRNG, }, { func.Unfreeze, 0, { 1, true, true, }, TTPASSES, }, { func.Unfreeze, -1, { SEGOUT, true, true, }, TTSEGRNG, }, { func.Unfreeze, -1, { SEGFOO1, true, true, }, TTSEGRNG, }, { func.Unfreeze, -998, { 1, true, }, TTARGCNT, }, { func.Unfreeze, -998, { 1, true, }, TTARGCNT, }, } -- -- metric functions -- local metrtest = { { func.MGetNames, 0, { }, TTPASSES, }, { func.MGetBonusTotal, 0, { }, TTPASSES, }, { func.MGetBonus, -1, { "nonesuch" }, TTPVALUE, }, } -- -- rotamer functions -- local rotatest = { { func.GetCount, 0, { 1, }, TTPASSES, }, { func.GetCount, -1, { SEGOUT, }, TTSEGRNG, }, { func.GetCount, -1, { SEGFOO1, }, TTSEGRNG, }, { func.SetRotamer, -2, { 1, HIROTA, }, TTPVALUE, }, { func.SetRotamer, -1, { SEGFOO1, 1 }, TTSEGRNG, }, { func.SetRotamer, -1, { SEGFOO1, HIROTA, }, TTSEGRNG, }, } -- -- save functions -- local savetest = { { func.GetSolutions, 0, { }, TTPASSES, }, { func.LoadSolution, -997, { "nonesuch" }, TTPVALUE, }, { func.LoadSolutionByName, -1, { "nonesuch" }, TTCRASHY, }, { func.SaveSolution, 0, { "nonesuch" }, TTPASSES, }, { func.SaveSecondaryStructure, 0, { }, TTPASSES, }, { func.LoadSecondaryStructure, 0, { }, TTPASSES, }, { func.Quicksave, 0, { 99 }, TTPASSES, }, { func.Quicksave, -999, { -999 }, TTPVALUE, }, { func.Quicksave, -999, { 0 }, TTPVALUE, }, { func.Quicksave, -999, { 999 }, TTPVALUE, }, { func.Quickload, 0, { 99 }, TTPASSES, }, { func.Quickload, -999, { -999 }, TTPVALUE, }, { func.Quickload, -999, { 0 }, TTPVALUE, }, { func.Quickload, -999, { 999 }, TTPVALUE, }, { func.QuicksaveEmpty, 0, { 99 }, TTPASSES, }, { func.QuicksaveEmpty, -999, { -999 }, TTPVALUE, }, { func.QuicksaveEmpty, -999, { 0 }, TTPVALUE, }, { func.QuicksaveEmpty, -999, { 999 }, TTPVALUE, }, } -- -- selection functions -- local seletest = { { func.IsSelected, -997, { "foo", }, TTARGTYP, }, { func.IsSelected, -1, { -1, }, TTSEGRNG, }, { func.IsSelected, -1, { SEGFOO3, }, TTSEGRNG, }, { func.IsSelected, -1, { SEGOUT, }, TTSEGRNG, }, { func.Select, -997, { "foo", }, TTARGTYP, }, { func.Select, -1, { -1, }, TTSEGRNG, }, { func.Select, -1, { SEGFOO3, }, TTSEGRNG, }, { func.Select, -1, { SEGOUT, }, TTSEGRNG, }, -- { func.Select, -997, { "next error OK" }, TTARGTYP, },--test error -- { func.Select, 0, { 1, 777, }, TTSEGRNG, },--test error -- { func.Select, -997, { "prev error OK" }, TTARGTYP, },--test error { func.SelectRange, -1, { 1, SEGOUT, }, TTSEGRNG, }, { func.SelectRange, -1, { SEGFOO1, segCnt }, TTSEGRNG, }, { func.SelectRange, -1, { SEGFOO2, SEGFOO2 }, TTSEGRNG, }, { func.SelectRange, -998, { 1, SEGMID, 999 }, TTARGCNT, }, } -- -- structure functions -- local strutest = { { func.CanMutate, -1, { SEGOUT, "a", }, TTSEGRNG, }, { func.CanMutate, -1, { SEGFOO1, "a", }, TTSEGRNG, }, { func.CanMutate, 0, { 1, "a", }, TTPASSES, }, { func.CanMutate, -2, { 1, "x", }, TTARGVAL, }, { func.DeleteCut, -1, { SEGOUT, }, TTSEGRNG, }, { func.DeleteCut, -1, { SEGFOO1, }, TTSEGRNG, }, { func.DeleteResidue, -1, { SEGOUT, }, TTSEGRNG, }, { func.DeleteResidue, -1, { SEGFOO1, }, TTCRASHY, }, { func.GetAminoAcid, -1, { SEGOUT, }, TTSEGRNG, }, { func.GetAminoAcid, -1, { SEGFOO1, }, TTSEGRNG, }, { func.GetAtomCount, -1, { SEGOUT, }, TTSEGRNG, }, { func.GetAtomCount, -1, { SEGFOO1, }, TTSEGRNG, }, { func.GetDistance, -1, { 1, SEGOUT, }, TTSEGRNG, }, { func.GetDistance, -1, { 1, SEGFOO1, }, TTSEGRNG, }, { func.GetDistance, -1, { SEGFOO1, 10, }, TTSEGRNG, }, { func.GetDistance, -1, { SEGOUT, 10, }, TTSEGRNG, }, { func.GetNote, -1, { SEGOUT, }, TTSEGRNG, }, { func.GetNote, -1, { SEGFOO1, }, TTSEGRNG, }, { func.GetSecondaryStructure, -1, { SEGOUT, }, TTSEGRNG, }, { func.GetSecondaryStructure, -1, { SEGFOO1, }, TTSEGRNG, }, { func.InsertCut, -1, { SEGOUT, }, TTSEGRNG, }, { func.InsertCut, -1, { SEGFOO1, }, TTSEGRNG, }, { func.InsertResidue, -1, { SEGOUT, }, TTSEGRNG, }, { func.InsertResidue, -1, { SEGFOO1, }, TTSEGRNG, }, { func.IsHydrophobic, -1, { SEGOUT, }, TTSEGRNG, }, { func.IsHydrophobic, -1, { SEGFOO1, }, TTSEGRNG, }, { func.IsLocked, -1, { SEGOUT, }, TTSEGRNG, }, { func.IsLocked, -1, { SEGFOO1, }, TTSEGRNG, }, { func.IsMutable, -1, { SEGOUT, }, TTSEGRNG, }, { func.IsMutable, -1, { SEGFOO1, }, TTSEGRNG, }, { func.SetAminoAcid, -2, { 1, "b", }, TTPVALUE, }, { func.SetAminoAcid, -1, { -1, "a", }, TTSEGRNG, }, { func.SetAminoAcid, -2, { 1, "b", }, TTARGVAL, }, { func.SetAminoAcidSelected, 0, { "a", }, TTPASSES, }, { func.SetAminoAcidSelected, -2, { "b", }, TTARGVAL, }, { func.SetNote, -1, { SEGOUT, "test note", }, TTSEGRNG, }, { func.SetNote, -1, { SEGFOO1, "test note", }, TTSEGRNG, }, { func.SetNote, -998, { 1, }, TTARGCNT, }, { func.SetNote, 0, { 1, "test note", }, TTPASSES, }, { func.SetSecondaryStructure, -2, { 1, "R", }, TTPVALUE, }, { func.SetSecondaryStructure, -1, { SEGFOO1, "X", }, TTSEGRNG, }, { func.SetSecondaryStructure, -1, { SEGFOO1, "L", }, TTSEGRNG, }, { func.SetSecondaryStructureSelected, -2, { "R", }, TTSEGRNG, }, { func.SetSecondaryStructureSelected, -2, { "X", }, TTPVALUE, }, { func.SetSecondaryStructureSelected, 0, { "L", }, TTPASSES, }, } local GPARM = 1 local GNAME = 2 local GDOIT = 3 local testgrpz = { { bandtest, "band", false, }, { bhavtest, "behavior", false, }, { conttest, "contactmap", false, }, { frzetest, "freeze", false, }, { metrtest, "metric", false, }, { rotatest, "rotamer", false, }, { savetest, "save", false, }, { seletest, "selection", false, }, { strutest, "structure", false, }, } -- -- inline dialog! -- local ask = dialog.CreateDialog ( ReVersion ) ask.l001 = dialog.AddLabel ( "Select the type of tests to run:" ) ask.ttpasses = dialog.AddCheckbox ( "expected to pass", opts.ttpasses ) ask.ttsegrng = dialog.AddCheckbox ( "segment range errors", opts.ttsegrng ) ask.ttpvalue = dialog.AddCheckbox ( "parameter value errors", opts.ttpvalue ) ask.ttargcnt = dialog.AddCheckbox ( "parameter count errors", opts.ttargcnt ) ask.ttargtyp = dialog.AddCheckbox ( "parameter type errors", opts.ttargtyp ) ask.ttcrashy = dialog.AddCheckbox ( "may crash Foldit", opts.ttcrashy ) ask.l005 = dialog.AddLabel ( "" ) ask.l006 = dialog.AddLabel ( "Test functions in all Foldit function groups:" ) ask.runall = dialog.AddCheckbox ( "all groups", opts.runall ) ask.l010 = dialog.AddLabel ( "or, select which groups to test:" ) for ii = 1, #testgrpz do ask [ testgrpz [ ii ] [ GNAME ] ] = dialog.AddCheckbox ( testgrpz [ ii ] [ GNAME ], testgrpz [ ii ] [ GDOIT ] ) end ask.OK = dialog.AddButton ( "OK", 1 ) ask.cancel = dialog.AddButton ( "Cancel", -1 ) local askrc = dialog.Show ( ask ) local grpcnt = 0 if askrc > 0 then opts.ttpasses = ask.ttpasses.value opts.ttsegrng = ask.ttsegrng.value opts.ttpvalue = ask.ttpvalue.value opts.ttargcnt = ask.ttargcnt.value opts.ttargtyp = ask.ttargtyp.value opts.ttcrashy = ask.ttcrashy.value -- -- see which groups were selected, if any -- for ii = 1, #testgrpz do testgrpz [ ii ] [ GDOIT ] = ask [ testgrpz [ ii ] [ GNAME ] ].value if testgrpz [ ii ] [ GDOIT ] then grpcnt = grpcnt + 1 end end -- -- if "run all" selected, but also one or more groups, -- run only the selected groups -- opts.runall = ask.runall.value if opts.runall and grpcnt == 0 then grpcnt = 0 for ii = 1, #testgrpz do testgrpz [ ii ] [ GDOIT ] = true grpcnt = grpcnt + 1 end end else cleanup () return end if opts.ttpasses then print ( "running test where the function should succeed" ) end if opts.ttsegrng then print ( "running tests for segment range errors" ) end if opts.ttpvalue then print ( "running tests for invalid parameter value errors" ) end if opts.ttargcnt then print ( "running tests for invalid parameter count errors" ) end if opts.ttargtyp then print ( "running tests for invalid parameter type errors" ) end if opts.ttcrashy then print ( "running tests for invalid parameter type errors" ) end print ( "" ) print ( grpcnt .. " groups selected" ) if grpcnt == 0 then print ( "no tests selected, cleaning up" ) cleanup () end print ( "--" ) -- -- all this inline too! maybe we need a function or two! -- local totlruns = 0 local totlfailz = 0 local totlfuns = 0 local totlskipz = 0 for gg = 1, #testgrpz do if testgrpz [ gg ] [ GDOIT ] then print ( "-----------------------------------------" ) print ( "testing functions in the " .. testgrpz [ gg ] [ GNAME ] .. " group" ) local lastfun = nil local testruns = 0 local testfailz = 0 local testfuns = 0 local testskipz = 0 local testtabl = testgrpz [ gg ] [ GPARM ] for tt = 1, #testtabl do local ttp = testtabl [ tt ] [ TESTTYPE ] if ( opts.ttpasses and ( ttp == TTPASSES ) ) or ( opts.ttsegrng and ( ttp == TTSEGRNG ) ) or ( opts.ttpvalue and ( ttp == TTPVALUE ) ) or ( opts.ttargcnt and ( ttp == TTARGCNT ) ) or ( opts.ttargtyp and ( ttp == TTARGTYP ) ) or ( opts.ttcrashy and ( ttp == TTCRASHY ) ) then testruns = testruns + 1 if testtabl [ tt ] [ TESTFUNC ] ~= lastfun then testfuns = testfuns + 1 lastfun = testtabl [ tt ] [ TESTFUNC ] print ( "-----------------------------------------" ) end if ttp == TTCRASHY then print ( "WARNING: this test may crash Foldit" ) end local argz = testtabl [ tt ] [ TESTARGZ ] local calltext -- -- format a description of the function call -- calltext = lastfun [ FUNCNAME ] .. " ( " for ii = 1, #argz do local argtext if type ( argz [ ii ] ) == "string" then argtext = "\"" .. argz [ ii ] .. "\"" else argtext = tostring ( argz [ ii ] ) end if ii > 1 then calltext = calltext .. ", " end calltext = calltext .. argtext end calltext = calltext .. " )" -- -- call the function -- --[[ local ask = dialog.CreateDialog ( ReVersion ) ask.testnum = dialog.AddLabel ( "test # " .. tt ) ask.calltext = dialog.AddTextbox ( "next: ", calltext ) structure.SetNote ( 1, "next test: " .. tt .. " - " .. calltext ) ask.OK = dialog.AddButton ( "OK", 1 ) dialog.Show ( ask ) ]]-- print ( "test # " .. tt .. ": calling " .. calltext ) local rc, errmsg rc, errmsg = lastfun [ FUNCCALL ] ( unpack ( argz ) ) -- -- report the results -- calltext = calltext .. ", rc = " .. rc if rc < 0 and errmsg ~= nil then calltext = calltext .. ", errmsg = \"" .. errmsg .. "\"" end print ( calltext ) if rc ~= testtabl [ tt ] [ TESTEXRC ] then testfailz = testfailz + 1 if rc == 0 then print ( "ERROR: unexpected rc = 0" ) else print ( "ERROR: unexpected rc = " .. rc .. ", errmsg = \"" .. errmsg .. "\"" ) end end else testskipz = testskipz + 1 end end -- print ( "-----------------------------------------" ) print ( "" ) print ( testgrpz [ gg ] [ GNAME ] .. " tests complete" ) print ( ) print ( testfuns .. " functions tested in " .. testgrpz [ gg ] [ GNAME ] .. " group" ) print ( testruns .. " tests run" ) print ( testfailz .. " test failures" ) print ( testskipz .. " tests skipped based on type" ) totlfuns = totlfuns + testfuns totlruns = totlruns + testruns totlfailz = totlfailz + testfailz totlskipz = totlskipz + testskipz -- end end print ( "-----------------------------------------" ) print ( "" ) print ( "all tests complete" ) print ( totlfuns .. " functions tested in " .. grpcnt .. " groups" ) print ( totlruns .. " total tests run" ) print ( totlfailz .. " test failures" ) print ( totlskipz .. " tests skipped based on type" ) cleanup () end function cleanup ( errmsg ) print ( "---" ) -- -- model 100 - print recipe name, puzzle, track, time, score, and gain -- local reason local start, stop, line, msg if errmsg == nil then reason = "complete" else -- -- model 120 - civilized error reporting, -- thanks to Bruno K. and Jean-Bob -- start, stop, line, msg = errmsg:find ( ":(%d+):%s()" ) if msg ~= nil then errmsg = errmsg:sub ( msg, #errmsg ) end if errmsg:find ( "Cancelled" ) ~= nil then reason = "cancelled" else reason = "error" end end print ( ReVersion .. " " .. reason ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) if reason == "error" then print ( "Unexpected error detected" ) if line ~= nil then print ( "Error line: " .. line ) end print ( "Error: \"" .. errmsg .. "\"" ) end -- -- model 130 - reset clash importance, clear selections, restore structures, etc. -- save.Quickload ( 3 ) save.LoadSecondaryStructure () selection.DeselectAll () behavior.SetClashImportance ( 1.0 ) band.DeleteAll () end -- main call xpcall ( main, cleanup ) --end of script

Comments


LociOiling Lv 1

This version adds testing the new "metric" functions, and also the "save" functions, both old and somewhat new.

See the comments for previous versions for more details.

There's now a "crashy" type of test, for something which is known to crash or hang Foldit. This test type is not selected by default.

The logic for selecting groups of functions has changed, so it's more like radio buttons*. Now if "select all" is checked, but you then select "save", "select all" is cleared, and only the "save" functions are tested.

There are still many functions which aren't tested.

Bruno Kestemont Lv 1

Even if it crashed the client after some time on 1929 ;)

test # 23: calling structure.SafeInsertResidue ( 189 )
structure.SafeInsertResidue ( 189 ), rc = 0
ERROR: unexpected rc = 0
test # 24: calling structure.SafeInsertResidue ( -1 )