ALLINSIGHT

Home of the AlmostImplementedException

How to work with templates

One of the key features in TTCN-3 are templates. You can use them to fill TTCN-3 records with predefined values and you can use them as matching-templates to check if the values are like expected.
If you have a complex structure and you need to check every single property you normally have to use a lot of if-statements. With a matching-template you can do it with a single line.

First we need a complex structure to work with. Lets just use the Message-Record from my last post and fill it using a template.

[ttcn3]
type record Value {
charstring path, charstring value optional
}

type record Message {
charstring file optional,
charstring portTypeName optional,
charstring operationName optional,
charstring bindingName optional,
set of Value values
}

template Message m_messageTemplate:={
portTypeName:=”b”,
operationName:=”c”,
count:=5,
values:={}
}
[/ttcn3]

The first two code-blocks should be clear, if not read my previous post how-to-define-your-own-types. The last block is the important one.
We define a template of type Message with the name m_messageTemplate. The prefix m_ (as recommended by ETSI) is used for templates which fills a type. M stands for message, because a template is a specific message (i would have used t_ but its reserved for timer).
As you can see, a template works exactly like a direct assign (see previous post), but you can use it multiple times.
And here is a snippet how to use it:

[ttcn3]
var Message v_variable := m_messageTemplate;
[/ttcn3]

That’s helpful if you always want the same values in all your message-objects. But what if you have to change one value? You can use parameter!
Templates support parameter just like functions. Lets define a few and see how it works:

[ttcn3]
template Message m_messageTemplate (charstring p_bindingName, charstring p_portTypeName:=”port”):={
portTypeName:=p_portTypeName,
operationName:=”c”,
bindingName:=p_bindingName,
count:=5,
values:={}
}

testcase simpleTest() runs on SimpleType{
var Message v_variable := m_messageTemplate(“test”);
log (v_variable);

v_variable := m_messageTemplate(“test”, “port”);
log (v_variable);

v_variable := m_messageTemplate(p_bindingName:=”test”, p_portTypeName:=”port”);
log (v_variable);
}
[/ttcn3]

Now I’ve changed the m_messageTemplate to use two parameter. As you may have noticed, both use the prefix p_ (see ETSI naming conventions).
The first one is mandatory, the second one has a default-value and is therefore optional.
I also modified my simpleTest from the First-Test-Post to show how to use a template with parameter. All 3 calls are allowed.
The first one only fills one parameter (p_bindingName). If we would define the first parameter with a default-value and the second without this call wouldn’t work.
The second sets both parameter. If you do it this way, be sure nobody changes the order of the template-parameter, otherwise the result is different and you would notice.
The last one is the best way to call a template or a function with a lot of (optional) parameter. Here you specify which parameter you want to set. If you have multiple optional parameter you just set the ones you need.

If you want to fill the values-part of the message-record its getting tricky. You have to know exactly how many entries you need and provide that many parameter. Since you can’t overload a template or function (a.k.a use the same name with different parameter) you have to use optional parameter.

[ttcn3]
template Message m_messageTemplate (
charstring p_bindingName, charstring p_portTypeName:=”port”,
charstring valuePath1:=””, template charstring valueFile1:=omit,
charstring valuePath2:=””, template charstring valueFile2:=omit,
charstring valuePath3:=””, template charstring valueFile3:=omit
):={
portTypeName:=p_portTypeName,
operationName:=”c”,
bindingName:=p_bindingName,
count:=5,
values:={
{valuePath1, valueFile1},
{valuePath2, valueFile2},
{valuePath3, valueFile3}
}
}
[/ttcn3]

Now I’ve defined 3 path-file-pairs. If you need more, you have to define more parameter. Since file is declared as optional i have to define the associated parameter as template with the default-value omit. There is no optional-keyword for parameter and only a template-parameter can be set to omit.
There are two problems with this approach. The first one is you have to set two associated parameter (path and file), but you can use one Value-parameter instead of the two separate charsting-parameter to fix this.
The second is a real problem. Regardless of the parameter you set, you’ll always have 3 values-entries with an empty charstring for the path and an omit for the file.

To fill the values-record only with parameter you’ve set you have to use a function to create the template and need a few tricks and workarounds. This will be shown in a later post.

Last but not least let me introduce you to matching templates. They work like the templates above, but can use wildcards instead of concrete values. So lets create a matching template for our Message-type using the same parameter as above and match it against a variable.
I already used match in my first testcase but this time we use it to check a complex type.

[ttcn3]
template Message mw_messageTemplateExpected (
template charstring p_bindingName, template charstring p_portTypeName:=*,
template charstring valuePath1:=*, template charstring valueFile1:=*,
template charstring valuePath2:=*, template charstring valueFile2:=*
):={
portTypeName:=p_portTypeName,
operationName:=”c”,
bindingName:=p_bindingName,
count:=5,
values:={
{valuePath2, valueFile2},
{valuePath1, valueFile1},
*
}
}

testcase simpleTest() runs on SimpleType{
var Message v_variable := m_messageTemplate(p_bindingName:=”test”, valuePath1:=”path”, valueFile1:=”file”);
var template Message expectedData := mw_messageTemplateExpected(p_bindingName:=”test”, valuePath1:=?, valueFile1:=?);

if (match(v_variable, expectedData)){
setverdict(pass);
}else{
setverdict(fail);
}
}
[/ttcn3]

Now I have to use mw_ as a prefix (see ETSI naming conventions) because its a matching template. I declared every parameter as template to allow omit, * and ? as values. With ? you can say you expect a value (everything != omit) but don’t care what value. * means you don’t even care if there is a value.
In values I added a * to indicate that I don’t care if there are more than two entries. If you remove it, the matching will fail, because we have 3 entries.
I also switched the order of value 1 and 2 in the values to show you that the order doesn’t matter.

When you execute this test, you’ll see that the matching is successful. !Important! The match-command uses the variable as first parameter and the template as second. You can’t match 2 templates or switch both parameters.
If you use TTWorkbench you can click on the match log-entry in the graphical-log to see both structures (variable and template). Warning! Both are interchanged on the screen, the template is left of the table and the variable is right.
The matching-table is very useful and can show you which values differ. A bit disappointing, it doesn’t show you which concrete value in a record or set is wrong.

That’s all for now, see you next time.

Share :

Leave a Reply

Your email address will not be published. Required fields are marked *