Hi,
I know that TTCN-3 is still new to a lot of you, but we are writing tons of integration testing against the various osmocom programs in it. It is quite amazing technology, and I would like to ask you to bear with me reading this mail :)
Pau was stating the question earlier today on not finding an example on how to use decmatch. Indeed, it took me some months to find that gem in the TTCN-3 world.
It solves the problem that you often have during test of layered protocol stacks: you have separate encoders/decoders for each protocol layer, and now you want to match on some of the *inner* payload.
So normally, you have some kind of header definition + a binary (octetstring) payload. This happens in RSL with the L3_INFO IE, and just the same on BSSAP/DTAP where again the L3 message (for example call control) is encapsulated inside one information element.
Now you have multiple options of addressing the problem: a) hand-written calls to the decoder function b) write na 'emulation' for the entire protocol layer c) use decmatch.
a) would look like this (pseudo-code):
var octetstring l3oct; var RSL_Message rsl RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) -> value rsl { var PDU_ML3_MS_NW l3 := dec_PDU_ML3_MS_NW(rsl.payload); if (match(l3, some_template)) { ... do something } ... }
Which uses the built-in pattern-matching on the RSL port to match any message that matches the tr_RSL_DATA_REQ template, and stores the resulting RSL message in a variable. It then uses an explicit call to the decoder function of the L3 message, and then uses regular conditional expressions for further matching on that inner L3 payload.
This is more or less how you would write in C, python or any other quite imperative programming languages. It's very verbose, time consuming and un-abstract/elegant.
TTCN-3 has many declarative aspects to it. Code like the above is a waste of your time :)
b) would mean that you implement some test component that handles the RSL messages on its bottom side test port, and the L3 messages on its top side test port. That is a possible way, and if you need a lot of state/logic of RSL, it maeks sense. But what if you really simply want to have a match? Then it would be a lot of effort and a large detour.
c) decmatch to the rescue!
You can write
RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS))
which means:
* do a receive on the RSL test port, and match on an incoming RSL message that matches the tr_RSL_DATA_REQ template, with channel number specified, link_id any (?), *and* if the octetstring payload, if decoded, matches the template tr_RRM_RR_STATUS !
This is *extremely* powerful and expressive. It allows you to condense complex, parametric template matching over multiple proocol layers. It would in the end match RSL DATA REQUEST, only if they contained a [valid] encoded RR STATUS. See https://gerrit.osmocom.org/6229 for the actual test case I used for the above examples.
Please also note that I never had to even write the function name of the decoder (dec_PDU_ML3_MS_NW), but TTCN-3 *automatically* figures out which decoder function it must call in order to decode from the binary octetstring.
Happy (TTCN-3) hacking + Osmocom bugfixing, Harald
Hi Harald,
thanks for the explanation! However, it's still not clear to me how to get the decoded payload out of the receive statement. From https://www.eclipse.org/forums/index.php/t/1089269/ I saw there's this "@decoded" keyword you can use but I couldn't figure out how to really use it in a proper way, and what exactly I would be getting with it.
I'm also wondering if several decmatch expressions can be stacked in a single statment, for instance image something like: RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS(foo, bar, decmatch tr_ANOTHER_TEMPLATE)). Linking it with first question, what I would be getting when using the @decoded keyword in this case?
And extra question I asked myself while doing some tests today: is there a way to check if a template received through a function parameter matches a specific template? I tried with match() but from what I understood from the compilation errors, it seems match() actually checks a value vs a template, and not 2 templates. Hm maybe just using "==" would work, I didn't check it.
Last query: Did you find a good tutorial or well documented examples for beginners in some specific place?
Hi Pau,
On Thu, Feb 01, 2018 at 12:18:11AM +0100, Pau Espin Pedrol wrote:
thanks for the explanation! However, it's still not clear to me how to get the decoded payload out of the receive statement. From https://www.eclipse.org/forums/index.php/t/1089269/ I saw there's this "@decoded" keyword you can use but I couldn't figure out how to really use it in a proper way, and what exactly I would be getting with it.
The ETSI TTCN-3 language spec actually has plenty of useful examples.
From ETSI ES 201 873-1 V4.8.1, Section 22.2.2 Example 2:
MyPort.receive(MyType2:{header := ?, payload := decmatch mw_myTemplate}) -> value (v_myVar := @decoded payload); // The encoded payload field of the received message is decoded and matched with // mw_myTemplate; if the matching is successful the decoded payload is stored in v_myVar.
I'm also wondering if several decmatch expressions can be stacked in a single statment, for instance image something like:
I have no idea, guess you'd have to try.
RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS(foo, bar, decmatch tr_ANOTHER_TEMPLATE)). Linking it with first question, what I would be getting when using the @decoded keyword in this case?
I guess you should raise that in the Eclipse Titan forum ;)
And extra question I asked myself while doing some tests today: is there a way to check if a template received through a function parameter matches a specific template?
templates cannot match other templates. They can only match values
I tried with match() but from what I understood from the compilation errors, it seems match() actually checks a value vs a template,
correct.
Hm maybe just using "==" would work, I didn't check it.
You can compare if two templates are equal. I would argue that this is not the same as your question "a template matches a template". So using "==" between two identical templates should evaluate true (I don't think I ever tried). But for sure, a more generic template wound not be equal to a more specific template, even though there are values that could match both templates.
Last query: Did you find a good tutorial or well documented examples for beginners in some specific place?
I've so far been looking primarily at * https://www.ttcn-3.org/files/TTCN3_P.pdf * the above-mentioned ETSI core language spec for TTCN-3 * the Eclipse/Ericsson TITAN referenceguide.pdf "Programmers Guide" which is part of https://www.eclipse.org/downloads/download.php?file=/titan/TitanDocuments_6_...