Commit 6e213869 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

Made OER encoding of default values canonical (bug 537502)



Change-Id: I1875d72d9d7bd3d8c5505c801b012c26358189ac
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 0118409e
......@@ -4799,8 +4799,14 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
" boolean has_extension = FALSE;\n");
for (i = sdef->oerNrOrRootcomps; i < sdef->nElements; i++) {
src = mputprintf(src,
" has_extension = has_extension || (field_%s.is_bound() && field_%s.is_present());\n",
sdef->elements[i].name, sdef->elements[sdef->oerP[i]].name);
" has_extension = has_extension || (field_%s.is_bound() && field_%s.is_present()",
sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].name);
if (sdef->elements[sdef->oerP[i]].isDefault) {
src = mputprintf(src, " && field_%s != %s",
sdef->elements[sdef->oerP[i]].name,
sdef->elements[sdef->oerP[i]].defvalname);
}
src = mputstr(src, ");\n");
}
}
size_t opt_elements = 0;
......@@ -4833,10 +4839,16 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) {
pos--;
src = mputprintf(src,
" if (field_%s.is_present()) {\n"
" if (field_%s.is_present()", sdef->elements[sdef->oerP[i]].name);
if (sdef->elements[sdef->oerP[i]].isDefault) {
src = mputprintf(src, " && field_%s != %s",
sdef->elements[sdef->oerP[i]].name,
sdef->elements[sdef->oerP[i]].defvalname);
}
src = mputprintf(src,
") {\n"
" c += %i;\n"
" }\n"
, sdef->elements[sdef->oerP[i]].name
, 1 << pos);
if (pos == 0) {
pos = 8;
......@@ -4856,8 +4868,13 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
for (i = 0; i < limit; i++) {
if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) {
src = mputprintf(src,
" if (field_%s.is_present())\n "
, sdef->elements[sdef->oerP[i]].name);
" if (field_%s.is_present()", sdef->elements[sdef->oerP[i]].name);
if (sdef->elements[sdef->oerP[i]].isDefault) {
src = mputprintf(src, " && field_%s != %s",
sdef->elements[sdef->oerP[i]].name,
sdef->elements[sdef->oerP[i]].defvalname);
}
src = mputstr(src, ")\n ");
}
src = mputprintf(src,
" field_%s.OER_encode(%s_descr_, p_buf);\n"
......@@ -4899,7 +4916,13 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
opt_elems++;
}
src = mputprintf(src,
" has_present = has_present || field_%s.is_present();\n", sdef->elements[sdef->oerP[j]].name);
" has_present = has_present || (field_%s.is_present()", sdef->elements[sdef->oerP[j]].name);
if (sdef->elements[sdef->oerP[j]].isDefault) {
src = mputprintf(src, " && field_%s != %s",
sdef->elements[sdef->oerP[j]].name,
sdef->elements[sdef->oerP[j]].defvalname);
}
src = mputstr(src, ");\n");
}
src = mputprintf(src,
" if (has_present) {\n"
......@@ -4914,10 +4937,18 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) {
pos2--;
src = mputprintf(src,
" if (field_%s.is_present()) {\n"
" if (field_%s.is_present()",
sdef->elements[sdef->oerP[j]].name);
if (sdef->elements[sdef->oerP[j]].isDefault) {
src = mputprintf(src, " && field_%s != %s",
sdef->elements[sdef->oerP[j]].name,
sdef->elements[sdef->oerP[j]].defvalname);
}
src = mputprintf(src,
") {\n"
" c2 += %i;\n"
" }\n"
, sdef->elements[sdef->oerP[j]].name, 1 << pos2);
, 1 << pos2);
if (pos2 == 0) {
pos2 = 8;
ind2++;
......@@ -4946,14 +4977,21 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
eag_pos++;
} else {
src = mputprintf(src,
" if (field_%s.is_present()) {\n"
" if (field_%s.is_present()", sdef->elements[sdef->oerP[i]].name);
if (sdef->elements[sdef->oerP[i]].isDefault) {
src = mputprintf(src, " && field_%s != %s",
sdef->elements[sdef->oerP[i]].name,
sdef->elements[sdef->oerP[i]].defvalname);
}
src = mputprintf(src,
") {\n"
" c += %i;\n"
" field_%s.OER_encode(%s_descr_, tmp_buf2);\n"
" encode_oer_length(tmp_buf2.get_len(), tmp_buf, FALSE);\n"
" tmp_buf.put_buf(tmp_buf2);\n"
" tmp_buf2.clear();\n"
" }\n"
, sdef->elements[sdef->oerP[i]].name, 1 << pos
, 1 << pos
, sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].typedescrname);
}
if (pos == 0) {
......
......@@ -6274,9 +6274,16 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
// If extendable record and has real extensions the first bit of the
// preamble is 1
if (p_td.oer->extendable) {
for (int i = p_td.oer->nr_of_root_comps; i < field_count; i++) {
for (int i = 0; i < field_count; i++) {
boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]);
const Base_Type* default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
// If there are extension fields the first bit is 1
if (get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present()) {
if (i >= p_td.oer->nr_of_root_comps &&
get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[i])->is_equal(default_value))) {
c = 1 << 7;
has_extension = true;
break;
......@@ -6285,14 +6292,19 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
pos--;
limit = p_td.oer->nr_of_root_comps;
}
next_default_idx = 0;
for (int i = 0; i < limit; i++) {
boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]);
const Base_Type* default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
if (get_at(p_td.oer->p[i])->is_optional() || is_default_field) {
pos--;
c += get_at(p_td.oer->p[i])->is_present() << pos;
if (get_at(p_td.oer->p[i])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[i])->is_equal(default_value))) {
c += 1 << pos;
}
if (pos == 0) {
p_buf.put_c(c);
pos = 8;
......@@ -6303,9 +6315,19 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
if (pos != 8) {
p_buf.put_c(c);
}
next_default_idx = 0;
for (int i = 0; i < limit; ++i) {
get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), p_buf);
boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]);
const Base_Type* default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
if (!is_default_field || !get_at(p_td.oer->p[i])->is_equal(default_value)) {
get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), p_buf);
}
}
int ext_default_idx_start = next_default_idx;
// If the record is extendable and has real extensions
if (has_extension) {
......@@ -6315,21 +6337,38 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
pos = 8;
int eag_pos = p_td.oer->eag_len == 0 ? -1 : 0;
for (int i = limit; i < field_count; i++) {
boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]);
const Base_Type* default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
pos--;
if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) {
eag_pos++;
bool found = false;
for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) {
if (get_at(p_td.oer->p[j])->is_bound() && get_at(p_td.oer->p[j])->is_present()) {
// Add bit if there are at least one present field
c += 1 << pos;
break;
if (j != i) {
is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]);
default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
}
if (get_at(p_td.oer->p[j])->is_bound() && get_at(p_td.oer->p[j])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[j])->is_equal(default_value))) {
found = true;
}
}
if (found) {
// Add bit if there is at least one present field
c += 1 << pos;
}
i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1;
eag_pos++;
} else {
// extension attribute groups counted as one in the presence bitmap
if (get_at(p_td.oer->p[i])->is_present()) {
if (get_at(p_td.oer->p[i])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[i])->is_equal(default_value))) {
c += 1 << pos;
}
}
......@@ -6351,9 +6390,11 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
p_buf.put_buf(tmp_buf);
tmp_buf.clear();
next_default_idx = ext_default_idx_start;
eag_pos = p_td.oer->eag_len == 0 ? -1 : 0;
for (int i = limit; i < field_count; ++i) {
boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]);
const Base_Type* default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
......@@ -6366,18 +6407,24 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
if (is_default_field) {
next_default_idx--;
}
int current_default_idx = next_default_idx;
bool has_present = false;
for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) {
if (get_at(p_td.oer->p[j])->is_present()) {
has_present = true;
}
is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]);
default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
if (get_at(p_td.oer->p[j])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[j])->is_equal(default_value))) {
has_present = true;
}
if (get_at(p_td.oer->p[j])->is_optional() || is_default_field) {
pos--;
c += get_at(p_td.oer->p[j])->is_present() << pos;
if (get_at(p_td.oer->p[j])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[j])->is_equal(default_value))) {
c += 1 << pos;
}
if (pos == 0) {
tmp_buf.put_c(c);
pos = 8;
......@@ -6389,8 +6436,16 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
tmp_buf.put_c(c);
}
if (has_present) {
next_default_idx = current_default_idx;
for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) {
get_at(p_td.oer->p[j])->OER_encode(*fld_descr(p_td.oer->p[j]), tmp_buf);
is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]);
default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
if (!is_default_field || !get_at(p_td.oer->p[j])->is_equal(default_value)) {
get_at(p_td.oer->p[j])->OER_encode(*fld_descr(p_td.oer->p[j]), tmp_buf);
}
}
encode_oer_length(tmp_buf.get_len(), p_buf, FALSE);
p_buf.put_buf(tmp_buf);
......@@ -6398,7 +6453,8 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
tmp_buf.clear();
i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1;
eag_pos++;
} else if (get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present()) {
} else if (get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present() &&
(!is_default_field || !get_at(p_td.oer->p[i])->is_equal(default_value))) {
get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), tmp_buf);
encode_oer_length(tmp_buf.get_len(), p_buf, FALSE);
p_buf.put_buf(tmp_buf);
......@@ -6862,8 +6918,13 @@ int Record_Type::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu
if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) {
eag_pos++;
for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) {
is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]);
default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (j != i) {
is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]);
default_value = is_default_field ? default_indexes[next_default_idx].value : NULL;
if (is_default_field) {
next_default_idx++;
}
}
if (get_at(p_td.oer->p[j])->is_optional()) {
get_at(p_td.oer->p[j])->set_to_omit();
}
......
......@@ -2700,6 +2700,17 @@
if (not(match(log2str(erres7), log2str(erres71)))) {
setverdict(fail, "tc_sequence: ", match(log2str(erres7), log2str(erres71)));
}
er7 := {
me := 1,
f1 := 5, // default value
f2 := omit,
f3 := 5 // default value
}
os := enc_ExtensionRecord5(er7);
if (os != '400101'O) { // there's no extension in the encoding, since it only contains default values and 'omit'
setverdict(fail, "tc_sequence: ", match('400101'O, os));
}
er7 := {
me := 1,
......@@ -2747,7 +2758,7 @@
setverdict(fail, "tc_sequence: ", match(log2str(er7), log2str(erres7)));
}
var ExtensionRecord6 er8, erres8;
var ExtensionRecord6 er8, erres8, erres81;
er8 := {
me := 1,
f0 := 0,
......@@ -2766,9 +2777,24 @@
if (os != 'C001010302FFE0038001000380010103800102038001030380010403800105038001060380010703800108038001090180'O) {
setverdict(fail, "tc_sequence: ", match('C001010302FFE0038001000380010103800102038001030380010403800105038001060380010703800108038001090180'O, os));
}
erres81 := {
me := 1,
f0 := 0,
f1 := 1,
f2 := 2,
f3 := 3,
f4 := 4,
f5 := 5,
f6 := 6,
f7 := 7,
f8 := 8,
f9 := 9,
f_nul := NULL,
f10 := 4 // default value
}
erres8 := dec_ExtensionRecord6(os);
if (not(match(log2str(er8), log2str(erres8)))) {
setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8)));
if (not(match(log2str(erres81), log2str(erres8)))) {
setverdict(fail, "tc_sequence: ", match(log2str(erres81), log2str(erres8)));
}
er8 := {
......@@ -2789,9 +2815,24 @@
if (os != 'C001010302D8A003800100038001010380010303800104038001080180'O) {
setverdict(fail, "tc_sequence: ", match('C001010302D8A003800100038001010380010303800104038001080180'O, os));
}
erres81 := {
me := 1,
f0 := 0,
f1 := 1,
f2 := omit,
f3 := 3,
f4 := 4,
f5 := omit,
f6 := omit,
f7 := omit,
f8 := 8,
f9 := omit,
f_nul := NULL,
f10 := 4 // default value
}
erres8 := dec_ExtensionRecord6(os);
if (not(match(log2str(er8), log2str(erres8)))) {
setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8)));
if (not(match(log2str(erres81), log2str(erres8)))) {
setverdict(fail, "tc_sequence: ", match(log2str(erres81), log2str(erres8)));
}
er8 := {
......@@ -2867,6 +2908,33 @@
setverdict(fail, "tc_sequence: ", match('C001010302D8BC0380010003800101038001030380010403800108018002010A04010B010C02010D'O, os));
}
erres8 := dec_ExtensionRecord6(os);
if (not(match(log2str(er8), log2str(erres8)))) {
setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8)));
}
er8 := {
me := 1,
f0 := 5, // default value
f1 := 3,
f2 := omit,
f3 := 5, // default value
f4 := omit,
f5 := omit,
f6 := omit,
f7 := 2,
f8 := 1,
f9 := omit,
f_nul := omit,
f10 := 4, // default value
f11 := 11,
f12 := 12,
f13 := 13
}
os := enc_ExtensionRecord6(er8);
if (os != 'C001010302418C03800103038001020380010104010B010C02010D'O) {
setverdict(fail, "tc_sequence: ", match('C001010302418C03800103038001020380010104010B010C02010D'O, os));
}
erres8 := dec_ExtensionRecord6(os);
if (not(match(log2str(er8), log2str(erres8)))) {
setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8)));
}
......@@ -3581,7 +3649,7 @@
with { extension "prototype (convert) decode(OER)" }
// Testing the decoding of a field with a default value (bug 534769, bug 534943)
testcase tc_default() runs on EmptyCT {
testcase tc_default_dec() runs on EmptyCT {
var octetstring enc := '000104'O;
var RecWithDefault dec := dec_RecWithDefault(enc);
var RecWithDefault dec_exp := { field1 := 1, field2 := 4 };
......@@ -3590,6 +3658,20 @@
}
setverdict(pass);
}
external function enc_RecWithDefault(in RecWithDefault pdu) return octetstring
with { extension "prototype (convert) encode(OER)" }
// Testing that the encoder omits the default field if its value is equal to the default value (bug 537502)
testcase tc_default_enc() runs on EmptyCT {
var RecWithDefault x := { field1 := 1, field2 := 4 };
var octetstring enc := enc_RecWithDefault(x);
var octetstring enc_exp := '000104'O;
if (enc != enc_exp) {
setverdict(fail, "Encoding failed. Got: ", enc, ", expected: ", enc_exp);
}
setverdict(pass);
}
control {
execute(tc_boolean());
......@@ -3612,7 +3694,8 @@
execute(tc_example());
execute(tc_529017());
execute(tc_533061());
execute(tc_default());
execute(tc_default_dec());
execute(tc_default_enc());
}
}
......@@ -328,7 +328,7 @@ ExtensionRecord6 ::= SEQUENCE {
[[f8 INTEGER DEFAULT 4]],
[[f9 INTEGER OPTIONAL]],
[[f-nul NULL OPTIONAL]],
f10 INTEGER,
f10 INTEGER DEFAULT 4,
[[f11 INTEGER,
f12 INTEGER]],
f13 INTEGER
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment