/****************************************************************************** * 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 AttributeTestcases { import from Functions all; import from Types all; //tests in case of no attributes: //if omit fields do not appear in the encoded text //if all not omitted field appear in the encoded text //if all not omitted field value appear in the correct form testcase tc_NoAttributeOnUpperLevel() runs on MTC { var Profile0 p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := omit, meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone_no\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760}}"); f_check_encoding(encoded:= f_enc_profile0(p), expected := os); f_bool2verdict( match(f_dec_profile0(f_enc_profile0(p)), p) ); } //tests in case of selecting attributes: //if omit fields appear in the encoded //if all not omitted field value appear in the correct form testcase tc_name_as_omit_as_null() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := omit, meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760},\"meetings\":null}"); f_check_encoding(encoded:= f_enc_profile(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile(p)), p) ); } testcase tc_name_as() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := "bob@ericsson.com", meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760},\"email\":\"bob@ericsson.com\",\"meetings\":null}"); f_check_encoding(encoded:= f_enc_profile(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile(p)), p) ); } // testing attribute "name as ..." when the aliases are keywords of the JSON variant syntax testcase tc_name_as_with_keywords() runs on MTC { var KeywordFields p := { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; var octetstring os := char2oct("{\"omit\":1,\"as\":2,\"null\":3,\"name\":4,\"value\":5,\"default\":6,\"extend\":7,\"metainfo\":8,\"for\":9,\"unbound\":10,\"JSON\":11}"); f_check_encoding(encoded := f_enc_kw_fld(p), expected := os); f_bool2verdict( match(f_dec_kw_fld(os), p) ); } //tests in case of selecting attributes: //if omit fields appear in the encoded //if all not omitted field value appear in the correct form testcase tc_attribute_compactprint1() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := omit, meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760},\"meetings\":null}"); f_check_encoding(encoded:= f_enc_profile_compact(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile_compact(p)), p) ); } testcase tc_attribute_compactprint2() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := "bob@ericsson.com", meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760},\"email\":\"bob@ericsson.com\",\"meetings\":null}"); f_check_encoding(encoded:= f_enc_profile_compact(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile_compact(p)), p) ); } testcase tc_attribute_compactprintp() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := "bob@ericsson.com", meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760},\"email\":\"bob@ericsson.com\",\"meetings\":null}"); f_check_encoding(encoded:= f_enc_profile_compact_p(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile_compact_p(p)), p) ); } //tests in case of selecting attributes: //if omit fields appear in the encoded //if all not omitted field value appear in the correct form //pretty printing testcase tc_attribute_prettyprint1() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := omit, meetings := omit } var octetstring os := char2oct("{\n\t\"name\" : \"Bob\",\n\t\"phone\" : {\n\t\t\"CountryPrefix\" : 6,\n\t\t\"NetworkPrefix\" : 1,\n\t\t\"LocalNumber\" : 3377760\n\t},\n\t\"meetings\" : null\n}"); f_check_encoding(encoded:= f_enc_profile_pretty(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile(p)), p) ); } //pretty printing testcase tc_attribute_prettyprint2() runs on MTC { var Profile p := { name := "Bob", phone_no := { 6, 1, 3377760 }, email_addr := "bob@ericsson.com", meetings := omit } var octetstring os := char2oct("{\"name\":\"Bob\",\"phone\":{\"CountryPrefix\":6,\"NetworkPrefix\":1,\"LocalNumber\":3377760},\"email\":\"bob@ericsson.com\",\"meetings\":null}"); f_check_encoding(encoded:= f_enc_profile(p), expected := os); f_bool2verdict( match(f_dec_profile(f_enc_profile(p)), p) ); } testcase tc_attribute_union() runs on MTC { var CBA c:= { f_val:= 1.75 } var octetstring os := char2oct("{\"float\":1.750000}"); f_check_encoding(encoded:= f_enc_cba(c) , expected := os); f_bool2verdict( match(f_dec_cba(f_enc_cba(c)), c) ); c:= { i_val := -2 } os := char2oct("{\"int\":-2}"); f_check_encoding(encoded:= f_enc_cba(c) , expected := os); f_bool2verdict( match(f_dec_cba(f_enc_cba(c)), c) ); c:= { cs_val := "Hello" } os := char2oct("{\"string\":\"Hello\"}"); f_check_encoding(encoded:= f_enc_cba(c) , expected := os); f_bool2verdict( match(f_dec_cba(f_enc_cba(c)), c) ); c:= { date_val := {"March",28,Friday} } os := char2oct("{\"date\":{\"month\":\"March\",\"day_idx\":28,\"day_name\":\"Friday\"}}"); f_check_encoding(encoded:= f_enc_cba(c) , expected := os); f_bool2verdict( match(f_dec_cba(f_enc_cba(c)), c) ); } // Encoding unions as JSON values (without the braces and the field name) // The decoder will attempt to decode each field and the first to successfully decode the value // will be the selected one (thus the order of the fields is important) testcase tc_attribute_as_value() runs on MTC { var Stuff stuff := { { ival := 18 }, { osval := '1D66FE'O }, { csval := "almafa" }, { bval := true }, { fval := 1.8e-20}, { ucsval := "almácska" }, { bsval := '1101101'B }, { prodval := { name := "Shoe", price := 79.99, code := 'A4C'H } }, { roival := { 1, 3, 3, 7 } }, { prod2val := { "Car", 14000.0, omit } }, { sizeval := Large }, { unival := { hsval := 'EE0'H } }, { unival := { rocsval := { "one", "two", "ten" } } } }; var octetstring os := unichar2oct("[18,\"1D66FE\",\"almafa\",true,1.800000e-20,\"almácska\",\"1101101\",{\"name\":\"Shoe\",\"price\":79.990000,\"code\":\"A4C\"},[1,3,3,7],{\"name\":\"Car\",\"price\":14000.000000},\"Large\",\"EE0\",[\"one\",\"two\",\"ten\"]]", "UTF-8"); f_check_encoding(encoded:= f_enc_stuff(stuff) , expected := os); f_bool2verdict( match(f_dec_stuff(f_enc_stuff(stuff)), stuff) ); setverdict(pass); } // Testing default values for record fields (decoding only) testcase tc_attribute_default() runs on MTC { var octetstring os := char2oct("{}"); var RecDef d := { i := -19, f := 1000000.000000, b := false, bs := '101'B, hs := 'DEAD'H, os := '1DE7'O, cs := "empty", ucs := "üres", size := Tiny, vt := fail }; f_bool2verdict( match(f_dec_def(os), d) ); os := char2oct("{ \"b\" : null }"); d.b := omit; f_bool2verdict( match(f_dec_def(os), d) ); } // Encoding a few values of ASN.1 types with the coding instruction "as value" // Results are the same as with the TTCN-3 types testcase tc_attribute_as_value_asn() runs on MTC { var AsnStuff stuff := { { nval := NULL }, { ival := -10 }, { anyval := 'DCBA'O }, { vsval := "something" }, { pardval := { id := 0, priority := low, val := { iNTEGER := -10 } } } }; var octetstring os := char2oct("[null,-10,\"DCBA\",\"something\",{\"id\":0,\"priority\":\"low\",\"val\":{\"iNTEGER\":-10}}]"); f_check_encoding(encoded := f_enc_asn_stuff(stuff), expected := os); f_bool2verdict( match(f_dec_asn_stuff(f_enc_asn_stuff(stuff)), stuff) ); } // Encoding a record with 2 optional union fields encoded as JSON values (attribute 'as value') // and as the 'null' value when omitted (attribute 'omit as null'). // One of the unions ('uniAsn') can decode the JSON value 'null' (field 'nval'), thus omitting // the union and setting this field have the same encoding, and decoding 'null' always sets the // field instead of omitting the union. // The other union ('uniTtcn') cannot decode the JSON value 'null', thus decoding 'null' omits // the union. testcase tc_attribute_optional_as_value() runs on MTC { var OptionalUnions val1 := { dummy := "nothing", uniTtcn := omit, uniAsn := omit }; var OptionalUnions val2 := { dummy := "nothing", uniTtcn := omit, uniAsn := { nval := NULL } }; var octetstring os := char2oct("{\"dummy\":\"nothing\",\"uniTtcn\":null,\"uniAsn\":null}"); f_check_encoding(encoded := f_enc_opt_uni(val1), expected := os); f_check_encoding(encoded := f_enc_opt_uni(val2), expected := os); f_bool2verdict( match(f_dec_opt_uni(os), val2) ); } // Encoding records and sets with unbound fields with meta info (attribute 'metainfo for unbound') // The unbound fields will have the 'null' value and an extra (meta info) field will be inserted // into the JSON document (after the current field) to specify that the field is unbound. testcase tc_attribute_metainfo_for_unbound() runs on MTC { // regular encoding and decoding tests var MetainfoRecord r := { num := 6 }; var octetstring os := char2oct("{\"num\":6,\"str\":null,\"metainfo str\":\"unbound\"}"); f_check_encoding(encoded := f_enc_meta_rec(r), expected := os); f_bool2verdict( log2str(f_dec_meta_rec(os)) == log2str(r) ); var MetainfoSet s := { str := "abc" }; os := char2oct("{\"int\":null,\"metainfo int\":\"unbound\",\"str\":\"abc\",\"octets\":null,\"metainfo octets\":\"unbound\"}"); f_check_encoding(encoded := f_enc_meta_set(s), expected := os); f_bool2verdict( log2str(f_dec_meta_set(os)) == log2str(s) ); // positive decoding tests (these cannot be produced by the encoder, but are still accepted by the decoder) os := char2oct("{ \"int\" : 3, \"str\" : \"abc\", \"octets\" : \"1234\", \"metainfo int\" : \"unbound\" }"); var MetainfoSet res := { str := "abc", octets := '1234'O }; f_bool2verdict( log2str(f_dec_meta_set(os)) == log2str(res) ); os := char2oct("{ \"metainfo int\" : \"unbound\", \"int\" : null, \"str\" : \"abc\", \"octets\" : \"1234\" }"); f_bool2verdict( log2str(f_dec_meta_set(os)) == log2str(res) ); // same expected result } // Negative tests for decoding with the unbound meta info attribute testcase tc_attribute_metainfo_for_unbound_negtest() runs on MTC { var octetstring os := char2oct("{ \"metainfo num\" : \"unbound\", \"num\" : 6, \"str\" : \"qwe\" }"); var MetainfoRecord dummyRec; @try { dummyRec := f_dec_meta_rec(os); setverdict(fail, "Expected error when decoding ", os); } @catch (msg) { if (not match (msg, pattern "*Meta info not applicable to field 'num'")) { setverdict(fail, "Unexpected error message when decoding ", os, " (msg: ", msg, ")"); } } os := char2oct("{ \"metainfo dummy\" : \"unbound\", \"num\" : 6, \"str\" : \"qwe\" }"); @try { dummyRec := f_dec_meta_rec(os); setverdict(fail, "Expected error when decoding ", os); } @catch (msg) { if (not match (msg, pattern "*Meta info provided for non-existent field 'dummy'")) { setverdict(fail, "Unexpected error message when decoding ", os, " (msg: ", msg, ")"); } } os := char2oct("{ \"int\" : 3, \"str\" : \"abc\", \"octets\" : \"1234\", \"metainfo int\" : \"bound\" }"); var MetainfoSet dummySet; @try { dummySet := f_dec_meta_set(os); setverdict(fail, "Expected error when decoding ", os); } @catch (msg) { if (not match (msg, pattern "*Invalid meta info for field 'num'")) { setverdict(fail, "Unexpected error message when decoding ", os, " (msg: ", msg, ")"); } } os := char2oct("{ \"int\" : 3, \"str\" : \"abc\", \"octets\" : \"1234\", \"metainfo int\" : 88 }"); @try { dummySet := f_dec_meta_set(os); setverdict(fail, "Expected error when decoding ", os); } @catch (msg) { if (not match (msg, pattern "*Invalid meta info for field 'num'")) { setverdict(fail, "Unexpected error message when decoding ", os, " (msg: ", msg, ")"); } } os := char2oct("{ \"int\" : null, \"str\" : \"abc\", \"octets\" : \"1234\" }"); @try { dummySet := f_dec_meta_set(os); setverdict(fail, "Expected error when decoding ", os); } @catch (msg) { if (not match (msg, pattern "*Invalid JSON token found while decoding field 'num'")) { setverdict(fail, "Unexpected error message when decoding ", os, " (msg: ", msg, ")"); } } os := char2oct("{ \"metainfo int\" : \"unbound\", \"int\" : [ 1, 3 ], \"str\" : \"abc\", \"octets\" : \"1234\" }"); @try { dummySet := f_dec_meta_set(os); setverdict(fail, "Expected error when decoding ", os); } @catch (msg) { if (not match (msg, pattern "*Invalid JSON token found while decoding field 'num'")) { setverdict(fail, "Unexpected error message when decoding ", os, " (msg: ", msg, ")"); } } setverdict(pass); } // Decoding test for the 'metainfo for unbound' attribute, where all fields of an embedded record are // set to unbound by meta info. The decoded embedded record should be unbound. testcase tc_attribute_metainfo_for_unbound_empty_rec() runs on MTC { var charstring dec_str := "{\"mynum\":99,\"mystr\":\"aa\", \"myRec\": {\"num\":null,\"metainfo num\":\"unbound\",\"str\":null,\"metainfo str\":\"unbound\" } }"; var MetainfoOuterRecord dec_val := f_dec_meta_outer_rec(char2oct(dec_str)); if (isbound(dec_val.myRec)) { setverdict(fail, "Field myrec should be unbound after decoding, instead of ", dec_val.myRec); } var MetainfoOuterRecord dec_val_exp := { mynum := 99, mystr := "aa", myRec := - }; if (log2str(dec_val) != log2str(dec_val_exp)) { setverdict(fail, "Invalid value after decoding. Expected: ", dec_val_exp, ", got: ", dec_val); } setverdict(pass); } // Encoding array types with unbound elements with meta info (attribute 'metainfo for unbound') // A JSON object with one key-value pair (containing the meta info) specifies that an element is unbound. testcase tc_attribute_metainfo_for_unbound_arrays() runs on MTC { // test 1: pre-generated array type (record of integer) var MetainfoRecOf recof := { 1, 2, -, 4 }; var octetstring os := char2oct("[1,2,{\"metainfo []\":\"unbound\"},4]"); f_check_encoding(encoded := f_enc_meta_recof(recof), expected := os); f_bool2verdict( log2str(f_dec_meta_recof(os)) == log2str(recof) ); // test 2: array of a structured type (set of MetainfoRecord) var MetainfoSetOf setof := { { num := 3, str := "abc" }, -, { num := 6 } }; os := char2oct("[{\"num\":3,\"str\":\"abc\"},{\"metainfo []\":\"unbound\"},{\"num\":6,\"str\":null,\"metainfo str\":\"unbound\"}]"); f_check_encoding(encoded := f_enc_meta_setof(setof), expected := os); f_bool2verdict( log2str(f_dec_meta_setof(os)) == log2str(setof) ); // test 3: TTCN-3 array (float [3]) var MetainfoArray arr := { 3.0, 6.0, - }; os := char2oct("[3.000000,6.000000,{\"metainfo []\":\"unbound\"}]"); f_check_encoding(encoded := f_enc_meta_arr(arr), expected := os); f_bool2verdict( log2str(f_dec_meta_arr(os)) == log2str(arr) ); } control { execute(tc_NoAttributeOnUpperLevel()) execute(tc_name_as_omit_as_null()); execute(tc_name_as()); execute(tc_name_as_with_keywords()); execute(tc_attribute_compactprint1()); execute(tc_attribute_compactprint2()); execute(tc_attribute_compactprintp()); execute(tc_attribute_prettyprint1()); execute(tc_attribute_prettyprint2()); execute(tc_attribute_union()); execute(tc_attribute_as_value()); //execute(tc_attribute_default()); execute(tc_attribute_as_value_asn()); execute(tc_attribute_optional_as_value()); execute(tc_attribute_metainfo_for_unbound()); execute(tc_attribute_metainfo_for_unbound_negtest()); execute(tc_attribute_metainfo_for_unbound_empty_rec()); execute(tc_attribute_metainfo_for_unbound_arrays()); } }