/******************************************************************************
 * Copyright (c) 2000-2025 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:
 *   Baranyi, Botond – initial implementation
 *
 ******************************************************************************/
module SetOfTests {

import from Types all;
import from Tools all;

// unaligned, basic
external function enc_setof1(in SetOf1 x) return bitstring with { extension "prototype(convert) encode(PER)" }
external function enc_setof2(in SetOf2 x) return bitstring with { extension "prototype(convert) encode(PER)" }
external function enc_setof3(in SetOf3 x) return bitstring with { extension "prototype(convert) encode(PER)" }
external function enc_setof4(in SetOf4 x) return bitstring with { extension "prototype(convert) encode(PER)" }
external function enc_setof5(in SetOf5 x) return bitstring with { extension "prototype(convert) encode(PER)" }

external function dec_setof1(in bitstring x) return SetOf1 with { extension "prototype(convert) decode(PER)" }
external function dec_setof2(in bitstring x) return SetOf2 with { extension "prototype(convert) decode(PER)" }
external function dec_setof3(in bitstring x) return SetOf3 with { extension "prototype(convert) decode(PER)" }
external function dec_setof4(in bitstring x) return SetOf4 with { extension "prototype(convert) decode(PER)" }
external function dec_setof5(in bitstring x) return SetOf5 with { extension "prototype(convert) decode(PER)" }

// aligned, basic
external function enc_setof1_a(in SetOf1 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED)" }
external function enc_setof2_a(in SetOf2 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED)" }
external function enc_setof3_a(in SetOf3 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED)" }
external function enc_setof4_a(in SetOf4 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED)" }
external function enc_setof5_a(in SetOf5 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED)" }

external function dec_setof1_a(in bitstring x) return SetOf1 with { extension "prototype(convert) decode(PER:ALIGNED)" }
external function dec_setof2_a(in bitstring x) return SetOf2 with { extension "prototype(convert) decode(PER:ALIGNED)" }
external function dec_setof3_a(in bitstring x) return SetOf3 with { extension "prototype(convert) decode(PER:ALIGNED)" }
external function dec_setof4_a(in bitstring x) return SetOf4 with { extension "prototype(convert) decode(PER:ALIGNED)" }
external function dec_setof5_a(in bitstring x) return SetOf5 with { extension "prototype(convert) decode(PER:ALIGNED)" }

// unaligned, canonical
external function enc_setof1_can(in SetOf1 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL)" }
external function enc_setof2_can(in SetOf2 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL)" }
external function enc_setof3_can(in SetOf3 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL)" }
external function enc_setof4_can(in SetOf4 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL)" }
external function enc_setof5_can(in SetOf5 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL)" }

// aligned, canonical
external function enc_setof1_a_can(in SetOf1 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED CANONICAL)" }
external function enc_setof2_a_can(in SetOf2 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNED, CANONICAL)" }
external function enc_setof3_a_can(in SetOf3 x) return bitstring with { extension "prototype(convert) encode(PER:ALIGNEDCANONICAL)" }
external function enc_setof4_a_can(in SetOf4 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL ALIGNED)" }
external function enc_setof5_a_can(in SetOf5 x) return bitstring with { extension "prototype(convert) encode(PER:CANONICAL ALIGNED)" }

testcase tc_per_setof_encode_unaligned_basic() runs on CT {
  // fixed length
  var SetOf1 x1 := { 19, 13 };
  var bitstring enc_exp := '10010011'B;
  var bitstring enc := enc_setof1(x1);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #1 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // constrained length, extendable
  var SetOf2 x2 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '0011010101101010110000100100011010000000'B;
  enc := enc_setof2(x2);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #2 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  var SetOf2 x3 := { 'AB'O, '56'O, '12'O, '34'O, '90'O, 'EF'O, '78'O, 'CD'O };
  enc_exp := '10000100010101011010101100001001000110100100100001110111101111000110011010000000'B;
  enc := enc_setof2(x3);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #3 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // semi-constrained length (if the length's upper bound is greater than 64K, then it is considered as infinite)
  var SetOf3 x4 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '000001000000000110101011000000010101011000000001000100100000000100110100'B;
  enc := enc_setof3(x4);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #4 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // unconstrained length
  var SetOf4 x5 := { { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '78'O }, { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '56'O } };
  enc_exp := '0000001001000000010001001000000001001101000000000101111000010000000100010010000000010011010000000001010101100000'B;
  enc := enc_setof4(x5);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #5 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // huge length
  var SetOf5 x6 := f_setof();
  enc_exp := f_seqof_setof_enc(false);
  enc := enc_setof5(x6);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #6 failed.");
  }
  setverdict(pass);
}

testcase tc_per_setof_encode_aligned_basic() runs on CT {
  // fixed length
  var SetOf1 x1 := { 19, 13 };
  var bitstring enc_exp := '10010011'B;
  var bitstring enc := enc_setof1_a(x1);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #1 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // constrained length, extendable
  var SetOf2 x2 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '0011010101101010110000100100011010000000'B;
  enc := enc_setof2_a(x2);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #2 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  var SetOf2 x3 := { 'AB'O, '56'O, '12'O, '34'O, '90'O, 'EF'O, '78'O, 'CD'O };
  enc_exp := '10000000000010001010101101010110000100100011010010010000111011110111100011001101'B;
  enc := enc_setof2_a(x3);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #3 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // semi-constrained length (if the length's upper bound is greater than 64K, then it is considered as infinite)
  var SetOf3 x4 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '000001000000000110101011000000010101011000000001000100100000000100110100'B;
  enc := enc_setof3_a(x4);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #4 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // unconstrained length
  var SetOf4 x5 := { { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '78'O }, { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '56'O } };
  enc_exp := '000000100100000000000001000100100000000100110100000000010111100001000000000000010001001000000001001101000000000101010110'B;
  enc := enc_setof4_a(x5);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #5 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // huge length
  var SetOf5 x6 := f_setof();
  enc_exp := f_seqof_setof_enc(false);
  enc := enc_setof5_a(x6);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #6 failed.");
  }
  setverdict(pass);
}

testcase tc_per_setof_encode_unaligned_canonical() runs on CT {
  // fixed length
  var SetOf1 x1 := { 19, 13 };
  var bitstring enc_exp := '00111001'B;
  var bitstring enc := enc_setof1_can(x1);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #1 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // constrained length, extendable
  var SetOf2 x2 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '0010001001000110100010101101010101100000'B;
  enc := enc_setof2_can(x2);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #2 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  var SetOf2 x3 := { 'AB'O, '56'O, '12'O, '34'O, '90'O, 'EF'O, '78'O, 'CD'O };
  enc_exp := '10000100000010010001101000101011001111000100100001010101111001101111011110000000'B;
  enc := enc_setof2_can(x3);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #3 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // semi-constrained length (if the length's upper bound is greater than 64K, then it is considered as infinite)
  var SetOf3 x4 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '000001000000000100010010000000010011010000000001010101100000000110101011'B;
  enc := enc_setof3_can(x4);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #4 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // unconstrained length
  var SetOf4 x5 := { { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '78'O }, { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '56'O } };
  enc_exp := '0000001001000000010001001000000001001101000000000101010110010000000100010010000000010011010000000001011110000000'B;
  enc := enc_setof4_can(x5);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #5 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // huge length
  var SetOf5 x6 := f_setof();
  enc_exp := f_seqof_setof_enc(true);
  enc := enc_setof5_can(x6);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #6 failed.");
  }
  setverdict(pass);
}

testcase tc_per_setof_encode_aligned_canonical() runs on CT {
  // fixed length
  var SetOf1 x1 := { 19, 13 };
  var bitstring enc_exp := '00111001'B;
  var bitstring enc := enc_setof1_a_can(x1);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #1 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // constrained length, extendable
  var SetOf2 x2 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '0010001001000110100010101101010101100000'B;
  enc := enc_setof2_a_can(x2);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #2 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  var SetOf2 x3 := { 'AB'O, '56'O, '12'O, '34'O, '90'O, 'EF'O, '78'O, 'CD'O };
  enc_exp := '10000000000010000001001000110100010101100111100010010000101010111100110111101111'B;
  enc := enc_setof2_a_can(x3);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #3 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // semi-constrained length (if the length's upper bound is greater than 64K, then it is considered as infinite)
  var SetOf3 x4 := { 'AB'O, '56'O, '12'O, '34'O };
  enc_exp := '000001000000000100010010000000010011010000000001010101100000000110101011'B;
  enc := enc_setof3_a_can(x4);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #4 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // unconstrained length
  var SetOf4 x5 := { { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '78'O }, { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '56'O } };
  enc_exp := '000000100100000000000001000100100000000100110100000000010101011001000000000000010001001000000001001101000000000101111000'B;
  enc := enc_setof4_a_can(x5);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #5 failed. Got: ", enc, ", expected: ", enc_exp);
  }
  
  // huge length
  var SetOf5 x6 := f_setof();
  enc_exp := f_seqof_setof_enc(true);
  enc := enc_setof5_a_can(x6);
  if (enc != enc_exp) {
    setverdict(fail, "Encoding set of #6 failed.");
  }
  setverdict(pass);
}

testcase tc_per_setof_decode_unaligned() runs on CT {
  // fixed length
  var bitstring enc := '10010011'B;
  var SetOf1 x1 := dec_setof1(enc);
  var SetOf1 x1_exp := { 19, 13 };
  if (x1 != x1_exp) {
    setverdict(fail, "Decoding set of #1 failed. Got: ", x1, ", expected: ", x1_exp);
  }
  
  // constrained length, extendable
  enc := '0011010101101010110000100100011010000000'B;
  var SetOf2 x2 := dec_setof2(enc);
  var SetOf2 x2_exp := { 'AB'O, '56'O, '12'O, '34'O };
  if (x2 != x2_exp) {
    setverdict(fail, "Decoding set of #2 failed. Got: ", x2, ", expected: ", x2_exp);
  }
  enc := '10000100010101011010101100001001000110100100100001110111101111000110011010000000'B;
  var SetOf2 x3 := dec_setof2(enc);
  var SetOf2 x3_exp := { 'AB'O, '56'O, '12'O, '34'O, '90'O, 'EF'O, '78'O, 'CD'O };
  if (x3 != x3_exp) {
    setverdict(fail, "Decoding set of #3 failed. Got: ", x3, ", expected: ", x3_exp);
  }
  
  // semi-constrained length (if the length's upper bound is greater than 64K, then it is considered as infinite)
  enc := '000001000000000110101011000000010101011000000001000100100000000100110100'B;
  var SetOf3 x4 := dec_setof3(enc);
  var SetOf3 x4_exp := { 'AB'O, '56'O, '12'O, '34'O };
  if (x4 != x4_exp) {
    setverdict(fail, "Decoding set of #4 failed. Got: ", x4, ", expected: ", x4_exp);
  }
  
  // unconstrained length
  enc := '0000001001000000010001001000000001001101000000000101111000010000000100010010000000010011010000000001010101100000'B;
  var SetOf4 x5 := dec_setof4(enc);
  var SetOf4 x5_exp := { { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '78'O }, { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '56'O } };
  if (x5 != x5_exp) {
    setverdict(fail, "Decoding set of #5 failed. Got: ", x5, ", expected: ", x5_exp);
  }
  
  // huge length
  enc := f_seqof_setof_enc(false);
  var SetOf5 x6 := dec_setof5(enc);
  var SetOf5 x6_exp := f_setof();
  if (x6 != x6_exp) {
    setverdict(fail, "Decoding set of #6 failed. Got: ", x6, ", expected: ", x6_exp);
  }
  setverdict(pass);
}

testcase tc_per_setof_decode_aligned() runs on CT {
  // fixed length
  var bitstring enc := '10010011'B;
  var SetOf1 x1 := dec_setof1_a(enc);
  var SetOf1 x1_exp := { 19, 13 };
  if (x1 != x1_exp) {
    setverdict(fail, "Decoding set of #1 failed. Got: ", x1, ", expected: ", x1_exp);
  }
  
  // constrained length, extendable
  enc := '0011010101101010110000100100011010000000'B;
  var SetOf2 x2 := dec_setof2_a(enc);
  var SetOf2 x2_exp := { 'AB'O, '56'O, '12'O, '34'O };
  if (x2 != x2_exp) {
    setverdict(fail, "Decoding set of #2 failed. Got: ", x2, ", expected: ", x2_exp);
  }
  enc := '10000000000010001010101101010110000100100011010010010000111011110111100011001101'B;
  var SetOf2 x3 := dec_setof2_a(enc);
  var SetOf2 x3_exp := { 'AB'O, '56'O, '12'O, '34'O, '90'O, 'EF'O, '78'O, 'CD'O };
  if (x3 != x3_exp) {
    setverdict(fail, "Decoding set of #3 failed. Got: ", x3, ", expected: ", x3_exp);
  }
  
  // semi-constrained length (if the length's upper bound is greater than 64K, then it is considered as infinite)
  enc := '000001000000000110101011000000010101011000000001000100100000000100110100'B;
  var SetOf3 x4 := dec_setof3_a(enc);
  var SetOf3 x4_exp := { 'AB'O, '56'O, '12'O, '34'O };
  if (x4 != x4_exp) {
    setverdict(fail, "Decoding set of #4 failed. Got: ", x4, ", expected: ", x4_exp);
  }
  
  // unconstrained length
  enc := '000000100100000000000001000100100000000100110100000000010111100001000000000000010001001000000001001101000000000101010110'B;
  var SetOf4 x5 := dec_setof4_a(enc);
  var SetOf4 x5_exp := { { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '78'O }, { f1 := '12'O, f2 := '34'O, f3 := omit, f4 := '56'O } };
  if (x5 != x5_exp) {
    setverdict(fail, "Decoding set of #5 failed. Got: ", x5, ", expected: ", x5_exp);
  }
  
  // huge length
  enc := f_seqof_setof_enc(false);
  var SetOf5 x6 := dec_setof5_a(enc);
  var SetOf5 x6_exp := f_setof();
  if (x6 != x6_exp) {
    setverdict(fail, "Decoding set of #6 failed. Got: ", x6, ", expected: ", x6_exp);
  }
  setverdict(pass);
}
  
control {
  execute(tc_per_setof_encode_unaligned_basic());
  execute(tc_per_setof_encode_aligned_basic());
  execute(tc_per_setof_encode_unaligned_canonical());
  execute(tc_per_setof_encode_aligned_canonical());
  execute(tc_per_setof_decode_unaligned());
  execute(tc_per_setof_decode_aligned());
}

}

