Protocol Testing

Important for:

Protocol Testing

No standard methodology, language, approach, tool

Protocol Testing

Personal story: During past years,

The TTCN-3 Language

But: Until 2015, only proprietary tools / compilers :(

Eclipse TITAN

Great, we can finally use TTCN-3 in FOSS!

Eclipse TITAN compiler workflow

ttcn3__1.png

TTCN-3 Language Features (with TITAN)

TTCN-3 Basic Types

TTCN-3 Structured Types

A structured type is an abstract type comprised of other types, whcih can be nested. An example for a record type (similar to a C-language struct) is shown below

type record MyMessageType {
  integer field1 optional<1>,
  charstring field2,
  boolean field3
};
  1. optional members may be present or not

TTCN-3 Union Type

A union expresses a set of alternative types of which one alternative must be chosen.

type union MyMessageUnion {
  integer field1,
  charstring field2,
};

Difference to C-language union: ischosen() can be used to learn which of the union members is chosen/defined!

Not-used and omit

Sub-typing

Sub-typing can be used to further constrain a given type. Typical examples include constrained number ranges, and string patterns

type integer MyIntRange (1..100);
type integer MyIntRange8 (0..infinity);
type charstring MyCharRange (”k”..”w");
type charstring SideType (”left”, ”right”);
type integer MyIntListRange (1..5,7,9);
type record length(0..10) of integer RecOfInt;
type charstring CrLfTermStrin (pattern ”*\r\n”);

Templates

Templates

// Value list template
template charstring tr_SingleABorC := (”A”, ”B”, ”C”);
// Value range
template float tr_NearPi := (3.14 .. 3.15);
template integer tr_FitsToOneByte := (0 .. 255);
template integer tr_GreaterThanZero := (1 .. infinity);
// Intermixed value list and range matching
template integer tr_Intermixed := ((0..127), 200, 255);

Matching inside values

// Using any element matching inside a bitstring value
// Last 2 bits can be '0' or '1'
template bitstring tr_AnyBSValue := ’101101??’B;
// Matches charstrings with the first character "a"
// and the last one "z"
template charstring tr_0 := pattern "a*z";

Parametric Templates

See below for an example of a parametric template:

type record MyMessageType {
  integer field1 optional,
  charstring field2,
  boolean field3
};

template MyMessageType trMyTemplte(boolean pl_param) := {
  field1 : = ?, // present, but any value
  field2 : = (”B”, ”O”, ”Q”) ,
  field3 := pl_param
};

The built-in match() function can be used to check if a given value matches a given template. Some TTCN-3 statements such as receive() have built-in capabilities for template matching, avoiding even the explicit call of match() in many cases.

Template Hierarchy

Using modified templates, one can build a hierarchy of templates: From the specific to the unspecific

template MyMsgType t_MyMsgAny := {
  msg_type := ?,
  foo := bar
};

template MyMsgType t_MyMsg23 modifies t_MyMsgAny := {
  msg_type := 23,
};

where

Encoders/Decoders

TITAN raw codec: UDP Example

How to express an UDP header using TITAN raw codec

type integer LIN2_BO_LAST (0..65535) with {
  variant ”FIELDLENGTH(16), COMP(nosign), BYTEORDER(last)”
};
type record UDP_header {
  LIN2_BO_LAST srcport,
  LIN2_BO_LAST dstport,
  LIN2_BO_LAST len,
  LIN2_BO_LAST cksum
} with { variant ”FIELDORDER(msb)” };
type record UDP packet {
  UDP_header header
  octetstring payload
} with {
  variant (header) ”LENGTHTO(header, payload), LENGTHINDEX(len)”
};

TITAN raw codec: GTP Example

How to express an GTP header using TITAN raw codec

type record GRE_Header {
  BIT1 csum_present,
  BIT1 rt_present,
  BIT1 key_present,
  ...
  OCT2 protocol_type,
  OCT2 checksum optional,
  OCT2 offset optional,
  OCT4 key otional,
  ...
} with {
  variant (checksum) "PRESENCE(csum_present='1', rt_present='1'B)"
  variant (offset) "PRESENCE(csum_present='1'B, rt_present='1'B)"
  variant (key) "PRESENCE(key_present='1'B)"
}

TITAN text codec: MGCP Example

type charstring MgcpVerb ("EPCF", "CRCX", "MDCX", "DLCX", "RQNT", "NTFY",
                          "AUEP", "AUCX", "RSIP") with {
  variant "TEXT_CODING(,convert=upper_case,,case_insensitive)"
};
type charstring MgcpTransId     (pattern "\d#(1,9)");
type charstring MgcpEndpoint    (pattern "*@*");
type charstring MgcpVersion     (pattern "\d.\d") with {
  variant "BEGIN('MGCP ')"
};
type record MgcpCommandLine {
        MgcpVerb        verb,
        MgcpTransId     trans_id,
        MgcpEndpoint    ep,
        MgcpVersion     ver
} with {
        variant "SEPARATOR(' ', '[\t ]+')"
        variant "END('\r\n', '([\r\n])|(\r\n)')"
};

Program Control Statements

Abstract Communications Operations

'… but if receive blocks, how can we wait for any of N events?

Program Control and Behavior

// x must be the first on queue P, y the second
P.receive(x); // Blocks until x appears on top of queue P
P.receive(y); // Blocks until y appears on top of queue P
// When y arrives first then P.receive(x) blocks -> error

This is what leads to the alt statement: alt declares a seto alternatives covering all events, which

The alt statement

P.send(req)
T.start;
// ...
alt {
[] P.receive(resp)  { /* actions to do and exit alt */ }
[] any port.receive { /* handle unexpected event */ }
[] T.timeout        { /* handle timer expiry and exit */ }
}

The alt and repeat statements

The repeat statement

P.send(req)
T.start;
alt {
  [] P.receive(resp)       { /* actions to do and exit alt */ }
  [] P.receive(keep_alive) { /* handle keep alive message */
                             repeat }
  [] any port.receive      { /* handle unexpected event */ }
  [] T.timeout             { /* handle timer expiry and exit */ }
}

The interleave statement

The interleave statement

interleave {
  [] P.receive(1) { /* actions, optional */ }
  [] Q.receive(4) { /* actions, optional */ }
  [] R.receive(6) { /* actions, optional */ }
}

The altstep construct

Definition of an altstep for PING/PONG handling and guard timer:

altstep my_altstep() {
  [] P.receive(tr_PING) { P.send(ts_PONG); }
  [] T_guard.timeout { setverdict(fail, "Guard timer timed out"); }
}

The altstep construct

Explicit Usage of the my_altstep defined on previous slide:

P.send(foo)
alt {
  [] P.receive(bar)
  [] my_altstep()
}

this dynamically adds the alternatives from my_altstep at the given location and priority of the above alt, ensuring that one doesn’t have to repeat ping/pong handling as well as global guard timer timeout handling in every alt or every single test case all over again.

default altstep activation

altstep as_pingpong() {
  [] P.receive(tr_PING) { P.send(ts_PONG); }
}
...
var default d1 := activate(as_pingpong());
... /* code executing with as_pingpong activated */
deactivate(d1);

TTCN-3 modules

TTCN-3 code is written in modules

Examples

Let’s have a look at some real-world examples and do a bit of a walk-through before continuing with the slides…

Logging

Logging

Log file format example:

// abstract data type before encode
13:30:41.243536 Sent on GTPC to system @GTP_CodecPort.Gtp1cUnitdata : { peer := { connId := 1, remName := "127.0.23.1", remPort := 2123 }, gtpc := { pn_bit := '0'B, s_bit := '1'B, e_bit := '0'B, spare := '0'B, pt := '1'B, version := '001'B, messageType := '01'O, lengthf := 0, teid := '00000000'O, opt_part := { sequenceNumber := '3AAC'O, npduNumber := '00'O, nextExtHeader := '00'O, gTPC_extensionHeader_List := omit }, gtpc_pdu := { echoRequest := { private_extension_gtpc := omit } } } }

// 'msg' contains encoded binary data actually sent via socket
13:30:41.243799 Outgoing message was mapped to @IPL4asp_Types.ASP_SendTo : { connId := 1, remName := "127.0.23.1", remPort := 2123, proto := { udp := { } }, msg := '32010004000000003AAC0000'O }

Logging

The same log file lines if run through ttcn3_logformat

13:30:41.243536 Sent on GTPC to system @GTP_CodecPort.Gtp1cUnitdata : {
    peer := {
        connId := 1,
        remName := "127.0.23.1",
        remPort := 2123
    },
    gtpc := {
        pn_bit := '0'B,
        s_bit := '1'B,
        e_bit := '0'B,
        spare := '0'B,
        pt := '1'B,
        version := '001'B,
        messageType := '01'O,
        lengthf := 0,
        teid := '00000000'O,
        opt_part := {
            sequenceNumber := '3AAC'O,
            npduNumber := '00'O,
            nextExtHeader := '00'O,
            gTPC_extensionHeader_List := omit
        },
        gtpc_pdu := {
            echoRequest := {
                private_extension_gtpc := omit
            }
        }
    }
}
13:30:41.243799 Outgoing message was mapped to @IPL4asp_Types.ASP_SendTo : {
    connId := 1,
    remName := "127.0.23.1",
    remPort := 2123,
    proto := {
        udp := { }
    },
    msg := '32010004000000003AAC0000'O
}

Existing TITAN Source

Further Reading

EOF

End of File