The law tester is a light off-line tool intended to help the debugging of laws during the development process. The deployment and execution of a law takes place in every controller on behalf of every agent part of the community defined by that law. This deployment scheme renders the process of debugging and testing difficult. The law tester addresses exactly this issue: it provides for the execution and debugging of a law as part of a stand-alone program. The law tester covers two aspects:
The law tester is designed as an interactive tool that receives commands from the standard input. There are two steps involved in running the tester: 1) the loading of the law, and 2)the dynamic evaluation of events. The rest of this document presents this two steps.
In order to start the law tester, obtain a console and issue the following command:
>java moses.Tester Please input the law file name with path (or URL):
Upon starting, the law tester waits fort the user to input the destination law file. This can be either an URL or a local file.
Any LGI law has two parts, the preamble and the body. The preamble
which is language independent is checked first upon loading.
Whenever a syntax error occurs, its location is reported to the
user. An example of such error, when encountered in an
alias declaration is reported as follows:
Error in Preambles: cannot understand the alias declaration: alias(,a@research.rutgers) -- Cannot successfully prepare the law, due to: preamble failure Please input the law file name with path (or URL):
After the preamble, the body of the law is validated. This step is language dependent. In the case of Java laws, the body of the law is compiled. In the case of Prolog laws, a Prolog engine consults the law. During this step, if any syntax error is encountered, it will be reported along with its location. Due to the different characteristics of the interpretor, there are slight differences between Java and Prolog laws: In the case of java laws, whenevar an error is reported, the tester demands for the user to correct the law and reload it:
Error information -- Cannot successfully load the law, due to: compilation failure Please input the law file name with path (or URL):
In the case of Prolog, the laws can still be loaded even in the presence of
errors (due to the nature of the interpretor, certain rules can be
evaluated, independent of the presence of other faulty rules).
An example of output for a faulty Prolog law follows.:
Error and warning information -- Do you want to accept this law? -- Press enter or "yes" to accept, "no" to try another law: no Please input the law file name with path (or URL):
When a syntactically correct law is loaded, the following message is displayed:
-- Successfully loaded the law
Note that laws are massaged for the testing purpose, prior to beeing loaded by the intepretor (see the moses manual for details of this).
After a law is loaded, various events can be submitted to
evaluation. This evaluation, however is performed in a certain
context. This context can be defined by specifying the following
environment variables: CS, DCS, Peer, PeerHash, RList, AList,
Self, ThisLawName, ThisLawHash . These variables are taken
from a file as follows:
Please input the configuration file name with path: (Press enter to skip this step, setting the context to its default value) ConfigurationFileName
Each entry in the file is a pair context(variable name,variable value).
An example of content of a configuration file is:
context(Self,a@mco.rutgers.edu) context(CS,[budget(budget(3)),position(client),ticket(1),time(100)]) context(DCS,[authority(myCA)]) context(ThisLawName,testlaw) context(Peer,e@time.net) context(PeerHash,122222222)
The configuration file can be updated and reloaded at any time during
the testing session.
If no configuration file is specified, the system will automatically
set the context variables to their default values. Certain variables
in the context cannot be manually set: Msg, SubjectHash and
Clock . Variable Clock is adjusted based on the system current
time, while the others are event dependent.
In order to discover runtime errors, a user should be able to interact with the tester by submitting events at the command line:
New Event: (!h for help):
The events are defined by their names, and their parameters. After an event is evaluated in a given context, a list of primitive operations is returned.
In order to test the event
sent(String source , String msg, String dest, String law),
a user has to provide an input similar to the following:
Evaluate the event: sent(x@aol.com,somemessage,y@yahoo.com,thislaw) With the control state [] The operations are: doForward() The new control state is : []
By examining the operations returned, the user can judge if the
evaluation parforms according to the desired model.
If there are operations manipulating the control state, the control
state is updated accordingly:
New Event: (!h for help):sent(source,addstring(budget(1)),dest,law) Evaluate the event: sent(source,addstring(budget(1)),dest,law) With the control state [] The operations are: doAdd(budget(1)) The new control state is : [budget(1)]
When the user provides an event that does not match any of the LGI events, the tester will provide the following message to the user:
New Event: (!h for help):sent(x@aol.com,somemessage,y@yahoo.com) Evaluate the event: sent(x@aol.com,somemessage,y@yahoo.com) With the control state [] The operations are: Error: The parameters you input is not correct, please input the parameters following the API: sent(java.lang.String,java.lang.String,java.lang.String,java.lang.String)"
Similar to the case of the Java laws, when presented with a valid event, the tester outputs the primitive operations obtained in the ruling. If this ruling contains invalid operations, they will be placed in a seperated category in order to notify the user. The operations regarding the control state are executed as well, and the CS is updated accordingly. For example, if the following law is tested:
adopted(Par,Cert) :- do(deliver(law,adopted,Self)),
do(add(budget(0))),
do(add(visits(0))),
do(delive(law,adopted2,Self)),
do(forward(law,Self)).
The following evaluation can be tested:
New Event: (!h for help):adopted([],[]). Evaluate the event: adopted([],[]). With the control state [] Valid operations: [do(deliver(law,adopted,'self@rutgers.edu')), do(add(budget(0))), do(add(visits(0)))] Invalid operations: [do(delive(law,adopted2,'self@rutgers.edu')), do(forward(law,'self@rutgers.edu'))] Updating the Control State... doAdd(budget(0)) doAdd(visits(0)) The new control state is : [budget(0),visits(0)] re-asserted the context of the law
From the output above, the user will be able to determine the validity of the evaluation, and discover the wrong operations.
A number of user commands are also available. They are as follows:
!h : help command;
!s: view the source code of the law;
!l: view the massaged source code of the law, which is the law indeed loaded by the interpretor;
!v: view all the regulated events of the law;
!c: view the context of the law;
!r: reload the configuration file;
!q: quit the tester;
context(VariableName, VariableValue): set the context "VariableName" to "VariableValue".
The variable name could be one of: CS, DCS, Peer, PeerHash, RList, AList, Self, ThisLawName,ThisLawHash
Example: context(CS,[budget(1)]) or context(Self,x@cs.rutgers.edu);
add(NewTerm): specially designed to manipulate the control state CS: add the term "NewTerm" to current
control state;
remove(OldTerm): specially designed to manipulate the control state CS: remove the term "OldTerm" from
current control state;