Commit d55fc396 authored by Jeno Attila Balasko's avatar Jeno Attila Balasko Committed by Gerrit Code Review
Browse files

Merge "Fixed JSON attribute 'chosen' to use default value and fixed 'omit...

Merge "Fixed JSON attribute 'chosen' to use default value and fixed 'omit otherwise' case (bugs 533487, 528465)"
parents 1367659d 8fa97841
......@@ -3219,7 +3219,16 @@ char* generate_json_decoder(char* src, const struct_def* sdef)
boolean has_metainfo_enabled = FALSE;
for (int i = 0; i < sdef->nElements; ++i) {
src = mputprintf(src, " boolean %s_found = FALSE;\n", sdef->elements[i].name);
if (sdef->elements[i].jsonDefaultValue) {
// initialize fields with their default values (they will be overwritten
// later, if the JSON document contains data for these fields)
src = mputprintf(src,
" field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n"
, sdef->elements[i].name, sdef->elements[i].typedescrname);
}
else {
src = mputprintf(src, " boolean %s_found = FALSE;\n", sdef->elements[i].name);
}
if (sdef->elements[i].jsonMetainfoUnbound) {
// initialize meta info states
src = mputprintf(src,
......@@ -3259,10 +3268,12 @@ char* generate_json_decoder(char* src, const struct_def* sdef)
src = mputprintf(src,
// check field name
"if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n"
" %s_found = TRUE;\n"
, (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname)
, sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
, sdef->elements[i].name);
, sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
if (!sdef->elements[i].jsonDefaultValue) {
src = mputprintf(src,
" %s_found = TRUE;\n", sdef->elements[i].name);
}
if (has_metainfo_enabled) {
src = mputstr(src, " if (is_metainfo) {\n");
if (sdef->elements[i].jsonMetainfoUnbound) {
......@@ -3416,59 +3427,60 @@ char* generate_json_decoder(char* src, const struct_def* sdef)
, (unsigned long) strlen(sdef->elements[i].dispname)
, sdef->elements[i].dispname);
}
src = mputprintf(src,
"if (!%s_found) {\n"
, sdef->elements[i].name);
if (sdef->elements[i].jsonDefaultValue) {
if (!sdef->elements[i].jsonDefaultValue) {
src = mputprintf(src,
" field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n"
, sdef->elements[i].name, sdef->elements[i].typedescrname);
}
else if (sdef->elements[i].isOptional) {
// if the conditions in attribute 'choice' indicate that this field is
// mandatory, then display an error
if (sdef->elements[i].jsonChosen != NULL) {
int j;
boolean has_otherwise = FALSE;
for (j = 0; j < sdef->elements[i].jsonChosen->nElements; j++) {
if (sdef->elements[i].jsonChosen->list[j].nElements == 0) {
has_otherwise = TRUE;
break;
}
}
boolean first_found = FALSE;
for (j = 0; j < sdef->elements[i].jsonChosen->nElements; j++) {
if ((!has_otherwise && sdef->elements[i].jsonChosen->list[j].fieldnum != -2) ||
(has_otherwise && sdef->elements[i].jsonChosen->list[j].fieldnum == -2)) {
if (!first_found) {
src = mputstr(src, " if (");
first_found = TRUE;
"if (!%s_found) {\n"
, sdef->elements[i].name);
if (sdef->elements[i].isOptional) {
// if the conditions in attribute 'choice' indicate that this field is
// mandatory, then display an error
if (sdef->elements[i].jsonChosen != NULL) {
int j;
boolean has_otherwise = FALSE;
boolean omit_otherwise = FALSE;
for (j = 0; j < sdef->elements[i].jsonChosen->nElements; j++) {
if (sdef->elements[i].jsonChosen->list[j].nElements == 0) {
has_otherwise = TRUE;
if (sdef->elements[i].jsonChosen->list[j].fieldnum == -2) {
omit_otherwise = TRUE;
}
break;
}
else {
src = mputstr(src, "\n || ");
}
boolean first_found = FALSE;
for (j = 0; j < sdef->elements[i].jsonChosen->nElements; j++) {
if (((!has_otherwise || omit_otherwise) && sdef->elements[i].jsonChosen->list[j].fieldnum != -2) ||
(has_otherwise && !omit_otherwise && sdef->elements[i].jsonChosen->list[j].fieldnum == -2)) {
if (!first_found) {
src = mputstr(src, " if (");
first_found = TRUE;
}
else {
src = mputstr(src, "\n || ");
}
src = genRawFieldChecker(src, sdef->elements[i].jsonChosen->list + j, !has_otherwise || omit_otherwise);
}
src = genRawFieldChecker(src, sdef->elements[i].jsonChosen->list + j, !has_otherwise);
}
if (first_found) {
src = mputprintf(src,
") {\n"
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_CHOSEN_FIELD_OMITTED, \"%s\");\n"
" return JSON_ERROR_FATAL;\n"
" }\n", sdef->elements[i].dispname);
}
}
if (first_found) {
src = mputprintf(src,
") {\n"
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_CHOSEN_FIELD_OMITTED, \"%s\");\n"
" return JSON_ERROR_FATAL;\n"
" }\n", sdef->elements[i].dispname);
}
src = mputprintf(src,
" field_%s = OMIT_VALUE;\n"
, sdef->elements[i].name);
} else {
src = mputprintf(src,
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n"
" return JSON_ERROR_FATAL;\n"
, sdef->elements[i].dispname);
}
src = mputprintf(src,
" field_%s = OMIT_VALUE;\n"
, sdef->elements[i].name);
} else {
src = mputprintf(src,
" JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n"
" return JSON_ERROR_FATAL;\n"
, sdef->elements[i].dispname);
}
src = mputstr(src,
" }\n ");
src = mputstr(src,
" }\n ");
} // if there's no default value
}
src = mputstr(src,
"\n return (int)dec_len;\n");
......
......@@ -627,6 +627,54 @@ testcase tc_attribute_chosen_negtest() runs on MTC {
setverdict(pass);
}
// Testing JSON decoding with attributes 'chosen' and 'default'.
// (The conditions in the attribute 'chosen' depend on fields that have default values.)
testcase tc_attribute_chosen_default() runs on MTC {
// Test #1: both fields use their default values
var octetstring buff := char2oct("{\"field\":{\"num\":1,\"str\":\"abc\"}}");
var PduWithId2 dec_exp := { protocolId1 := 1, protocolId2 := 0, field := { type1 := { num := 1, str := "abc" } } };
var PduWithId2 dec := f_dec_pduwithid2(buff);
if (dec != dec_exp) {
setverdict(fail, "Test #1 failed. Expected: ", dec_exp, ", got: ", dec);
}
// Test #2: the first field uses its default value, the second decodes its value from the buffer
buff := char2oct("{\"protocolId2\":-1,\"field\":{\"num\":1,\"str\":\"abc\"}}");
dec_exp := { protocolId1 := 1, protocolId2 := -1, field := { type1 := { num := 1, str := "abc" } } };
dec := f_dec_pduwithid2(buff);
if (dec != dec_exp) {
setverdict(fail, "Test #2 failed. Expected: ", dec_exp, ", got: ", dec);
}
// Test #3: the second field uses its default value, the first decodes its value from the buffer
buff := char2oct("{\"protocolId1\":6,\"field\":{\"num\":1,\"str\":\"abc\"}}");
dec_exp := { protocolId1 := 6, protocolId2 := 0, field := { type3 := { num := 1.0, str := "abc" } } };
dec := f_dec_pduwithid2(buff);
if (dec != dec_exp) {
setverdict(fail, "Test #3 failed. Expected: ", dec_exp, ", got: ", dec);
}
// Test #4: both fields decode their values from the buffer
buff := char2oct("{\"protocolId1\":6,\"protocolId2\":-1}");
dec_exp := { protocolId1 := 6, protocolId2 := -1, field := omit };
dec := f_dec_pduwithid2(buff);
if (dec != dec_exp) {
setverdict(fail, "Test #4 failed. Expected: ", dec_exp, ", got: ", dec);
}
// Test #5: both fields decode their values from the buffer,
// however, the first field appears after the union field in the buffer,
// so its default value is used when checking the conditions of the attribute 'chosen'
buff := char2oct("{\"protocolId2\":-1,\"field\":{\"num\":1,\"str\":\"abc\"},\"protocolId1\":6}");
dec_exp := { protocolId1 := 6, protocolId2 := -1, field := { type1 := { num := 1, str := "abc" } } };
dec := f_dec_pduwithid2(buff);
if (dec != dec_exp) {
setverdict(fail, "Test #5 failed. Expected: ", dec_exp, ", got: ", dec);
}
setverdict(pass);
}
control {
execute(tc_NoAttributeOnUpperLevel())
......@@ -655,5 +703,6 @@ control {
execute(tc_attribute_default_struct());
execute(tc_attribute_chosen());
execute(tc_attribute_chosen_negtest());
execute(tc_attribute_chosen_default());
}
}
......@@ -430,6 +430,9 @@ external function f_dec_null(in octetstring x) return HasNull
external function f_dec_pduwithid(in octetstring x) return PduWithId
with { extension "prototype(convert) decode(JSON)" }
external function f_dec_pduwithid2(in octetstring x) return PduWithId2
with { extension "prototype(convert) decode(JSON)" }
//============== Internal Functions ====================
function f_check_encoding(in octetstring encoded, in octetstring expected) {
......
......@@ -351,6 +351,17 @@ type record StructType3 {
type record of PduWithId PduWithIdList;
type record PduWithId2 {
integer protocolId1,
integer protocolId2,
Choices field optional
}
with {
variant (field) "chosen (type1, { protocolId1 = 1, protocolId2 = 1 }; type2, protocolId1 = 0; type3, protocolId2 = 0; omit, otherwise)";
variant (protocolId1) "default (1)";
variant (protocolId2) "default (0)";
}
} with {
encode "JSON";
extension "anytype integer, charstring, R, RoI, Thing";
......
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