/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Balasko, Jeno
 *   Baranyi, Botond
 *   Raduly, Csaba
 *
 ******************************************************************************/
module Txersets
{
modulepar boolean Txersets_verbose := false;
#define verbose Txersets_verbose

#include "../macros.ttcnin"

external function flatten(inout universal charstring par) ;

import from Sets all;
import from SetValues all;
import from AsnValues all;

DECLARE_XER_ENCODERS(Sobs, sobs); // bitstring
DECLARE_EXER_ENCODERS(Sobs,sobs);
DECLARE_XER_ENCODERS(Sobo, sobo); // bool
DECLARE_EXER_ENCODERS(Sobo,sobo);
DECLARE_XER_ENCODERS(Soc, soc); // choice
DECLARE_EXER_ENCODERS(Soc,soc);
DECLARE_XER_ENCODERS(Sopdv, sopdv);
DECLARE_EXER_ENCODERS(Sopdv,sopdv);
DECLARE_XER_ENCODERS(Soen, soen); // enum
DECLARE_EXER_ENCODERS(Soen,soen);
DECLARE_XER_ENCODERS(Soex, soex); // external
DECLARE_EXER_ENCODERS(Soex,soex);
//-- DECLARE_XER_ENCODERS(Soin, soin);
//-- DECLARE_EXER_ENCODERS(Soin,soin);
DECLARE_XER_ENCODERS(Soi, soi); // int
DECLARE_EXER_ENCODERS(Soi,soi);
DECLARE_XER_ENCODERS(Son, son); // NULL
DECLARE_EXER_ENCODERS(Son,son);
//-- DECLARE_XER_ENCODERS(Socsf, socsf);
//-- DECLARE_EXER_ENCODERS(Socsf,socsf)
DECLARE_XER_ENCODERS(Soid, soid); // objid
DECLARE_EXER_ENCODERS(Soid,soid);
DECLARE_XER_ENCODERS(Soos, soos); // octetstring
DECLARE_EXER_ENCODERS(Soos,soos);
DECLARE_XER_ENCODERS(Sor, sor); // real
DECLARE_EXER_ENCODERS(Sor,sor);
DECLARE_XER_ENCODERS(Soroid, soroid); // relative oid
DECLARE_EXER_ENCODERS(Soroid,soroid);
DECLARE_XER_ENCODERS(So_bmp, sobmp); // BMPstring
DECLARE_EXER_ENCODERS(So_bmp,sobmp);
DECLARE_XER_ENCODERS(So_gen, sogen); // GeneralString
DECLARE_EXER_ENCODERS(So_gen,sogen);
DECLARE_XER_ENCODERS(So_gra, sogra); // GraphicString
DECLARE_EXER_ENCODERS(So_gra,sogra);
DECLARE_XER_ENCODERS(So_ia5, soia5); // IA5String
DECLARE_EXER_ENCODERS(So_ia5,soia5);
DECLARE_XER_ENCODERS(So_num, sonum); // NumericString
DECLARE_EXER_ENCODERS(So_num,sonum);
DECLARE_XER_ENCODERS(So_prn, soprn); // PrintableString
DECLARE_EXER_ENCODERS(So_prn,soprn);
DECLARE_XER_ENCODERS(So_ttx, sottx); // TeletexString
DECLARE_EXER_ENCODERS(So_ttx,sottx);
//-- same as above: DECLARE_XER_ENCODERS(So_t61, sot61);
//DECLARE_EXER_ENCODERS(So_t61,sot61);
DECLARE_XER_ENCODERS(So_uni, souni); // UniversalString
DECLARE_EXER_ENCODERS(So_uni,souni);
DECLARE_XER_ENCODERS(So_utf, soutf); // UTF8String
DECLARE_EXER_ENCODERS(So_utf,soutf);
DECLARE_XER_ENCODERS(So_vtx, sovtx); // VideotexString
DECLARE_EXER_ENCODERS(So_vtx,sovtx);
DECLARE_XER_ENCODERS(So_vis, sovis); // VisibleString
DECLARE_EXER_ENCODERS(So_vis,sovis);
//-- same as above: DECLARE_XER_ENCODERS(So_646, so646);
//DECLARE_EXER_ENCODERS(So_646,so646);
DECLARE_XER_ENCODERS(So_unr, sounr); // big, scary, unrestricted CHARACTER STRING
DECLARE_EXER_ENCODERS(So_unr,sounr);

DECLARE_XER_ENCODERS(Sosel, sosel); // selection type
DECLARE_EXER_ENCODERS(Sosel,sosel);
DECLARE_XER_ENCODERS(Sonc , sonc); // named choice
DECLARE_EXER_ENCODERS(Sonc, sonc);

type component Tsets {}

//-------------------- SET OF BIT STRING --------------------

const charstring sobs0 :=
"<Sobs/>\n\n";

const charstring sobs1 :=
"<Sobs>\n" &
"\t<BIT_STRING>" &
"1110010110010011011110111010110111100111010110100110111011" &
"</BIT_STRING>\n" &
"</Sobs>\n\n";

const charstring sobs2 :=
"<Sobs>\n" &
"\t<BIT_STRING>" &
"1110010110010011011110111010110111100111010110100110111011" &
"</BIT_STRING>\n" &
"\t<BIT_STRING/>\n" &
"</Sobs>\n\n";


testcase enc_sobs() runs on Tsets
{
  var universal charstring expected;

  expected := sobs0;
  CHECK_METHOD(bxer_enc_sobs, sobs_0, expected);
  CHECK_METHOD(exer_enc_sobs, sobs_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobs, sobs_0, expected & lf);

  expected := sobs1;
  CHECK_METHOD(bxer_enc_sobs, sobs_1, expected);
  CHECK_METHOD(exer_enc_sobs, sobs_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobs, sobs_1, expected & lf);

  expected := sobs2;
  CHECK_METHOD(bxer_enc_sobs, sobs_2, expected);
  CHECK_METHOD(exer_enc_sobs, sobs_2, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobs, sobs_2, expected & lf);
}

testcase dec_sobs() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sobs, sobs0, Sobs, sobs_0);
  CHECK_DECODE(exer_dec_sobs, sobs0, Sobs, sobs_0);

  CHECK_DECODE2(        sobs, sobs1, Sobs, sobs_1);
  CHECK_DECODE(exer_dec_sobs, sobs1, Sobs, sobs_1);

  CHECK_DECODE2(        sobs, sobs2, Sobs, sobs_2);
  CHECK_DECODE(exer_dec_sobs, sobs2, Sobs, sobs_2);
}

//-------------------- SET OF BOOELAN --------------------

const charstring sobo0 :=
"<Sobo/>\n\n";

const charstring sobo1 :=
"<Sobo>\n" &
"\t<true/>\n" &
"</Sobo>\n\n";

const charstring sobo1_exer :=
"<Sobo>\n" &
"\t<BOOLEAN>true</BOOLEAN>\n" &
"</Sobo>\n\n";

const charstring sobo3 :=
"<Sobo>\n" &
"\t<true/><false/><true/>\n" &
"</Sobo>\n\n";

const charstring sobo3_exer :=
"<Sobo>\n" &
"\t<BOOLEAN>true</BOOLEAN>\n" &
"\t<BOOLEAN>false</BOOLEAN>\n" &
"\t<BOOLEAN>true</BOOLEAN>\n" &
"</Sobo>\n\n";

testcase enc_sobo() runs on Tsets
{
  var universal charstring expected;

  expected := sobo0;
  CHECK_METHOD(bxer_enc_sobo, sobo_0, expected);
  CHECK_METHOD(exer_enc_sobo, sobo_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobo, sobo_0, expected & lf);

  expected := sobo1;
  CHECK_METHOD(bxer_enc_sobo, sobo_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobo, sobo_1, expected & lf);
  expected := sobo1_exer;
  CHECK_METHOD(exer_enc_sobo, sobo_1, expected);

  expected := sobo3;
  CHECK_METHOD(bxer_enc_sobo, sobo_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobo, sobo_3, expected & lf);
  expected := sobo3_exer;
  CHECK_METHOD(exer_enc_sobo, sobo_3, expected);
}

testcase dec_sobo() runs on Tsets
{
  // decoder suffix, inp, type, expected
  CHECK_DECODE2(        sobo, sobo0, Sobo, sobo_0);
  CHECK_DECODE(exer_dec_sobo, sobo0, Sobo, sobo_0);

  CHECK_DECODE2(        sobo, sobo1, Sobo, sobo_1);
  CHECK_DECODE(exer_dec_sobo, sobo1_exer, Sobo, sobo_1);

  CHECK_DECODE2(        sobo, sobo3, Sobo, sobo_3);
  CHECK_DECODE(exer_dec_sobo, sobo3_exer, Sobo, sobo_3);
}

//-------------------- SET OF CHOICE --------------------

const charstring soc0 :=
"<Soc/>\n\n";

const charstring soc1 :=
"<Soc>\n" &
"\t<is>9.109382e-31</is>\n" &
"</Soc>\n\n";

const charstring soc1_exer :=
"<Soc>\n" &
"\t<CHOICE>\n" &
"\t\t<is>9.109382e-31</is>\n" &
"\t</CHOICE>\n" &
"</Soc>\n\n";

const charstring soc3_exer :=
"<Soc>\n" &
"\t<CHOICE>\n" &
"\t\t<is>0.841471</is>\n" &
"\t</CHOICE>\n" &
"\t<CHOICE>\n" &
"\t\t<is>0.909297</is>\n" &
"\t</CHOICE>\n" &
"\t<CHOICE>\n" &
"\t\t<is>0.141120</is>\n" &
"\t</CHOICE>\n" &
"</Soc>\n\n";

const charstring soc3 :=
"<Soc>\n" &
"\t<is>0.841471</is>\n" &
"\t<is>0.909297</is>\n" &
"\t<is>0.141120</is>\n" &
"</Soc>\n\n";

const charstring sonc0 :=
"<Sonc/>\n\n";

const charstring sonc1 :=
"<Sonc>\n" &
"\t<is>9.109382e-31</is>\n" &
"</Sonc>\n\n";

const charstring sonc1_exer :=
"<Sonc>\n" &
"\t<NamedChoice>\n" &
"\t\t<is>9.109382e-31</is>\n" &
"\t</NamedChoice>\n" &
"</Sonc>\n\n";

const charstring sonc3 :=
"<Sonc>\n" &
"\t<is>0.841471</is>\n" &
"\t<is>0.909297</is>\n" &
"\t<is>0.141120</is>\n" &
"</Sonc>\n\n";

const charstring sonc3_exer :=
"<Sonc>\n" &
"\t<NamedChoice>\n" &
"\t\t<is>0.841471</is>\n" &
"\t</NamedChoice>\n" &
"\t<NamedChoice>\n" &
"\t\t<is>0.909297</is>\n" &
"\t</NamedChoice>\n" &
"\t<NamedChoice>\n" &
"\t\t<is>0.141120</is>\n" &
"\t</NamedChoice>\n" &
"</Sonc>\n\n";

testcase enc_soc() runs on Tsets
{
  var universal charstring expected;

  expected := soc0;
  CHECK_METHOD(bxer_enc_soc, soc_0, expected);
  CHECK_METHOD(exer_enc_soc, soc_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soc, soc_0, expected & lf);

  expected := soc1;
  CHECK_METHOD(bxer_enc_soc, soc_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soc, soc_1, expected & lf);
  expected := soc1_exer;
  CHECK_METHOD(exer_enc_soc, soc_1, expected);

  expected := soc3;
  CHECK_METHOD(bxer_enc_soc, soc_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soc, soc_3, expected & lf);
  expected := soc3_exer;
  CHECK_METHOD(exer_enc_soc, soc_3, expected);

  /* Now for a named choice */

  expected := sonc0;
  CHECK_METHOD(bxer_enc_sonc, sonc_0, expected);
  CHECK_METHOD(exer_enc_sonc, sonc_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sonc, sonc_0, expected & lf);

  expected := sonc1;
  CHECK_METHOD(bxer_enc_sonc, sonc_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sonc, sonc_1, expected & lf);
  expected := sonc1_exer;
  CHECK_METHOD(exer_enc_sonc, sonc_1, expected);

  expected := sonc3;
  CHECK_METHOD(bxer_enc_sonc, sonc_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sonc, sonc_3, expected & lf);
  expected := sonc3_exer;
  CHECK_METHOD(exer_enc_sonc, sonc_3, expected);
}

testcase dec_soc() runs on Tsets
{
  // decoder suffix, inp, type, expected
  CHECK_DECODE2(soc, soc0, Soc, soc_0);
  CHECK_DECODE2(soc, soc1, Soc, soc_1);
  CHECK_DECODE2(soc, soc3, Soc, soc_3);

  CHECK_DECODE2(sonc, sonc0, Sonc, sonc_0);
  CHECK_DECODE2(sonc, sonc1, Sonc, sonc_1);
  CHECK_DECODE2(sonc, sonc3, Sonc, sonc_3);
}

//-------------------- SET OF EMBEDDED PDV --------------------

const charstring sopdv0 :=
"<Sopdv/>\n\n";

const charstring sopdv1 :=
"<Sopdv>\n" &
"\t<SEQUENCE>\n" &
"\t\t<identification>\n" &
"\t\t\t<syntax>0.4.0.1.3.5</syntax>\n" &
"\t\t</identification>\n" &
"\t\t<data-value>DECAFBAD</data-value>\n" &
"\t</SEQUENCE>\n" &
"</Sopdv>\n\n";

testcase enc_sopdv() runs on Tsets
{
  var universal charstring expected;

  expected := sopdv0;
  CHECK_METHOD(bxer_enc_sopdv, sopdv_0, expected);
  CHECK_METHOD(exer_enc_sopdv, sopdv_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sopdv, sopdv_0, expected & lf);

  expected := sopdv1;
  CHECK_METHOD(bxer_enc_sopdv, sopdv_1, expected);
  CHECK_METHOD(exer_enc_sopdv, sopdv_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sopdv, sopdv_1, expected & lf);
}

testcase dec_sopdv() runs on Tsets
{
  // decoder suffix, inp, type, expected
  CHECK_DECODE2(sopdv, sopdv0, Sopdv, sopdv_0);
  CHECK_DECODE2(sopdv, sopdv1, Sopdv, sopdv_1);
}

//-------------------- SET OF ENUMERATED --------------------

const charstring soen0 :=
"<Soen/>\n\n";

const charstring soen1 :=
"<Soen>\n" &
"\t<fileNotFound/>\n" &
"</Soen>\n\n";

const charstring soen1_exer :=
"<Soen>\n" &
"\t<ENUMERATED>fileNotFound</ENUMERATED>\n" &
"</Soen>\n\n";

const charstring soen3 :=
"<Soen>\n" &
"\t<truee/><falsee/><fileNotFound/>\n" &
"</Soen>\n\n";

const charstring soen3_exer :=
"<Soen>\n" &
"\t<ENUMERATED>truee</ENUMERATED>\n\t<ENUMERATED>falsee</ENUMERATED>\n\t<ENUMERATED>fileNotFound</ENUMERATED>\n" &
"</Soen>\n\n";

testcase enc_soen() runs on Tsets
{
  var universal charstring expected;

  expected := soen0;
  CHECK_METHOD(bxer_enc_soen, soen_0, expected);
  CHECK_METHOD(exer_enc_soen, soen_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soen, soen_0, expected & lf);

  expected := soen1;
  CHECK_METHOD(bxer_enc_soen, soen_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soen, soen_1, expected & lf);
  expected := soen1_exer;
  CHECK_METHOD(exer_enc_soen, soen_1, expected);

  expected := soen3;
  CHECK_METHOD(bxer_enc_soen, soen_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soen, soen_3, expected & lf);
  expected := soen3_exer;
  CHECK_METHOD(exer_enc_soen, soen_3, expected);
}

testcase dec_soen() runs on Tsets
{
  // decoder suffix, inp, type, expected
  CHECK_DECODE2(soen, soen0, Soen, soen_0);
  CHECK_DECODE2(soen, soen1, Soen, soen_1);
  CHECK_DECODE2(soen, soen3, Soen, soen_3);
}

//-------------------- SET OF EXTERNAL --------------------

const charstring soex0 :=
"<Soex/>\n\n";

const charstring soex1 :=
"<Soex>\n" &
"\t<SEQUENCE>\n" &
"\t\t<direct-reference>2.1.1</direct-reference>\n" &
"\t\t<indirect-reference>111</indirect-reference>\n" &
"\t\t<data-value-descriptor>using context negotiation, both</data-value-descriptor>\n" &
"\t\t<encoding>\n" &
"\t\t\t<octet-aligned>1337D00D</octet-aligned>\n" &
"\t\t</encoding>\n" &
"\t</SEQUENCE>\n" &
"</Soex>\n\n";

const charstring soex3 :=
"<Soex>\n" &
"\t<SEQUENCE>\n" &
"\t\t<direct-reference>2.1.1</direct-reference>\n" &
"\t\t<indirect-reference>111</indirect-reference>\n" &
"\t\t<data-value-descriptor>using context negotiation, both</data-value-descriptor>\n" &
"\t\t<encoding>\n" &
"\t\t\t<octet-aligned>1337D00D</octet-aligned>\n" &
"\t\t</encoding>\n" &
"\t</SEQUENCE>\n" &
"\t<SEQUENCE>\n" &
"\t\t<direct-reference>2.1.1</direct-reference>\n" &
"\t\t<indirect-reference>111</indirect-reference>\n" &
"\t\t<data-value-descriptor>using context negotiation, both</data-value-descriptor>\n" &
"\t\t<encoding>\n" &
"\t\t\t<octet-aligned>1337D00D</octet-aligned>\n" &
"\t\t</encoding>\n" &
"\t</SEQUENCE>\n" &
"\t<SEQUENCE>\n" &
"\t\t<direct-reference>2.1.1</direct-reference>\n" &
"\t\t<indirect-reference>111</indirect-reference>\n" &
"\t\t<data-value-descriptor>using context negotiation, both</data-value-descriptor>\n" &
"\t\t<encoding>\n" &
"\t\t\t<octet-aligned>1337D00D</octet-aligned>\n" &
"\t\t</encoding>\n" &
"\t</SEQUENCE>\n" &
"</Soex>\n\n";

testcase enc_soex() runs on Tsets
{
  var universal charstring expected;

  expected := soex0;
  CHECK_METHOD(bxer_enc_soex, soex_0, expected);
  CHECK_METHOD(exer_enc_soex, soex_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soex, soex_0, expected & lf);

  expected := soex1;
  CHECK_METHOD(bxer_enc_soex, soex_1, expected);
  CHECK_METHOD(exer_enc_soex, soex_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soex, soex_1, expected & lf);

  expected := soex3;
  CHECK_METHOD(bxer_enc_soex, soex_3, expected);
  CHECK_METHOD(exer_enc_soex, soex_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soex, soex_3, expected & lf);
}

testcase dec_soex() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(soex, soex0, Soex, soex_0);

  CHECK_DECODE2(soex, soex1, Soex, soex_1);

  CHECK_DECODE2(soex, soex3, Soex, soex_3);
}

//-------------------- SET OF INTEGER --------------------

const charstring soi0 :=
"<Soi/>\n\n";

const charstring soi1 :=
"<Soi>\n" &
"\t<INTEGER>42</INTEGER>\n" &
"</Soi>\n\n";

const charstring soi3 :=
"<Soi>\n" &
"\t<INTEGER>21</INTEGER>\n" &
"\t<INTEGER>1211</INTEGER>\n" &
"\t<INTEGER>111221</INTEGER>\n" &
"</Soi>\n" &
lf;

testcase enc_soint() runs on Tsets
{
  var universal charstring expected;

  expected := soi0;
  CHECK_METHOD(bxer_enc_soi, soi_0, expected);
  CHECK_METHOD(exer_enc_soi, soi_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soi, soi_0, expected & lf);

  expected := soi1;
  CHECK_METHOD(bxer_enc_soi, soi_1, expected);
  CHECK_METHOD(exer_enc_soi, soi_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soi, soi_1, expected & lf);

  expected := soi3;
  CHECK_METHOD(bxer_enc_soi, soi_3, expected);
  CHECK_METHOD(exer_enc_soi, soi_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soi, soi_3, expected & lf);
}

testcase dec_soint() runs on Tsets
{
  //    type suffix, input, type, expected
  CHECK_DECODE2(soi, soi0, Soi, soi_0);

  CHECK_DECODE2(soi, soi1, Soi, soi_1);

  CHECK_DECODE2(soi, soi3, Soi, soi_3);
}

//-------------------- SET OF NULL --------------------

const charstring son0 :=
"<Son/>\n\n";

const charstring son1 :=
"<Son>\n" &
"\t<NULL/>\n" &
"</Son>\n\n";

const charstring son1_exer :=
"<Son>\n" &
"<NULL/>" &
"</Son>\n\n";

const charstring son3 :=
"<Son>\n" &
"\t<NULL/><NULL/><NULL/>\n" &
"</Son>\n\n" ;

const charstring son3_exer :=
"<Son>\n" &
"<NULL/><NULL/><NULL/>" &
"</Son>\n\n" ;

testcase enc_son() runs on Tsets
{
  var universal charstring expected;

  expected := son0;
  CHECK_METHOD(bxer_enc_son, son_0, expected);
  CHECK_METHOD(exer_enc_son, son_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_son, son_0, expected & lf);

  expected := son1;
  CHECK_METHOD(bxer_enc_son, son_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_son, son_1, expected & lf);
  expected := son1_exer;
  CHECK_METHOD(exer_enc_son, son_1, expected);

  expected := son3;
  CHECK_METHOD(bxer_enc_son, son_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_son, son_3, expected & lf);
  expected := son3_exer;
  CHECK_METHOD(exer_enc_son, son_3, expected);
}

testcase dec_son() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        son, son0, Son, son_0);
  CHECK_DECODE(exer_dec_son, son0, Son, son_0);

  CHECK_DECODE2(        son, son1, Son, son_1);
  CHECK_DECODE(exer_dec_son, son1, Son, son_1);

  CHECK_DECODE2(        son, son3, Son, son_3);
  CHECK_DECODE(exer_dec_son, son3, Son, son_3);
}

//-------------------- SET OF OBJECT IDENTIFIER --------------------

const charstring soid0 :=
"<Soid/>\n\n";

const charstring soid1 :=
"<Soid>\n" &
"\t<OBJECT_IDENTIFIER>1.2.3.4</OBJECT_IDENTIFIER>\n" &
"</Soid>\n\n";

const charstring soid3 :=
"<Soid>\n" &
"\t<OBJECT_IDENTIFIER>0.4.0</OBJECT_IDENTIFIER>\n" &
"\t<OBJECT_IDENTIFIER>0.4.0.127.0.5</OBJECT_IDENTIFIER>\n" &
"\t<OBJECT_IDENTIFIER>2.6.6.1.2.4.4</OBJECT_IDENTIFIER>\n" &
"</Soid>\n" &
lf;

testcase enc_soid() runs on Tsets
{
  var universal charstring expected;

  expected := soid0;
  CHECK_METHOD(bxer_enc_soid, soid_0, expected);
  CHECK_METHOD(exer_enc_soid, soid_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soid, soid_0, expected & lf);

  expected := soid1;
  CHECK_METHOD(bxer_enc_soid, soid_1, expected);
  CHECK_METHOD(exer_enc_soid, soid_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soid, soid_1, expected & lf);

  expected := soid3;
  CHECK_METHOD(bxer_enc_soid, soid_3, expected);
  CHECK_METHOD(exer_enc_soid, soid_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soid, soid_3, expected & lf);
}

testcase dec_soid() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        soid, soid0, Soid, soid_0);
  CHECK_DECODE(exer_dec_soid, soid0, Soid, soid_0);

  CHECK_DECODE2(        soid, soid1, Soid, soid_1);
  CHECK_DECODE(exer_dec_soid, soid1, Soid, soid_1);

  CHECK_DECODE2(        soid, soid3, Soid, soid_3);
  CHECK_DECODE(exer_dec_soid, soid3, Soid, soid_3);
}

//-------------------- SET OF OCTET STRING --------------------

const charstring soos0 :=
"<Soos/>\n\n";

const charstring soos1 :=
"<Soos>\n" &
"\t<OCTET_STRING>13211311123113112211</OCTET_STRING>\n" &
"</Soos>\n\n";

const charstring soos3 :=
"<Soos>\n" &
"\t<OCTET_STRING>1123</OCTET_STRING>\n" &
"\t<OCTET_STRING>5813</OCTET_STRING>\n" &
"\t<OCTET_STRING/>\n" &
"</Soos>\n\n";


testcase enc_soos() runs on Tsets
{
  var universal charstring expected;

  expected := soos0;
  CHECK_METHOD(bxer_enc_soos, soos_0, expected);
  CHECK_METHOD(exer_enc_soos, soos_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soos, soos_0, expected & lf);

  expected := soos1;
  CHECK_METHOD(bxer_enc_soos, soos_1, expected);
  CHECK_METHOD(exer_enc_soos, soos_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soos, soos_1, expected & lf);

  expected := soos3;
  CHECK_METHOD(bxer_enc_soos, soos_3, expected);
  CHECK_METHOD(exer_enc_soos, soos_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soos, soos_3, expected & lf);
}

testcase dec_soos() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        soos, soos0, Soos, soos_0);
  CHECK_DECODE(exer_dec_soos, soos0, Soos, soos_0);

  CHECK_DECODE2(        soos, soos1, Soos, soos_1);
  CHECK_DECODE(exer_dec_soos, soos1, Soos, soos_1);

  CHECK_DECODE2(        soos, soos3, Soos, soos_3);
  CHECK_DECODE(exer_dec_soos, soos3, Soos, soos_3);
}

//-------------------- SET OF REAL --------------------

const charstring sor0 :=
"<Sor/>\n\n";

const charstring sor1 :=
"<Sor>\n" &
"\t<REAL>1.602176e-19</REAL>\n" &
"</Sor>\n\n";

const charstring sor3 :=
"<Sor>\n" &
"\t<REAL>0.540302</REAL>\n" &
"\t<REAL>-0.416147</REAL>\n" &
"\t<REAL>-0.989992</REAL>\n" &
"</Sor>\n" &
lf;

testcase enc_sor() runs on Tsets
{
  var universal charstring expected;

  expected := sor0;
  CHECK_METHOD(bxer_enc_sor, sor_0, expected);
  CHECK_METHOD(exer_enc_sor, sor_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sor, sor_0, expected & lf);

  expected := sor1;
  CHECK_METHOD(bxer_enc_sor, sor_1, expected);
  CHECK_METHOD(exer_enc_sor, sor_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sor, sor_1, expected & lf);

  expected := sor3;
  CHECK_METHOD(bxer_enc_sor, sor_3, expected);
  CHECK_METHOD(exer_enc_sor, sor_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sor, sor_3, expected & lf);
}

testcase dec_sor() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sor, sor0, Sor, sor_0);
  CHECK_DECODE(exer_dec_sor, sor0, Sor, sor_0);

  CHECK_DECODE2(        sor, sor1, Sor, sor_1);
  CHECK_DECODE(exer_dec_sor, sor1, Sor, sor_1);

  CHECK_DECODE2(        sor, sor3, Sor, sor_3);
  CHECK_DECODE(exer_dec_sor, sor3, Sor, sor_3);
}

//-------------------- SET OF RELATIVE-OID --------------------

const charstring soroid0 :=
"<Soroid/>\n\n";

const charstring soroid1 :=
"<Soroid>\n" &
"\t<RELATIVE_OID>4.3.2.1</RELATIVE_OID>\n" &
"</Soroid>\n\n";

const charstring soroid3 :=
"<Soroid>\n" &
"\t<RELATIVE_OID>1</RELATIVE_OID>\n" &
"\t<RELATIVE_OID>1.1</RELATIVE_OID>\n" &
"\t<RELATIVE_OID>1.1.1</RELATIVE_OID>\n" &
"</Soroid>\n\n";

testcase enc_soroid() runs on Tsets
{
  var universal charstring expected;

  expected := soroid0;
  CHECK_METHOD(bxer_enc_soroid, soroid_0, expected);
  CHECK_METHOD(exer_enc_soroid, soroid_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soroid, soroid_0, expected & lf);

  expected := soroid1;
  CHECK_METHOD(bxer_enc_soroid, soroid_1, expected);
  CHECK_METHOD(exer_enc_soroid, soroid_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soroid, soroid_1, expected & lf);

  expected := soroid3;
  CHECK_METHOD(bxer_enc_soroid, soroid_3, expected);
  CHECK_METHOD(exer_enc_soroid, soroid_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soroid, soroid_3, expected & lf);
}

testcase dec_soroid() runs on Tsets
{
  //       type suffix, input, type, expected
  CHECK_DECODE2(        soroid, soroid0, Soroid, soroid_0);
  CHECK_DECODE(exer_dec_soroid, soroid0, Soroid, soroid_0);

  CHECK_DECODE2(        soroid, soroid1, Soroid, soroid_1);
  CHECK_DECODE(exer_dec_soroid, soroid1, Soroid, soroid_1);

  CHECK_DECODE2(        soroid, soroid3, Soroid, soroid_3);
  CHECK_DECODE(exer_dec_soroid, soroid3, Soroid, soroid_3);
}

//-------------------- SET OF BMPString --------------------

const charstring sobmp0 :=
"<So-bmp/>\n\n";

const charstring sobmp1 :=
"<So-bmp>\n" &
"\t<BMPString>BMP</BMPString>\n" &
"</So-bmp>\n\n";

const charstring sobmp3 :=
"<So-bmp>\n" &
"\t<BMPString>Bee</BMPString>\n" &
"\t<BMPString>Emm</BMPString>\n" &
"\t<BMPString>Pee</BMPString>\n" &
"\t<BMPString/>\n" &
"</So-bmp>\n\n";

testcase enc_sobmp() runs on Tsets
{
  var universal charstring expected;

  expected := sobmp0;
  CHECK_METHOD(bxer_enc_sobmp, so_bmp_0, expected);
  CHECK_METHOD(exer_enc_sobmp, so_bmp_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobmp, so_bmp_0, expected & lf);

  expected := sobmp1;
  CHECK_METHOD(bxer_enc_sobmp, so_bmp_1, expected);
  CHECK_METHOD(exer_enc_sobmp, so_bmp_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobmp, so_bmp_1, expected & lf);

  expected := sobmp3;
  CHECK_METHOD(bxer_enc_sobmp, so_bmp_3, expected);
  CHECK_METHOD(exer_enc_sobmp, so_bmp_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sobmp, so_bmp_3, expected & lf);
}

testcase dec_sobmp() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sobmp, sobmp0, So_bmp, so_bmp_0);
  CHECK_DECODE(exer_dec_sobmp, sobmp0, So_bmp, so_bmp_0);

  CHECK_DECODE2(        sobmp, sobmp1, So_bmp, so_bmp_1);
  CHECK_DECODE(exer_dec_sobmp, sobmp1, So_bmp, so_bmp_1);

  CHECK_DECODE2(        sobmp, sobmp3, So_bmp, so_bmp_3);
  CHECK_DECODE(exer_dec_sobmp, sobmp3, So_bmp, so_bmp_3);
}

//-------------------- SET OF GeneralString --------------------

const charstring sogen0 :=
"<So-gen/>\n\n";

const charstring sogen1 :=
"<So-gen>\n" &
"\t<GeneralString>general</GeneralString>\n" &
"</So-gen>\n\n";

const charstring sogen3 :=
"<So-gen>\n" &
"\t<GeneralString>Alexis Alexander</GeneralString>\n" &
"\t<GeneralString>&apos;Anvil&apos; Shin Fai</GeneralString>\n" &
"\t<GeneralString>Rodall &quot;Demo&quot; Juhziz</GeneralString>\n" &
"\t<GeneralString/>\n" &
"</So-gen>\n\n";

testcase enc_sogen() runs on Tsets
{
  var universal charstring expected;

  expected := sogen0;
  CHECK_METHOD(bxer_enc_sogen, so_gen_0, expected);
  CHECK_METHOD(exer_enc_sogen, so_gen_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sogen, so_gen_0, expected & lf);

  expected := sogen1;
  CHECK_METHOD(bxer_enc_sogen, so_gen_1, expected);
  CHECK_METHOD(exer_enc_sogen, so_gen_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sogen, so_gen_1, expected & lf);

  expected := sogen3;
  CHECK_METHOD(bxer_enc_sogen, so_gen_3, expected);
  CHECK_METHOD(exer_enc_sogen, so_gen_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sogen, so_gen_3, expected & lf);
}

testcase dec_sogen() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(sogen, sogen0, So_gen, so_gen_0);
  CHECK_DECODE(exer_dec_sogen, sogen0, So_gen, so_gen_0);

  CHECK_DECODE2(        sogen, sogen1, So_gen, so_gen_1);
  CHECK_DECODE(exer_dec_sogen, sogen1, So_gen, so_gen_1);

  CHECK_DECODE2(        sogen, sogen3, So_gen, so_gen_3);
  CHECK_DECODE(exer_dec_sogen, sogen3, So_gen, so_gen_3);
}

//-------------------- SET OF GraphicString --------------------

const charstring sogra0 :=
"<So-gra/>\n\n";

const charstring sogra1 :=
"<So-gra>\n" &
"\t<GraphicString>graphic</GraphicString>\n" &
"</So-gra>\n\n";

const charstring sogra3 :=
"<So-gra>\n" &
"\t<GraphicString>3dfx</GraphicString>\n" &
"\t<GraphicString>nVidia</GraphicString>\n" &
"\t<GraphicString>Matrox</GraphicString>\n" &
"\t<GraphicString/>\n" &
"</So-gra>\n\n";

testcase enc_sogra() runs on Tsets
{
  var universal charstring expected;

  expected := sogra0;
  CHECK_METHOD(bxer_enc_sogra, so_gra_0, expected);
  CHECK_METHOD(exer_enc_sogra, so_gra_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sogra, so_gra_0, expected & lf);

  expected := sogra1;
  CHECK_METHOD(bxer_enc_sogra, so_gra_1, expected);
  CHECK_METHOD(exer_enc_sogra, so_gra_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sogra, so_gra_1, expected & lf);

  expected := sogra3;
  CHECK_METHOD(bxer_enc_sogra, so_gra_3, expected);
  CHECK_METHOD(exer_enc_sogra, so_gra_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sogra, so_gra_3, expected & lf);
}


testcase dec_sogra() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sogra, sogra0, So_gra, so_gra_0);
  CHECK_DECODE(exer_dec_sogra, sogra0, So_gra, so_gra_0);

  CHECK_DECODE2(        sogra, sogra1, So_gra, so_gra_1);
  CHECK_DECODE(exer_dec_sogra, sogra1, So_gra, so_gra_1);

  CHECK_DECODE2(        sogra, sogra3, So_gra, so_gra_3);
  CHECK_DECODE(exer_dec_sogra, sogra3, So_gra, so_gra_3);
}

//-------------------- SET OF IA5String --------------------

const charstring soia50 :=
"<So-ia5/>\n\n";

const charstring soia51 :=
"<So-ia5>\n" &
"\t<IA5String>IA5</IA5String>\n" &
"</So-ia5>\n\n";

const charstring soia53 :=
"<So-ia5>\n" &
"\t<IA5String>IA5</IA5String>\n" &
"\t<IA5String>IA5</IA5String>\n" &
"\t<IA5String>Cthulhu fhtagn!</IA5String>\n" &
"\t<IA5String/>\n" &
"</So-ia5>\n\n";

testcase enc_soia5() runs on Tsets
{
  var universal charstring expected;

  expected := soia50;
  CHECK_METHOD(bxer_enc_soia5, so_ia5_0, expected);
  CHECK_METHOD(exer_enc_soia5, so_ia5_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soia5, so_ia5_0, expected & lf);

  expected := soia51;
  CHECK_METHOD(bxer_enc_soia5, so_ia5_1, expected);
  CHECK_METHOD(exer_enc_soia5, so_ia5_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soia5, so_ia5_1, expected & lf);

  expected := soia53;
  CHECK_METHOD(bxer_enc_soia5, so_ia5_3, expected);
  CHECK_METHOD(exer_enc_soia5, so_ia5_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soia5, so_ia5_3, expected & lf);
}


testcase dec_soia5() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        soia5, soia50, So_ia5, so_ia5_0);
  CHECK_DECODE(exer_dec_soia5, soia50, So_ia5, so_ia5_0);

  CHECK_DECODE2(        soia5, soia51, So_ia5, so_ia5_1);
  CHECK_DECODE(exer_dec_soia5, soia51, So_ia5, so_ia5_1);

  CHECK_DECODE2(        soia5, soia53, So_ia5, so_ia5_3);
  CHECK_DECODE(exer_dec_soia5, soia53, So_ia5, so_ia5_3);
}

//-------------------- SET OF NumericString --------------------

const charstring sonum0 :=
"<So-num/>\n\n";

const charstring sonum1 :=
"<So-num>\n" &
"\t<NumericString>666</NumericString>\n" &
"</So-num>\n\n";

const charstring sonum3 :=
"<So-num>\n" &
"\t<NumericString>555</NumericString>\n" &
"\t<NumericString>436</NumericString>\n" &
"\t<NumericString>3747</NumericString>\n" &
"\t<NumericString/>\n" &
"</So-num>\n\n";

testcase enc_sonum() runs on Tsets
{
  var universal charstring expected;

  expected := sonum0;
  CHECK_METHOD(bxer_enc_sonum, so_num_0, expected);
  CHECK_METHOD(exer_enc_sonum, so_num_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sonum, so_num_0, expected & lf);

  expected := sonum1;
  CHECK_METHOD(bxer_enc_sonum, so_num_1, expected);
  CHECK_METHOD(exer_enc_sonum, so_num_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sonum, so_num_1, expected & lf);

  expected := sonum3;
  CHECK_METHOD(bxer_enc_sonum, so_num_3, expected);
  CHECK_METHOD(exer_enc_sonum, so_num_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sonum, so_num_3, expected & lf);
}

testcase dec_sonum() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sonum, sonum0, So_num, so_num_0);
  CHECK_DECODE(exer_dec_sonum, sonum0, So_num, so_num_0);

  CHECK_DECODE2(        sonum, sonum1, So_num, so_num_1);
  CHECK_DECODE(exer_dec_sonum, sonum1, So_num, so_num_1);

  CHECK_DECODE2(        sonum, sonum3, So_num, so_num_3);
  CHECK_DECODE(exer_dec_sonum, sonum3, So_num, so_num_3);
}

//-------------------- SET OF PrintableString --------------------

const charstring soprn0 :=
"<So-prn/>\n\n";

const charstring soprn1 :=
"<So-prn>\n" &
"\t<PrintableString>prn</PrintableString>\n" &
"</So-prn>\n\n";

// This looks like quoted-printable, but it has no special meaning.
// It simply contains more '=' characters than your average text :)
const charstring soprn3 :=
"<So-prn>\n" &
"\t<PrintableString>=E1rv=EDzt=FBr=F5 t=FCk=F6rf=FAr=F3g=E9p</PrintableString>\n" &
"\t<PrintableString>=C1RV=CDZT=DBR=D5 T=DCK=D6RF=DAR=D3G=C9P</PrintableString>\n" &
"\t<PrintableString>A m=F8=F8se once bit my sister</PrintableString>\n" &
"\t<PrintableString/>\n" &
"</So-prn>\n\n";

testcase enc_soprn() runs on Tsets
{
  var universal charstring expected;

  expected := soprn0;
  CHECK_METHOD(bxer_enc_soprn, so_prn_0, expected);
  CHECK_METHOD(exer_enc_soprn, so_prn_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soprn, so_prn_0, expected & lf);

  expected := soprn1;
  CHECK_METHOD(bxer_enc_soprn, so_prn_1, expected);
  CHECK_METHOD(exer_enc_soprn, so_prn_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soprn, so_prn_1, expected & lf);

  expected := soprn3;
  CHECK_METHOD(bxer_enc_soprn, so_prn_3, expected);
  CHECK_METHOD(exer_enc_soprn, so_prn_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soprn, so_prn_3, expected & lf);
}

testcase dec_soprn() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        soprn, soprn0, So_prn, so_prn_0);
  CHECK_DECODE(exer_dec_soprn, soprn0, So_prn, so_prn_0);

  CHECK_DECODE2(        soprn, soprn1, So_prn, so_prn_1);
  CHECK_DECODE(exer_dec_soprn, soprn1, So_prn, so_prn_1);

  CHECK_DECODE2(        soprn, soprn3, So_prn, so_prn_3);
  CHECK_DECODE(exer_dec_soprn, soprn3, So_prn, so_prn_3);
}

//-------------------- SET OF TeletexString --------------------

const charstring sottx0 :=
"<So-ttx/>\n\n";

const charstring sottx1 :=
"<So-ttx>\n" &
"\t<TeletexString>ttx</TeletexString>\n" &
"</So-ttx>\n\n";

const charstring sottx3 :=
"<So-ttx>\n" &
"\t<TeletexString>Tee</TeletexString>\n" &
"\t<TeletexString>Tie</TeletexString>\n" &
"\t<TeletexString>Ecks</TeletexString>\n" &
"\t<TeletexString/>\n" &
"</So-ttx>\n\n";

testcase enc_sottx() runs on Tsets
{
  var universal charstring expected;

  expected := sottx0;
  CHECK_METHOD(bxer_enc_sottx, so_ttx_0, expected);
  CHECK_METHOD(exer_enc_sottx, so_ttx_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sottx, so_ttx_0, expected & lf);

  expected := sottx1;
  CHECK_METHOD(bxer_enc_sottx, so_ttx_1, expected);
  CHECK_METHOD(exer_enc_sottx, so_ttx_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sottx, so_ttx_1, expected & lf);

  expected := sottx3;
  CHECK_METHOD(bxer_enc_sottx, so_ttx_3, expected);
  CHECK_METHOD(exer_enc_sottx, so_ttx_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sottx, so_ttx_3, expected & lf);
}

testcase dec_sottx() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sottx, sottx0, So_ttx, so_ttx_0);
  CHECK_DECODE(exer_dec_sottx, sottx0, So_ttx, so_ttx_0);

  CHECK_DECODE2(        sottx, sottx1, So_ttx, so_ttx_1);
  CHECK_DECODE(exer_dec_sottx, sottx0, So_ttx, so_ttx_0);

  CHECK_DECODE2(        sottx, sottx3, So_ttx, so_ttx_3);
  CHECK_DECODE(exer_dec_sottx, sottx0, So_ttx, so_ttx_0);
}

//-------------------- SET OF UniversalString --------------------

const charstring souni0 :=
"<So-uni/>\n\n";

const charstring souni1 :=
"<So-uni>\n" &
"\t<UniversalString>univ</UniversalString>\n" &
"</So-uni>\n\n";


const charstring souni3 :=
"<So-uni>\n" &
"\t<UniversalString>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;</UniversalString>\n" &
"\t<UniversalString>&lt;html&gt;&lt;head&gt;&lt;/head&gt;</UniversalString>\n" &
"\t<UniversalString>&lt;body onload=&apos;javascript.alert(&quot;Universal&quot;)&apos;&gt;&amp;nbsp;&lt;/body&gt;&lt;/html&gt;</UniversalString>\n" &
"\t<UniversalString/>\n" &
"</So-uni>\n\n";

testcase enc_souni() runs on Tsets
{
  var universal charstring expected;

  expected := souni0;
  CHECK_METHOD(bxer_enc_souni, so_uni_0, expected);
  CHECK_METHOD(exer_enc_souni, so_uni_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_souni, so_uni_0, expected & lf);

  expected := souni1;
  CHECK_METHOD(bxer_enc_souni, so_uni_1, expected);
  CHECK_METHOD(exer_enc_souni, so_uni_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_souni, so_uni_1, expected & lf);

  expected := souni3;
  CHECK_METHOD(bxer_enc_souni, so_uni_3, expected);
  CHECK_METHOD(exer_enc_souni, so_uni_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_souni, so_uni_3, expected & lf);
}

testcase dec_souni() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        souni, souni0, So_uni, so_uni_0);
  CHECK_DECODE(exer_dec_souni, souni0, So_uni, so_uni_0);

  CHECK_DECODE2(        souni, souni1, So_uni, so_uni_1);
  CHECK_DECODE(exer_dec_souni, souni1, So_uni, so_uni_1);

  CHECK_DECODE2(        souni, souni3, So_uni, so_uni_3);
  CHECK_DECODE(exer_dec_souni, souni3, So_uni, so_uni_3);
}

//-------------------- SET OF UTF8String --------------------

const charstring soutf0 :=
"<So-utf/>\n\n";

const charstring soutf1 :=
"<So-utf>\n" &
"\t<UTF8String>utf</UTF8String>\n" &
"</So-utf>\n\n";

const charstring soutf3 :=
"<So-utf>\n" &
"\t<UTF8String>utf</UTF8String>\n" &
"\t<UTF8String>utf</UTF8String>\n" &
"\t<UTF8String>utf</UTF8String>\n" &
"\t<UTF8String/>\n" &
"</So-utf>\n\n";

testcase enc_soutf() runs on Tsets
{
  var universal charstring expected;

  expected := soutf0;
  CHECK_METHOD(bxer_enc_soutf, so_utf_0, expected);
  CHECK_METHOD(exer_enc_soutf, so_utf_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soutf, so_utf_0, expected & lf);

  expected := soutf1;
  CHECK_METHOD(bxer_enc_soutf, so_utf_1, expected);
  CHECK_METHOD(exer_enc_soutf, so_utf_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soutf, so_utf_1, expected & lf);

  expected := soutf3;
  CHECK_METHOD(bxer_enc_soutf, so_utf_3, expected);
  CHECK_METHOD(exer_enc_soutf, so_utf_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_soutf, so_utf_3, expected & lf);
}

testcase dec_soutf() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        soutf, soutf0, So_utf, so_utf_0);
  CHECK_DECODE(exer_dec_soutf, soutf0, So_utf, so_utf_0);

  CHECK_DECODE2(        soutf, soutf1, So_utf, so_utf_1);
  CHECK_DECODE(exer_dec_soutf, soutf1, So_utf, so_utf_1);

  CHECK_DECODE2(        soutf, soutf3, So_utf, so_utf_3);
  CHECK_DECODE(exer_dec_soutf, soutf3, So_utf, so_utf_3);
}

//-------------------- SET OF VideotexString --------------------

const charstring sovtx0 :=
"<So-vtx/>\n\n";

const charstring sovtx1 :=
"<So-vtx>\n" &
"\t<VideotexString>vtx</VideotexString>\n" &
"</So-vtx>\n\n";

const charstring sovtx3 :=
"<So-vtx>\n" &
"\t<VideotexString>Vee</VideotexString>\n" &
"\t<VideotexString>Tee</VideotexString>\n" &
"\t<VideotexString>Ecxs</VideotexString>\n" &
"\t<VideotexString/>\n" &
"</So-vtx>\n\n";

testcase enc_sovtx() runs on Tsets
{
  var universal charstring expected;

  expected := sovtx0;
  CHECK_METHOD(bxer_enc_sovtx, so_vtx_0, expected);
  CHECK_METHOD(exer_enc_sovtx, so_vtx_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sovtx, so_vtx_0, expected & lf);

  expected := sovtx1;
  CHECK_METHOD(bxer_enc_sovtx, so_vtx_1, expected);
  CHECK_METHOD(exer_enc_sovtx, so_vtx_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sovtx, so_vtx_1, expected & lf);

  expected := sovtx3;
  CHECK_METHOD(bxer_enc_sovtx, so_vtx_3, expected);
  CHECK_METHOD(exer_enc_sovtx, so_vtx_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sovtx, so_vtx_3, expected & lf);
}

testcase dec_sovtx() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sovtx, sovtx0, So_vtx, so_vtx_0);
  CHECK_DECODE(exer_dec_sovtx, sovtx0, So_vtx, so_vtx_0);

  CHECK_DECODE2(        sovtx, sovtx1, So_vtx, so_vtx_1);
  CHECK_DECODE(exer_dec_sovtx, sovtx1, So_vtx, so_vtx_1);

  CHECK_DECODE2(        sovtx, sovtx3, So_vtx, so_vtx_3);
  CHECK_DECODE(exer_dec_sovtx, sovtx3, So_vtx, so_vtx_3);
}

//-------------------- SET OF VisibleString --------------------

const charstring sovis0 :=
"<So-vis/>\n\n";

const charstring sovis1 :=
"<So-vis>\n" &
"\t<VisibleString>vis</VisibleString>\n" &
"</So-vis>\n\n";

const charstring sovis3 :=
"<So-vis>\n" &
"\t<VisibleString>red</VisibleString>\n" &
"\t<VisibleString>green</VisibleString>\n" &
"\t<VisibleString>blue</VisibleString>\n" &
"\t<VisibleString/>\n" &
"</So-vis>\n\n";

testcase enc_sovis() runs on Tsets
{
  var universal charstring expected;

  expected := sovis0;
  CHECK_METHOD(bxer_enc_sovis, so_vis_0, expected);
  CHECK_METHOD(exer_enc_sovis, so_vis_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sovis, so_vis_0, expected & lf);

  expected := sovis1;
  CHECK_METHOD(bxer_enc_sovis, so_vis_1, expected);
  CHECK_METHOD(exer_enc_sovis, so_vis_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sovis, so_vis_1, expected & lf);

  expected := sovis3;
  CHECK_METHOD(bxer_enc_sovis, so_vis_3, expected);
  CHECK_METHOD(exer_enc_sovis, so_vis_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sovis, so_vis_3, expected & lf);
}

testcase dec_sovis() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sovis, sovis0, So_vis, so_vis_0);
  CHECK_DECODE(exer_dec_sovis, sovis0, So_vis, so_vis_0);

  CHECK_DECODE2(        sovis, sovis1, So_vis, so_vis_1);
  CHECK_DECODE(exer_dec_sovis, sovis1, So_vis, so_vis_1);

  CHECK_DECODE2(        sovis, sovis3, So_vis, so_vis_3);
  CHECK_DECODE(exer_dec_sovis, sovis3, So_vis, so_vis_3);
}

//-------------------- SET OF CHARACTER STRING --------------------

const charstring sounr0 :=
"<So-unr/>\n\n";

const charstring sounr1 :=
"<So-unr>\n" &
"\t<SEQUENCE>\n" &
"\t\t<identification>\n" &
"\t\t\t<fixed/>\n" &
"\t\t</identification>\n" &
"\t\t<string-value>" &
//"\t\t\tC3815256 C38D5A54 C5B052C5 902054C3 9C4BC396 5246C39A 52C39347 C38950\n" &
"C3815256C38D5A54C5B052C5902054C39C4BC3965246C39A52C39347C38950" &
"</string-value>\n" &
"\t</SEQUENCE>\n" &
"</So-unr>\n\n";

const charstring sounr3 :=
"<So-unr>\n" &

"\t<SEQUENCE>\n" &
"\t\t<identification>\n" &
"\t\t\t<fixed/>\n" &
"\t\t</identification>\n" &
"\t\t<string-value>" &
"C3815256C38D5A54C5B052C5902054C39C4BC3965246C39A52C39347C38950" &
"</string-value>\n" &
"\t</SEQUENCE>\n" &



"\t<SEQUENCE>\n" &
"\t\t<identification>\n" &
"\t\t\t<syntaxes>\n" &
"\t\t\t\t<abstract>1.2.3.4</abstract>\n" &
"\t\t\t\t<transfer>2.7.1.8</transfer>\n" &
"\t\t\t</syntaxes>\n" &
"\t\t</identification>\n" &
"\t\t<string-value>C3A17276C3AD7A74C5B172C5912074C3</string-value>\n" &
"\t</SEQUENCE>\n" &

"\t<SEQUENCE>\n" &
"\t\t<identification>\n" &
"\t\t\t<syntax>1.2.3.4</syntax>\n" &
"\t\t</identification>\n" &
"\t\t<string-value>BC6BC3B67266C3BA72C3B367C3A970</string-value>\n" &
"\t</SEQUENCE>\n" &

"</So-unr>\n\n";


testcase enc_sounr() runs on Tsets
{
  var universal charstring expected;

  expected := sounr0;
  CHECK_METHOD(bxer_enc_sounr, so_unr_0, expected);
  CHECK_METHOD(exer_enc_sounr, so_unr_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sounr, so_unr_0, expected & lf);

  expected := sounr1;
  CHECK_METHOD(bxer_enc_sounr, so_unr_1, expected);
  CHECK_METHOD(exer_enc_sounr, so_unr_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sounr, so_unr_1, expected & lf);

  expected := sounr3;
  CHECK_METHOD(bxer_enc_sounr, so_unr_3, expected);
  CHECK_METHOD(exer_enc_sounr, so_unr_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sounr, so_unr_3, expected & lf);
}

testcase dec_sounr() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sounr, sounr0, So_unr, so_unr_0);
  CHECK_DECODE(exer_dec_sounr, sounr0, So_unr, so_unr_0);

  CHECK_DECODE2(        sounr, sounr1, So_unr, so_unr_1);
  CHECK_DECODE(exer_dec_sounr, sounr1, So_unr, so_unr_1);

  CHECK_DECODE2(        sounr, sounr3, So_unr, so_unr_3);
  CHECK_DECODE(exer_dec_sounr, sounr3, So_unr, so_unr_3);
}

//-------------------- SET OF selection type --------------------

const charstring sosel0 :=
"<Sosel/>\n\n";

const charstring sosel1 :=
"<Sosel>\n" &
"\t<Sel>1.602176e-19</Sel>\n" &
"</Sosel>\n\n";

const charstring sosel3 :=
"<Sosel>\n" &
"\t<Sel>0.841471</Sel>\n" &
"\t<Sel>0.909297</Sel>\n" &
"\t<Sel>0.141120</Sel>\n" &
"</Sosel>\n\n";


testcase enc_sosel() runs on Tsets
{
  var universal charstring expected;

  expected := sosel0;
  CHECK_METHOD(bxer_enc_sosel, SetValues.sosel_0, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sosel, SetValues.sosel_0, expected & lf);

  expected := sosel1;
  CHECK_METHOD(bxer_enc_sosel, SetValues.sosel_1, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sosel, SetValues.sosel_1, expected & lf);

  expected := sosel3;
  CHECK_METHOD(bxer_enc_sosel, SetValues.sosel_3, expected);
  flatten(expected);
  CHECK_METHOD(cxer_enc_sosel, SetValues.sosel_3, expected & lf);
}

testcase dec_sosel() runs on Tsets
{
  //     type suffix, input, type, expected
  CHECK_DECODE2(        sosel, sosel0, Sosel, SetValues.sosel_0);
  CHECK_DECODE(exer_dec_sosel, sosel0, Sosel, SetValues.sosel_0);

  CHECK_DECODE2(        sosel, sosel1, Sosel, SetValues.sosel_1);
  CHECK_DECODE(exer_dec_sosel, sosel1, Sosel, SetValues.sosel_1);

  CHECK_DECODE2(        sosel, sosel3, Sosel, SetValues.sosel_3);
  CHECK_DECODE(exer_dec_sosel, sosel3, Sosel, SetValues.sosel_3);
}



// enc_sonc is folded into enc_soc

/***********************************************/


control {
  execute(enc_sobs());
  execute(dec_sobs());

  execute(enc_sobo());
  execute(dec_sobo());

  execute(enc_soc());
  execute(dec_soc());

  execute(enc_sopdv());
  execute(dec_sopdv());

  execute(enc_soen());
  execute(dec_soen());

  execute(enc_soex());
  execute(dec_soex());

//   execute(enc_soin());
  execute(enc_soint());
  execute(dec_soint());

  execute(enc_son());
  execute(dec_son());
//   execute(enc_socsf());
  execute(enc_soid());
  execute(dec_soid());

  execute(enc_soos());
  execute(dec_soos());

  execute(enc_sor());
  execute(dec_sor());

  execute(enc_soroid());
  execute(dec_soroid());

  execute(enc_sobmp());
  execute(dec_sobmp());

  execute(enc_sogen());
  execute(dec_sogen());

  execute(enc_sogra());
  execute(dec_sogra());

  execute(enc_soia5());
  execute(dec_soia5());

  execute(enc_sonum());
  execute(dec_sonum());

  execute(enc_soprn());
  execute(dec_soprn());

  execute(enc_sottx());
  execute(dec_sottx());

// same as above:   execute(enc_sot61());
  execute(enc_souni());
  execute(dec_souni());

  execute(enc_soutf());
  execute(dec_soutf());

  execute(enc_sovtx());
  execute(dec_sovtx());

  execute(enc_sovis());
  execute(dec_sovis());

// same as above:   execute(enc_so646());
  execute(enc_sounr());
  execute(dec_sounr());


  // oddities

  execute(enc_sosel());
  execute(dec_sosel());
}

}
