/****************************************************************************** * Copyright (c) 2000-2015 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html ******************************************************************************/ module Untagged { modulepar boolean Untagged_verbose := false; #define verbose Untagged_verbose #include "../macros.ttcnin" /* * * * * * * * * * * Untagged applied to a field * * * * * * * * * * */ type enumerated ProductColor { red(0), green(1), blue(2) } type record ProductInfo { charstring name, ProductColor color } type record AdditionalInfo { integer size, boolean available } type record ProductU { record of ProductColor color, ProductInfo info, AdditionalInfo addInfo, union { integer usd, integer euro } priceInfo } with { variant (color) "untagged"; variant (info) "untagged"; variant (addInfo) "untagged"; variant (priceInfo) "untagged"; // It's getting a bit monotonous... variant (priceInfo.usd) "name as uppercased"; variant (priceInfo.euro) "name as uppercased"; } const ProductU val := { color := { red, green, blue }, info := { name := "shirt", color:= red }, addInfo := { size := 44, available := false }, priceInfo := { usd := 25 } } const universal charstring str_prodU_e := "\n" & "\tred\n" & "\tgreen\n" & "\tblue\n" & "\tshirt\n" & "\tred\n" & "\t44\n" & "\tfalse\n" & "\t25\n" & "\n" & "\n"; const universal charstring str_prodU_b := "\n" & "\t\n" & "\t\t\n" & "\t\n" & "\t\n" & "\t\tshirt\n" & "\t\t\n" & "\t\n" & "\t\n" & "\t\t44\n" & "\t\t\n" & "\t\n" & "\t\n" & "\t\t25\n" & "\t\n" & "\n" & "\n"; DECLARE_XER_ENCODERS(ProductU, prodU); DECLARE_EXER_ENCODERS(ProductU, prodU); type component UTA {} testcase encode_ut() runs on UTA { CHECK_METHOD(bxer_enc_prodU, val, str_prodU_b); CHECK_METHOD(exer_enc_prodU, val, str_prodU_e); } testcase decode_ut() runs on UTA { CHECK_DECODE(bxer_dec_prodU, str_prodU_b, ProductU, val); CHECK_DECODE(exer_dec_prodU, str_prodU_e, ProductU, val); } /* * * * * * * * * * * Untagged applied to a type * * * * * * * * * * */ type record ProductInfo2 { charstring name, ProductColor color } with { variant "untagged"; variant "name as 'ProductInfo'"; } type record AdditionalInfo2 { integer size, boolean available } with { variant "untagged"; variant "name as 'AdditionalInfo'"; } type record Product2 { record of ProductColor color, ProductInfo2 info, AdditionalInfo2 addInfo, union { integer usd, integer euro } priceInfo } with { variant "name as 'ProductU'" variant (color) "untagged"; variant (info) "untagged"; variant (priceInfo) "untagged"; // It's getting a bit monotonous... variant (priceInfo.usd) "name as uppercased"; variant (priceInfo.euro) "name as uppercased"; } DECLARE_XER_ENCODERS(Product2, prod2); DECLARE_EXER_ENCODERS(Product2, prod2); // EXER only const Product2 val2 := { color := { red, green, blue }, info := { name := "shirt", color:= red }, addInfo := { size := 44, available := false }, priceInfo := { usd := 25 } } const universal charstring str_prod_b2 := "\n" & "\t\n" & "\t\t\n" & "\t\n" & "\t\n" & "\t\tshirt\n" & "\t\t\n" & "\t\n" & "\t\n" & "\t\t44\n" & "\t\t\n" & "\t\n" & "\t\n" & "\t\t25\n" & "\t\n" & "\n" & "\n"; testcase encode_ut2() runs on UTA { CHECK_METHOD(bxer_enc_prod2, val2, str_prod_b2); CHECK_METHOD(exer_enc_prod2, val2, str_prodU_e); } testcase decode_ut2() runs on UTA { CHECK_DECODE(bxer_dec_prod2, str_prod_b2, Product2, val2); CHECK_DECODE(exer_dec_prod2, str_prodU_e, Product2, val2); } /* * * * * * * * * * * Nested untagged * * * * * * * * * * */ type record level0 { level1 f1 } with { variant (f1) "untagged"; variant "untagged" } type record level1 { level2 f2 } with { variant (f2) "untagged" } type record level2 { level3 f3 } with { variant (f3) "untagged" } type union level3 { integer i, float f } DECLARE_XER_ENCODERS(level0, l0); DECLARE_EXER_ENCODERS(level0, l0); const level0 cl0 := { f1 := { // a level1 f2 := { // a level2 f3 := { i := 13 } } } } const universal charstring bstr_cl0 := "\n" & "\t\n" & "\t\t\n" & "\t\t\t\n" & "\t\t\t\t13\n" & "\t\t\t\n" & "\t\t\n" & "\t\n" & "\n\n"; const universal charstring estr_cl0 := // This is the "right thing" because UNTAGGED is ignored for top-level types "\n" & "\t13\n" & "\n\n"; testcase encode_deep() runs on UTA { CHECK_METHOD(bxer_enc_l0, cl0, bstr_cl0); CHECK_METHOD(exer_enc_l0, cl0, estr_cl0); } testcase decode_deep() runs on UTA { CHECK_DECODE(bxer_dec_l0, bstr_cl0, level0, cl0); CHECK_DECODE(exer_dec_l0, estr_cl0, level0, cl0); } /* * * * * * * * * * * Deeper * * * * * * * * * * */ type union ch0 { level0 l0, record of integer numbers } with { variant (numbers) "untagged" } type record wrapper { ch0 c0 } with { variant (c0) "untagged" } DECLARE_XER_ENCODERS(wrapper, w); DECLARE_EXER_ENCODERS(wrapper, w); const wrapper cw0 := { c0 := { l0 := cl0 } } const wrapper cw1 := { c0 := { numbers := { 3, 14, 15, 92, 6 } } } const universal charstring bstr_cw0 := "\n" & "\t\n" & "\t\t\n" & "\t\t\t\n" & "\t\t\t\t\n" & "\t\t\t\t\t\n" & "\t\t\t\t\t\t13\n" & "\t\t\t\t\t\n" & "\t\t\t\t\n" & "\t\t\t\n" & "\t\t\n" & "\t\n" & "\n\n"; const universal charstring estr_cw0 := "\n" & "\t13\n" & "\n\n"; const universal charstring bstr_cw1 := "\n" & "\t\n" & "\t\t\n" & "\t\t\t3\n" & "\t\t\t14\n" & "\t\t\t15\n" & "\t\t\t92\n" & "\t\t\t6\n" & "\t\t\n" & "\t\n" & "\n\n"; const universal charstring estr_cw1 := "\n" & "\t3\n" & "\t14\n" & "\t15\n" & "\t92\n" & "\t6\n" & "\n\n"; testcase encode_wrap() runs on UTA { CHECK_METHOD(bxer_enc_w, cw0, bstr_cw0); CHECK_METHOD(exer_enc_w, cw0, estr_cw0); CHECK_METHOD(bxer_enc_w, cw1, bstr_cw1); CHECK_METHOD(exer_enc_w, cw1, estr_cw1); } testcase decode_wrap() runs on UTA { CHECK_DECODE(bxer_dec_w, bstr_cw1, wrapper, cw1); CHECK_DECODE(exer_dec_w, estr_cw1, wrapper, cw1); CHECK_DECODE(bxer_dec_w, bstr_cw0, wrapper, cw0); CHECK_DECODE(exer_dec_w, estr_cw0, wrapper, cw0); } /* * * * * * * * HK76145 * * * * * * * * * */ type record dir { record of record { record { charstring name, integer size } folder } lista } with { variant (lista) "untagged" variant (lista[-]) "untagged" } DECLARE_XER_ENCODERS(dir, dir); DECLARE_EXER_ENCODERS(dir, dir); const dir durr := { lista := {{ folder := { name := "foo", size := 13 } }} } const universal charstring bstr_durr := "\n" & "\t\n" & "\t\t\n" & "\t\t\t\n" & "\t\t\t\tfoo\n" & "\t\t\t\t13\n" & "\t\t\t\n" & "\t\t\n" & "\t\n" & "\n\n"; const universal charstring estr_durr := "\n" & "\t\n" & "\t\tfoo\n" & "\t\t13\n" & "\t\n" & "\n\n"; testcase encode_dir() runs on UTA { CHECK_METHOD(bxer_enc_dir, durr, bstr_durr); CHECK_METHOD(exer_enc_dir, durr, estr_durr); } testcase decode_dir() runs on UTA { CHECK_DECODE(bxer_dec_dir, bstr_durr, dir, durr); CHECK_DECODE(exer_dec_dir, estr_durr, dir, durr); } /* * * * * * * * Empty record in an untagged record-of * * * * * * * */ type record Envelope { //record of Header header optional, Body body } type union Body { record {} fault, record of Content content_list } with { variant (content_list) "untagged"; variant (content_list[-]) "untagged"; } type union Content { Logout logout, LogoutResponse logoutResponse } with { variant (logout ) "name as capitalized" variant (logoutResponse) "name as capitalized" } type record Logout {}; type record LogoutResponse {}; DECLARE_XER_ENCODERS(Envelope, env); DECLARE_EXER_ENCODERS(Envelope, env); const Envelope resp := { body := { content_list := {{ logoutResponse := {} }} } } const universal charstring str_resp := "\n" & "\t\n" & "\t\t\n" & "\t" & "\n\n\n"; const universal charstring str_resp_non_canon := "\n" & "\t\n" & "\t\t\n" & "\t\t\n" & "\t" & "\n\n\n"; testcase encode_env() runs on UTA { CHECK_METHOD(exer_enc_env, resp, str_resp); } testcase decode_env() runs on UTA { CHECK_DECODE(exer_dec_env, str_resp, Envelope, resp); CHECK_DECODE(exer_dec_env, str_resp_non_canon, Envelope, resp); } /* * * * * Untagged simple types as fields * * * * */ /* * * * * * * * * Tests for HL75936 * * * * * * * */ // bitstring is exempt : not character-encodable // ~~~~~~~~~~~~ boolean type record r_b { boolean field } with { variant (field) "untagged"; } DECLARE_EXER_ENCODERS(r_b, b); const r_b c_b := { field := true } const universal charstring s_b := "true\n\n"; testcase encode_ut_bool() runs on UTA { CHECK_METHOD(exer_enc_b, c_b, s_b); } testcase decode_ut_bool() runs on UTA { CHECK_DECODE(exer_dec_b, s_b, r_b, c_b); } // ~~~~~~~~~~~~~~~ charstring type record r_cs { charstring field } with { variant (field) "untagged" } DECLARE_EXER_ENCODERS(r_cs, cs); const r_cs c_cs := { field := "Hello, world!" } const universal charstring s_cs := "Hello, world!\n\n"; testcase encode_ut_cs() runs on UTA { CHECK_METHOD(exer_enc_cs, c_cs, s_cs); } testcase decode_ut_cs() runs on UTA { CHECK_DECODE(exer_dec_cs, s_cs, r_cs, c_cs); } // ~~~~~~~~~~~~~~~ float type record r_f { float field } with { variant (field) "untagged" } DECLARE_EXER_ENCODERS(r_f, f); const r_f c_f := { field := 42.42 } const universal charstring s_f := "42.420000\n\n"; testcase encode_ut_f() runs on UTA { CHECK_METHOD(exer_enc_f, c_f, s_f); } testcase decode_ut_f() runs on UTA { CHECK_DECODE(exer_dec_f, s_f, r_f, c_f); } // ~~~~~~~~~~~~~~~ integer type record r_i { integer field } with { variant (field) "untagged" } DECLARE_EXER_ENCODERS(r_i, i); const r_i c_i := { field := 42 } const universal charstring s_i := "42\n\n"; testcase encode_ut_i() runs on UTA { CHECK_METHOD(exer_enc_i, c_i, s_i); } testcase decode_ut_i() runs on UTA { CHECK_DECODE(exer_dec_i, s_i, r_i, c_i); } // ~~~~ octetstring (needs hexBinary or base64Binary to be character-encodable) type record r_ostr { octetstring field } with { variant (field) "untagged" variant (field) "XSD:hexBinary" } DECLARE_EXER_ENCODERS(r_ostr, ostr); const r_ostr c_ostr := { field := 'DEADBEEF'O } const universal charstring s_ostr := "DEADBEEF\n\n"; testcase encode_ut_ostr() runs on UTA { CHECK_METHOD(exer_enc_ostr, c_ostr, s_ostr); } testcase decode_ut_ostr() runs on UTA { CHECK_DECODE(exer_dec_ostr, s_ostr, r_ostr, c_ostr); } type record r_ostr64 { octetstring field } with { variant (field) "untagged" variant (field) "XSD:base64Binary" } DECLARE_EXER_ENCODERS(r_ostr64, ostr64); const r_ostr64 c_ostr64 := { field := 'DEADBEEF'O } const universal charstring s_ostr64 := "3q2+7w==\n\n"; testcase encode_ut_ostr64() runs on UTA { CHECK_METHOD(exer_enc_ostr64, c_ostr64, s_ostr64); } testcase decode_ut_ostr64() runs on UTA { CHECK_DECODE(exer_dec_ostr64, s_ostr64, r_ostr64, c_ostr64); } // ~~~~~~~~~~~~~~~ universal charstring type record r_ustr { charstring missing optional, universal charstring field } with { variant (missing) "attribute"; variant (field) "untagged"; } DECLARE_EXER_ENCODERS(r_ustr, ustr); const r_ustr c_ustr := { missing := omit, // LATIN CAPITAL LETTER A WITH RING ABOVE // | LATIN SMALL LETTER O WITH DIAERESIS field := char(0,0,0,197) & "ngstr" & char(0,0,0,246) & "m" } const universal charstring s_ustr := "" & c_ustr.field & "\n\n"; const r_ustr c_ustr0 := { missing := omit, field := "" } const universal charstring s_ustr0 := "\n\n"; testcase encode_ut_ustr() runs on UTA { CHECK_METHOD(exer_enc_ustr, c_ustr, s_ustr); CHECK_METHOD(exer_enc_ustr, c_ustr0,s_ustr0); } testcase decode_ut_ustr() runs on UTA { CHECK_DECODE(exer_dec_ustr, s_ustr, r_ustr, c_ustr); CHECK_DECODE(exer_dec_ustr, s_ustr0,r_ustr, c_ustr0); } /* * * * * * * * * * * Run it! * * * * * * * * * * */ control { execute(encode_ut()); execute(decode_ut()); execute(encode_ut2()); execute(decode_ut2()); execute(encode_deep()); execute(decode_deep()); execute(encode_wrap()); execute(decode_wrap()); execute(encode_dir()); execute(decode_dir()); execute(encode_env()); execute(decode_env()); // // // // execute(encode_ut_bool()); execute(decode_ut_bool()); execute(encode_ut_cs()); execute(decode_ut_cs()); execute(encode_ut_f()); execute(decode_ut_f()); execute(encode_ut_i()); execute(decode_ut_i()); execute(encode_ut_ostr()); execute(decode_ut_ostr()); execute(encode_ut_ostr64()); execute(decode_ut_ostr64()); execute(encode_ut_ustr()); execute(decode_ut_ustr()); } } with { encode "XML"; }