Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Support multiple STL files across same module (#10)
Browse files Browse the repository at this point in the history
* Support multiple STL files across same module

Modules can be split across multiple files. Example usage is reflected
in example/example.test, which imports example_base.stl (event
definitions, transition definitions, etc.) and example.stl (transition
instances).

* Allow STL constants to be defined in manifest

Constants can be declared in the STL without a value, and then defined
in the manifest via the 'constants' dictionary entry. Constants are
referenced in the manifest by '<module>::<constant name>'.

* Pass --manifest-args as a list instead of a string

If a manifest variable was a string with a space in it (for example,
--manifest-args="the_string='this has spaces in it'"), it could not be
parsed since we were splitting on whitespace. Now, we just pass the args
as a list (e.g. --manifest-args "this_string='has spaces'" "foo='bar'").

* Fixed quotes in README.md

Example code and commands should be copy/pastable directly from the
README.

* Change Uniqueness qualifiers to not require previous value

This is a simplification of the built-in UniqueInt and UniqueString
qualifiers.
  • Loading branch information
stopping authored Mar 21, 2017
1 parent 895c5f8 commit d5023a4
Show file tree
Hide file tree
Showing 13 changed files with 502 additions and 423 deletions.
108 changes: 70 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,10 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
-a MANIFEST_ARGS, --manifest-args MANIFEST_ARGS
A series of space separated key=value pairs. Each
instance of $key in the manifest file is replaced by
value verbatim. In particular, if you want to pass a
string, it must be explicitly quoted, e.g.:
ip="0.0.0.0"
A list of <key>=<value> pairs. Each instance of
'$<key>' in the manifest file is replaced by <value>
verbatim. In particular, if you want to pass a string,
it must be explicitly quoted, e.g.: 'ip="0.0.0.0"'
-d, --debug Increase logging verbosity to debug level.
```

Expand All @@ -70,26 +69,35 @@ The **test manifest** describes the tests to be run. The test manifest file typi
example.test:
{
'stl_files': ['example.stl'],
'roles': [
{ 'role': 'example::rReceiver',
'ipAddress': $ip, # Must pass --manifest-args="ip='0.0.0.0'" to run.
'transportId': 'receiver-0',
},
],
'test': ['example::rReceiver'],
'stl_files': [
'example_base.stl',
'example.stl',
],
'roles': [ # Role information
{ 'role': 'example::rReceiver',
'ipAddress': $ip, # Must pass --manifest-args 'ip="0.0.0.0"'
'transportId': 'receiver-0',
},
],
'constants': {
'example::kHelloWorld': $hello_world, # Must pass --manifest-args \
# 'hello_world="Hello, world!"'
},
'test': ['example::rReceiver'],
}
$ python test_driver.py example/example.test --manifest-args=”ip=’0.0.0.0’”
$ python test_driver.py example/example.test \
--manifest-args 'ip="0.0.0.0"' 'hello_world="Hello, world!"'
```

### 3.2. stl_files
The ‘stl_files’ field must be a list of strings naming the STL files that include the transitions to be tested. The filenames here should be relative to the manifest .test file. In the example above, [example.test](example/example.test) and [example.stl](example/example.stl) are in the same directory.
The ‘stl_files’ field must be a list of strings naming the STL files that include the transitions to be tested. The filenames here should be relative to the manifest .test file. In the example above, [example.test](example/example.test) and [example_base.stl](example/example_base.stl) are in the same directory.

### 3.3. roles
The ‘roles’ field must be list of dicts. Each dict element in the list describes one role. These are the roles described in the stl_files listed in the ‘stl_files’ field. In the above example, there [example.stl](example/example.stl) contains the following:
The ‘roles’ field must be list of dicts. Each dict element in the list describes one role. These are the roles described in the stl_files listed in the ‘stl_files’ field. In the above example, [example_base.stl](example/example_base.stl) contains the following:
```
example.stl:
Expand All @@ -106,7 +114,7 @@ This gets transformed into
```
{
'role': 'example::rReceiver',
'ipAddress': $ip, # Must pass --manifest-args="ip='0.0.0.0'" to run.
'ipAddress': $ip, # Must pass --manifest-args 'ip="0.0.0.0"'
'transportId': 'receiver-0',
}
```
Expand All @@ -115,11 +123,32 @@ The ‘role’ key maps to the ‘module:rRoleName’, which in this case is ‘

The remaining key: value pairs map to the fields of the role as described in the STL file.

### 3.4. test
### 3.4. constants
The ‘constants’ field must be a dictionary. Each entry in the dictionary defines a declared constant described in the stl_files listed in the ‘stl_files’ field. In the above example, [example_base.stl](example/example_base.stl) contains the following:
```
example_base.stl:
module example;
...
const string kHelloWorld;
...
```

This value gets defined in the manifest here:
```
'constants': {
'example::kHelloWorld': $hello_world, # Must pass --manifest-args \
# 'hello_world="Hello, world!"'
}
```

The key maps to the ‘<module>::<constantName>’, which in this case is ‘example::kHelloWorld’.

### 3.5. test
The ‘test’ field must be a list of strings naming the roles to be tested. Each entry in the test list must correspond to a ‘role’ value in the ‘roles’ list.

### 3.5. Substituting Parameters
Values can be substituted from the command line by passing a space separated list of key=value pairs to the --manifest-args option of test\_driver.py. The manifest .test file will then replace any occurence of $key with value. $key can be located anywhere in the manifest file (e.g. in the list of stl\_files, as a key or vparameter_example.test: test).
### 3.6. Substituting Parameters
Values can be substituted from the command line by passing a space separated list of <key>=<value> pairs to the --manifest-args option of test\_driver.py. The manifest .test file will then replace any occurence of $<key> with <value>. $<key> can be located anywhere in the manifest file (e.g. in the list of stl\_files, as a key or value in any of the manifest dictionaries).
```
parameter_example.test:
Expand All @@ -129,25 +158,27 @@ parameter_example.test:
'roles': [
{ 'role': '$TEST_ROLE',
$FIELD: $VALUE,
‘my_number’: $my_number,
‘my_boolean’: $my_boolean,
‘str_no_quotes’: ‘$str_no_quotes’,
‘str_with_quotes’: $str_with_quotes,
'my_number': $my_number,
'my_boolean': $my_boolean,
'str_no_quotes': '$str_no_quotes',
'str_with_quotes': $str_with_quotes,
'str_with_spaces': $str_with_spaces,
},
],
'test': [$TEST_ROLE],
'test': ['$TEST_ROLE'],
}
$ python test_driver.py parameter_example.test --manifest-args=”\
$ python test_driver.py parameter_example.test --manifest-args \
STL_FILE=example.stl \
TEST_ROLE=example::rReceiver \
FIELD=new_field \
VALUE=new_value \
FIELD=\'new_field\' \
VALUE=\'new_value\' \
my_number=3 \
my_boolean=True \
str_no_quotes=World \
str_with_quotes=’bar’”
'str_no_quotes=Hello, World' \
str_with_quotes=\'bar\' \
'str_with_spaces=\'foo bar baz\''
```

This is exactly equivalent to running with the following manifest:
Expand All @@ -158,14 +189,15 @@ parameter_example_with_substitues.test:
'roles': [
{ 'role': 'example::rReceiver',
‘new_field’: ‘new_value’,
‘my_number’: 3,
‘my_boolean’: True,
‘str_no_quotes’: ‘Hello, World’,
‘str_with_quotes’: ‘bar’,
'new_field': 'new_value',
'my_number': 3,
'my_boolean': True,
'str_no_quotes': 'Hello, World',
'str_with_quotes': 'bar',
'str_with_spaces': 'foo bar baz',
},
],
'test': [example::rReceiver],
'test': ['example::rReceiver'],
}
```
138 changes: 0 additions & 138 deletions example/example.stl
Original file line number Diff line number Diff line change
Expand Up @@ -14,144 +14,6 @@

module example;

// Constants
//
const string kHelloWorld = "Hello, World!";

// Roles
//
role rSender {
string ipAddress;
string transportId;
}

role rReceiver {
string ipAddress;
string transportId;
}

// States
//
state sTlsState(int tlsId) {
kNotConnected,
kConnected,
}

// Messages
//
message mSimpleMessage {
encode "stl.lib.JsonEncoding";
required string words;
}

message[] mMessageArray {
encode "stl.lib.JsonEncoding";
required int i;
}

message mProtoMessage {
encode "stl.lib.ProtobufEncoding";
external "proto.example_pb2.SimpleMsg";
}

message mMessageWithData {
encode "stl.lib.JsonEncoding";

required int request_id;
required string data;
optional string optional_data;
repeated string optional_repeated_data;
optional mNestedMessage optional_nested_data;

message mNestedMessage {
required string data;
}
}

message mCustomEncodeMessage {
encode "example_lib.KeyValueEncoding";
required int request_id : "ord" = 0, "key" = "ri";
required string data : "ord" = 1, "key" = "da";
}

// Qualifiers
//
qualifier int UniqueInt(int prev) = external "stl.lib.UniqueInt";

// Events
//
event Sleep(int tlsId) = external "noop.Sleep";
event LogParams(mSimpleMessage msg) = external "noop.LogParams";
event LogEncodedParams(mMessagearray msg) = external "noop.LogEncodedParams";

event SendRequest(int& requestId, string data) =
LogEncodedParams(mMessageWithData {
request_id = UniqueInt(requestId) -> requestId;
data = data;
});

event SendResponse(int requestId, string data) =
LogEncodedParams(mMessageWithData {
request_id = requestId;
data = data;
});

event SendRequestCustom(int& requestId, string data) =
LogEncodedParams(mCustomEncodeMessage {
request_id = UniqueInt(requestId) -> requestId;
data = data;
});

event SendResponseCustom(int requestId, string data) =
LogEncodedParams(mCustomEncodeMessage {
request_id = requestId;
data = data;
});

// Transitions
//
transition tConnectTls(int tlsId) {
pre_states = [ sTlsState(tlsId).kNotConnected ]
events {
rSender -> Sleep(tlsId) -> rReceiver;
}
post_states = [ sTlsState(tlsId).kConnected ]
}

transition tDisconnectTls(int tlsId) {
pre_states = [ sTlsState(tlsId).kConnected ]
events {
rSender -> LogParams(mSimpleMessage { words = kHelloWorld; }) -> rReceiver;
rSender -> LogEncodedParams(mMessageArray [{ i = 600; }, {i = 30;}]) -> rReceiver;
rSender -> LogEncodedParams(mProtoMessage {
foo = mMessageArray [{ i = 13; }, { i = 14;}];
fizz = 12345;
buzz = [true, true, false];
}) -> rReceiver;
}
post_states = [ sTlsState(tlsId).kNotConnected ]
}

transition tRequestResponse(int tlsId) {
int requestId;
pre_states = [ sTlsState(tlsId).kConnected ]
events {
rSender -> SendRequest(&requestId, "REQUEST") -> rReceiver;
rReceiver -> SendResponse(requestId, "RESPONSE") -> rSender;
}
post_states = []
}

transition tRequestResponseCustom(int tlsId) {
int requestId;
pre_states = [ sTlsState(tlsId).kConnected ]
events {
rSender -> SendRequestCustom(&requestId, "REQUEST") -> rReceiver;
rReceiver -> SendResponseCustom(requestId, "RESPONSE") -> rSender;
}
post_states = []
}

transition tConnectTlsActual = tConnectTls(1);
transition tDisconnectTlsActual = tDisconnectTls(1);
transition tRequestResponseActual = tRequestResponse(1);
Expand Down
15 changes: 13 additions & 2 deletions example/example.test
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# This test can be run from this directory with:
# PYTHONPATH=$PYTHONPATH:$PWD/.. python run_test.py example.test
# -a ip=\"127.0.0.1\" hello_world='"Hello, world!"'
{
'stl_files': ['example.stl'],
'stl_files': [
'example_base.stl',
'example.stl',
],

'roles': [ # Role information
{ 'role': 'example::rReceiver',
'ipAddress': $ip, # Must pass --manifest-args="ip='0.0.0.0'" to run.
'ipAddress': $ip, # Must pass --manifest-args 'ip="0.0.0.0"'
'transportId': 'receiver-0',
},
],

'constants': {
'example::kHelloWorld': $hello_world, # Must pass --manifest-args \
# 'hello_world="Hello, world!"'
},

'test': ['example::rReceiver'],
}
Loading

0 comments on commit d5023a4

Please sign in to comment.