Tests-PrimCallController

PCCByCompilation
This class is for switching external prim calls (primitiveExternalCall) on and off.
It is best suited for permanently switching plugin calls off while preserving the possibility to switch them on later. For plugin testing purposes you probably should use PCCByLiterals for temporarily switch on/off them instead.
It works on a source code basis by compilation:
Disabling works by putting an enabled prim call into a special comment followed by a recompile to transform it into a disabled one.
Enabling works by pulling the disabled prim call out of the special comment followed by a recompile to transform it into an enabled one.
As a consequence, enabling of prims only works with method sources containing the mentioned special comment, which normally has been generated by this tool for disabling the corresponding prim.
Please look into superclass PrimCallControllerAbstract for more info and the user interface.
Structure:
No instVars here: look into superclass.
Implementation note:
To harden it for sunit testing purposes some special accessing of the source code has been necessary: to avoid accessing different processes a sources file at once, followed by generating garbage, the process priority of actions leading to these accesses has been increased (sunit tests run in the background). A better solution would be to introduce a source file locking mechanism.
comment
disabled2EnabledPrimMethodString:
disabled2EnabledPrimString:
remove comment quotes and comment after first comment quote
disabledPrimStartString
disabledPrimStopChar
end of disabling comment
enabled2DisabledPrimMethodString:
enabled2DisabledPrimString:
enabledPrimStartString
enabledPrimStopChar
existsCallIn:
Here existsCompiledCallIn: (see also comment there) is sufficient to
query for enabled and failed, but not for disabled prim calls: so check
for disabled ones in sources, too.
existsDisabledCallIn:
extractCallModuleNames:
Returns prim call and module name as call->module Association.
extractCallNamesFromPrimString:
method works for both enabled and disabled prim strings
extractDisabledPrimStringFrom:
extractEnabledPrimStringFrom:
higherPriority
this priority seems to be necessary to avoid source file accessing errors
methodSourceContainsDisabledCall:
methodsWithCall
Expensive! For just querying the system unaffected by an instance of
this class use PCCByLiterals instead.
methodsWithDisabledCall
Answer a SortedCollection of all the methods that contain, in source
code, the substring indicating a disabled prim.
privateDisableCallIn:
Disables enabled or failed external prim call by recompiling method
with prim call commented out, will be called by superclass.
privateEnableCallIn:
Enables disabled external prim call by recompiling method with prim
call taken from disabling comment, will be called by superclass.
PCCByCompilationTest
PCCByCompilation tests.
Tests are in the superclass and inherited from there.
cDisabledExternalCallWithoutModule
{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName'>
cDisabledRealExternalCall
{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>
cDisabledRealExternalCallNaked
{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>
cDisabledRealExternalCallOrPrimitiveFailed
{prim disabled by PCCByCompilation} <primitive: 'primGetModuleName' module:'LargeIntegers'>
cExternalCall1
cExternalCall2
cExternalCallWithoutModule
cFailedCall
cNoExternalCall
cRealExternalCall
cRealExternalCallNaked
cRealExternalCallOrPrimitiveFailed
cSingularExternalCall
classToBeTested
disabledCallSelectors
enabledCallSelectors
exampleModuleName
failModuleName
failedCallSelector
isAbstract
methodSelectorsToExampleModule
moduleNameNotWithSingularCallName
moduleNameWithSingularCallName
noExternalCallSelector
realExternalCallOrPrimitiveFailedSelector
singularCallName
occurrs exactly once as prim call name in >>cSingularExternalCall
singularCallSelector
PCCByLiterals
This class is for switching external prim calls (primitiveExternalCall) on and off.
It is best suited for plugin testing purposes with temporarily switching plugin calls off and on. For permanently switching plugin calls off while preserving the possibility to switch them on later, you should use PCCByCompilation instead.
It works by manipulating literals in the CompiledMethods:
Disabling works by changing the function index in the first literal of the CompiledMethod to a negative value (-2). This leads to a fast fail (value -2 is used for disabling to make a difference to the standard failed value of -1).
Enabling works by changing the function index in the first literal of the CompiledMethod to 0, followed by flushing the method cache. This enforces a fresh lookup.
Please look into superclass PrimCallControllerAbstract for more info and the user interface.
Structure:
No instVars here: look into superclass.
existsCallIn:
Here >>existsCompiledCallIn: (see also comment there) is sufficient to
query for all enabled, failed and disabled prim calls; for the by
compiler version it is not sufficient for disabled ones.
existsDisabledCallIn:
extractCallModuleNames:
Returns prim call and module name as call->module Association.
methodsWithCall
Returns all methods containing external prim calls.
methodsWithDisabledCall
Returns all methods containing disabled external prim calls.
privateDisableCallIn:
Disables enabled or failed external prim call by filling function ref
literal with special fail value, will be called by superclass.
privateEnableCallIn:
Enables disabled external prim call.
PCCByLiteralsTest
PCCByLiterals tests.
Tests are in the superclass and inherited from there.
classToBeTested
disabledCallSelectors
enabledCallSelectors
exampleModuleName
failModuleName
failedCallSelector
isAbstract
lDisabledExternalCallWithoutModule
lDisabledRealExternalCall
lDisabledRealExternalCallNaked
lDisabledRealExternalCallOrPrimitiveFailed
primitiveExternalCall
lExternalCall1
lExternalCall2
lExternalCallWithoutModule
primitiveExternalCall
lFailedCall
lNoExternalCall
lRealExternalCall
lRealExternalCallNaked
lRealExternalCallOrPrimitiveFailed
lSingularExternalCall
methodSelectorsToExampleModule
moduleNameNotWithSingularCallName
moduleNameWithSingularCallName
noExternalCallSelector
realExternalCallOrPrimitiveFailedSelector
setUp
singularCallName
occurrs exactly once as prim call name in >>lSingularExternalCall
singularCallSelector
PrimCallControllerAbstract
A PrimCallController (PCC) serves for switching external prim calls (primitiveExternalCall) on and off: this is an abstract class, instantiate one of the subclasses PCCByLiterals and PCCByCompilation.
External prim calls are used to access internal and external modules (plugins) as shown by
SmalltalkImage current listLoadedModules.
SmalltalkImage current listBuiltinModules.
Note: not loaded external modules (since they have not been called so far) are not shown by these methods.
Highlight: dis/en-abling prims by a PCC works for both internal and external modules!
To help you choosing the right subclass, some properties are listed in the following table:
Functionality/Property | PCCByLiterals PCCByCompilation
------------------------------------------------------------------------------------------------------
testing plugins | suited not suited
permanent disabling of external prim calls | no yes
------------------------------------------------------------------------------------------------------
method changes visible in changeset | no yes
enabling survives snapshot/compilation | yes yes
disabling survives snapshot/compilation | no yes
speed disabling | fast medium
speed enabling | fast slow
CompiledMethod pointer valid after en/dis-abling | yes no

Important: Be careful with mixing the use of different PCCs! PCCByLiterals does not see prims disabled by PCCByCompilation and vice versa. For playing around you should start with PCCByLiterals; use PCCByCompilation only, if you know what you are doing!
In protocols 'ui controlling', 'ui logging' and 'ui querying' (please look into this class) are the most important user interface methods. Thereafter the methods in 'ui testing' could be of interest.
Useful expressions:
Controlling:
"Factorial example"
| pcc tDisabled tEnabled tEnabled2 |
pcc _ PCCByLiterals new logStream: Transcript. "logStream set here for more info"
pcc disableCallsIntoModule: 'LargeIntegers'.
tDisabled _ [1000 factorial] timeToRun.
pcc enableDisabled.
tEnabled _ [1000 factorial] timeToRun.
tEnabled2 _ [1000 factorial] timeToRun.
{tDisabled. tEnabled. tEnabled2}
Note: You shouldn't switch off module 'LargeIntegers' for a longer time, since this slows down your system.
Querying:
PCCByLiterals new methodsWithCall. "all calls"
PCCByLiterals new methodsWithCall: 'prim1'. "call in all modules or without module"
PCCByLiterals new methodsWithCallIntoModule: nil. "all calls without module"
PCCByLiterals new methodsWithCallIntoModule: 'LargeIntegers'. "all calls into module 'LargeIntegers'"
PCCByLiterals new
methodsWithCallIntoModule: 'LargeIntegers'
forClass: Integer. "all calls into module 'LargeIntegers' in class Integer"
PCCByLiterals new
methodsWithCallIntoModule: 'LargeIntegers'
forClasses: Integer withAllSubclasses. "all calls into module 'LargeIntegers' in class Integer withAllSubclasses"
| pcc | (pcc _ PCCByLiterals new) methodsWithCall
collect: [:mRef | {mRef. pcc extractCallModuleNames: mRef}].
Structure:
treatedMethods Dictionary of MethodReferences->#disabled/#enabled
-- contains changed methods and how they are changed last
logStream WriteStream -- shows info about changed methods ifNotNil
changeStatusOfFailedCalls Boolean -- if status of failed calls should be changed, default is false
blockSelectCallName:
blockSelectFailedCall
Precondition: mRef references compiledCall.
blockSelectModuleName:
changeCallCompiledMethod:enable:
Enables disabled or disables enabled external prim call by recompiling
method with prim call taken from comment.
changeCallMethod:class:enable:
Enables disabled or disables enabled external prim call by recompiling
method with prim call taken from comment.
changeStatusOfFailedCalls
En/dis-able not only dis/en-abled calls, but also failed ones. Using this
feature can hide serious problems.
changeStatusOfFailedCallsFlag
disableCallIn:
Disables enabled external prim call.
disableCallInCompiledMethod:
Disables external prim call.
disableCallInMethod:class:
Disables external prim call.
disableCallsIntoModule:
Disables enabled external prim calls in aModule.
disableCallsIntoModule:forClasses:
Disables enabled external prim calls in aModule for classes.
disableEnabled
Disables these external prim calls, which are formerly enabled by self.
enableCallIn:
Enables disabled external prim call.
enableCallInCompiledMethod:
Enables disabled external prim call.
enableCallInMethod:class:
Enables disabled external prim call.
enableCallsIntoModule:
Enables disabled external prim calls in aModule.
enableCallsIntoModule:forClasses:
Enables disabled external prim calls in aModule for classes.
enableDisabled
Enables these external prim calls, which are formerly disabled by self.
existsCallIn:
existsCompiledCallIn:
This just means that there is a compiled in external prim call: from the
by compiler subclass point of view disabled prim calls not visible by
this method are also prim calls.
existsDisabledCallIn:
existsEnabledCallIn:
existsFailedCallIn:
extractCallModuleNames:
Returns prim call and module name as call->module Association.
extractCallModuleNamesFromLiterals:
initialize
Subclasses should redefine this method to perform initializations on instance creation
log:
logStream
logStream:
If aStreamOrNil is notNil, there will be shown dis/en-abling prim call
info; nil means no logging.
methodsWithCall
Returns all methods containing external prim calls.
methodsWithCall:
methodsWithCall:enabled:
methodsWithCall:intoModule:
methodsWithCall:intoModule:enabled:
methodsWithCallEnabled:
methodsWithCallForClass:enabled:
methodsWithCallForClasses:enabled:
methodsWithCallIntoModule:
methodsWithCallIntoModule:enabled:
methodsWithCallIntoModule:forClass:
methodsWithCallIntoModule:forClasses:
methodsWithCallIntoModule:forClasses:enabled:
methodsWithCompiledCall
Returns all methods containing compiled in external prim calls.
If the by compilation subclass has disabled some, this method does *not*
return all methods containing prim calls (use >>methodsWithCall in this
case).
methodsWithDisabledCall
Returns all methods containing disabled external prim calls.
methodsWithDisabledCall:
methodsWithDisabledCall:intoModule:
methodsWithDisabledCallIntoModule:
methodsWithDisabledCallIntoModule:forClass:
methodsWithDisabledCallIntoModule:forClasses:
methodsWithEnabledCall
Returns all methods containing enabled external prim calls.
methodsWithEnabledCall:
methodsWithEnabledCall:intoModule:
methodsWithEnabledCallIntoModule:
methodsWithEnabledCallIntoModule:forClass:
methodsWithEnabledCallIntoModule:forClasses:
methodsWithFailedCall
Returns all methods containing failed external prim calls.
methodsWithFailedCallForClass:
methodsWithFailedCallForClasses:
methodsWithFailedCallIntoModule:
methodsWithFailedCallIntoModule:forClass:
methodsWithFailedCallIntoModule:forClasses:
preserveStatusOfFailedCalls
Do not en/dis-able failed calls (default).
privateDisableCallIn:
Disables enabled or failed external prim call.
privateEnableCallIn:
Enables disabled external prim call.
privateEnableViaLiteralIn:
Enables external prim call by filling function ref literal with zero for
'non called'.
switchStored
Disables enabled and enables disabled (see corresponding method
comments).
treatedMethods
PrimCallControllerAbstractTest
PrimCallController tests.
Tests are here, but this class isAbstract and won't be tested.
Tests are done in the subclasses, which inherit the tests here.
If you want to perform some more very slow tests, change doNotMakeSlowTestsFlag in >>setUp.
avoidSlowTest
compiledMethodsToExampleModule
disabledCallRefs
enabledCallRefs
failedCallRef
isAbstract
methodRefsToExampleModule
noExternalCallRef
numOfCallsExampleModule
setUp
singularCallRef
testChangeFailedCallFailing
testChangeFailedCallSucceedingDisable
testChangeFailedCallSucceedingEnable
testDisableCallsIntoModule
wrong module
testDisableCallsIntoModuleForClasses
wrong module
testEnableCallsIntoModule
testEnableCallsIntoModuleForClasses
wrong module
testEnableDisableCallIn
testEnableDisableCallInCompiledMethod
Note: >>compiledMethodsToExampleModule has to be called frequently,
since the CMs are changing with a successful compile!
testEnableDisableCallInMethodClass
testExistsCallIn
testExistsDisabledCallIn
testExistsEnabledCallIn
testExistsFailedCallIn
testMethodsWithCallAndMethodsWithDisabledCall
testMethodsWithCallIntoModule
testMethodsWithCallIntoModuleForClass
precondition: all enabled
testMethodsWithCallIntoModuleForClasses
precondition: all enabled
testMethodsWithCallX
testMethodsWithCallXIntoModule
testMethodsWithDisabledCallIntoModule
testMethodsWithDisabledCallIntoModuleForClass
precondition: all enabled
testMethodsWithDisabledCallIntoModuleForClasses
precondition: all enabled
testMethodsWithDisabledCallX
testMethodsWithDisabledCallXIntoModule
precondition: all enabled
testMethodsWithEnabledCall
testMethodsWithEnabledCallIntoModule
testMethodsWithEnabledCallIntoModuleForClass
precondition: all enabled
testMethodsWithEnabledCallIntoModuleForClasses
precondition: all enabled
testMethodsWithEnabledCallX
testMethodsWithEnabledCallXIntoModule
precondition: all enabled
testMethodsWithFailedCall
testMethodsWithFailedCallForClass
testMethodsWithFailedCallIntoModule
testMethodsWithFailedCallIntoModuleForClass
testSwitchPrimCallOffOn
testSwitchStored
all enabled, precondition
testTryCaches
all enabled, precondition
wrongCallRef
wrongClassRef