Skip to content

Commit 9f6627f

Browse files
Refactor .eq, .default, .size, etc. to accept types, not just numbers
Signed-off-by: Øyvind Rønningstad <[email protected]>
1 parent 1965dfa commit 9f6627f

File tree

4 files changed

+377
-119
lines changed

4 files changed

+377
-119
lines changed

tests/cases/corner_cases.cddl

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
; SPDX-License-Identifier: Apache-2.0
55
;
66

7+
One = 1
8+
Two = 2
9+
Three = 3
10+
Ten = 10
11+
712
Numbers = [
8-
one: 1,
13+
one: One,
914
minustwo: -2,
10-
fourtoten: 4..10,
11-
twobytes: uint .size 2,
15+
fourtoten: 4..Ten,
16+
twobytes: uint .size Two,
1217
onetofourbytes: uint .size 0b1..0o4, ; Testing binary and octal
1318
minusfivektoplustwohundred: -5000..200,
1419
fourbillion: 0xEE6B2800,
@@ -72,9 +77,9 @@ MultiGroup = +(3,-4)
7277
Union = Group / MultiGroup / (3,4) / "\"hello\""
7378

7479
Map = {
75-
listkey: [5,6] => bool,
80+
listkey: ((([5,6] => bool))),
7681
union: (7=>uint) / (-8=>uint),
77-
twotothree: 2*3 nil => bstr,
82+
twotothree: (2*3 (nil => bstr)),
7883
}
7984

8085
EmptyMap = {}
@@ -103,8 +108,10 @@ ValueRange = [
103108
lesseq1: uint .le 1,
104109
equal42: uint .eq 42,
105110
equalstrworld: tstr .eq "world",
106-
default3: ?int .gt 2 .default 3,
107-
defaulthello: ?bstr .default 'hello',
111+
equalpi: float .size 8 .eq ((( 3.14 ))),
112+
equaltrue: bool .eq true,
113+
default3: ?int .gt 2 .default Three,
114+
defaulthello: ?bstr .default ((('hello'))),
108115
defaulte: ?float .size 4 .default 2.72,
109116
defaultfalse: ?bool .default false,
110117
]

tests/decode/test5_corner_cases/src/main.c

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,127 +1109,151 @@ ZTEST(cbor_decode_test5, test_range)
11091109

11101110
ZTEST(cbor_decode_test5, test_value_range)
11111111
{
1112-
const uint8_t payload_value_range1[] = {LIST(6),
1112+
const uint8_t payload_value_range1[] = {LIST(8),
11131113
11,
11141114
0x19, 0x03, 0xe7, // 999
11151115
0x29, // -10
11161116
1,
11171117
0x18, 42, // 42
11181118
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1119+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1120+
0xF5,
11191121
END
11201122
};
11211123

1122-
const uint8_t payload_value_range2[] = {LIST(A),
1124+
const uint8_t payload_value_range2[] = {LIST(C),
11231125
0x18, 100, // 100
11241126
0x39, 0x03, 0xe8, // -1001
11251127
0x18, 100, // 100
11261128
0,
11271129
0x18, 42, // 42
11281130
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1131+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1132+
0xF5,
11291133
0x04,
11301134
0x42, 'h', 'i', // "hi"
11311135
0xFA, 0x40, 0x48, 0xf5, 0xc3,
11321136
0xF5,
11331137
END
11341138
};
11351139

1136-
const uint8_t payload_value_range3_inv[] = {LIST(6),
1140+
const uint8_t payload_value_range3_inv[] = {LIST(8),
11371141
10,
11381142
0x19, 0x03, 0xe7, // 999
11391143
0x29, // -10
11401144
1,
11411145
0x18, 42, // 42
11421146
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1147+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1148+
0xF5,
11431149
END
11441150
};
11451151

1146-
const uint8_t payload_value_range4_inv[] = {LIST(6),
1152+
const uint8_t payload_value_range4_inv[] = {LIST(8),
11471153
11,
11481154
0x19, 0x03, 0xe8, // 1000
11491155
0x29, // -10
11501156
1,
11511157
0x18, 42, // 42
11521158
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1159+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1160+
0xF5,
11531161
END
11541162
};
11551163

1156-
const uint8_t payload_value_range5_inv[] = {LIST(6),
1164+
const uint8_t payload_value_range5_inv[] = {LIST(8),
11571165
11,
11581166
0x19, 0x03, 0xe7, // 999
11591167
0x2a, // -11
11601168
1,
11611169
0x18, 42, // 42
11621170
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1171+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1172+
0xF5,
11631173
END
11641174
};
11651175

1166-
const uint8_t payload_value_range6_inv[] = {LIST(6),
1176+
const uint8_t payload_value_range6_inv[] = {LIST(8),
11671177
11,
11681178
0x19, 0x03, 0xe7, // 999
11691179
0x29, // -10
11701180
2,
11711181
0x18, 42, // 42
11721182
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1183+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1184+
0xF5,
11731185
END
11741186
};
11751187

1176-
const uint8_t payload_value_range7_inv[] = {LIST(6),
1188+
const uint8_t payload_value_range7_inv[] = {LIST(8),
11771189
11,
11781190
0x19, 0x03, 0xe7, // 999
11791191
0x29, // -10
11801192
1,
11811193
0x18, 43, // 42
11821194
0x65, 'w', 'o', 'r', 'l', 'e', // "worle"
1195+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1196+
0xF5,
11831197
END
11841198
};
11851199

1186-
const uint8_t payload_value_range8_inv[] = {LIST(6),
1200+
const uint8_t payload_value_range8_inv[] = {LIST(8),
11871201
11,
11881202
0x19, 0x03, 0xe7, // 999
11891203
0x29, // -10
11901204
1,
11911205
0x18, 42, // 42
11921206
0x66, 'w', 'o', 'r', 'l', 'd', 'd', // "worldd"
1207+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1208+
0xF5,
11931209
END
11941210
};
11951211

1196-
const uint8_t payload_value_range9_inv[] = {LIST(6),
1212+
const uint8_t payload_value_range9_inv[] = {LIST(8),
11971213
11,
11981214
0x19, 0x03, 0xe7, // 999
11991215
0x29, // -10
12001216
1,
12011217
0x18, 42, // 42
12021218
0x64, 'w', 'o', 'r', 'l', // "worl"
1219+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1220+
0xF5,
12031221
END
12041222
};
12051223

1206-
const uint8_t payload_value_range10_inv[] = {LIST(6),
1224+
const uint8_t payload_value_range10_inv[] = {LIST(8),
12071225
11,
12081226
0x39, 0x03, 0xe6, // -999
12091227
0x39, // -10
12101228
1,
12111229
0x18, 42, // 42
12121230
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1231+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1232+
0xF5,
12131233
END
12141234
};
12151235

1216-
const uint8_t payload_value_range11_inv[] = {LIST(6),
1236+
const uint8_t payload_value_range11_inv[] = {LIST(8),
12171237
11,
12181238
0x1a, 0x10, 0x00, 0x00, 0x00, // 0x10000000
12191239
0x39, 0x03, 0xe8, // -1001
12201240
1,
12211241
0x18, 42, // 42
12221242
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1243+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1244+
0xF5,
12231245
END
12241246
};
12251247

1226-
const uint8_t payload_value_range12_inv[] = {LIST(A),
1248+
const uint8_t payload_value_range12_inv[] = {LIST(C),
12271249
0x18, 100, // 100
12281250
0x39, 0x03, 0xe8, // -1001
12291251
0x18, 100, // 100
12301252
0,
12311253
0x18, 42, // 42
12321254
0x65, 'w', 'o', 'r', 'l', 'd', // "world"
1255+
0xFB, 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,
1256+
0xF5,
12331257
0x01, // TOO LOW
12341258
0x42, 'h', 'i', // "hi"
12351259
0xFA, 0x40, 0x48, 0xf5, 0xc3,
@@ -1289,8 +1313,9 @@ ZTEST(cbor_decode_test5, test_value_range)
12891313
zassert_equal(exp_output_value_range1.defaultfalse,
12901314
output.defaultfalse, NULL);
12911315

1292-
zassert_equal(ZCBOR_SUCCESS, cbor_decode_ValueRange(payload_value_range2, sizeof(payload_value_range2),
1293-
&output, &out_len), NULL);
1316+
int ret = cbor_decode_ValueRange(payload_value_range2, sizeof(payload_value_range2),
1317+
&output, &out_len);
1318+
zassert_equal(ZCBOR_SUCCESS, ret, zcbor_error_str(ret));
12941319
zassert_equal(sizeof(payload_value_range2), out_len, "%d != %d", sizeof(payload_value_range2), out_len);
12951320
zassert_equal(exp_output_value_range2.greater10,
12961321
output.greater10, NULL);
@@ -1330,8 +1355,9 @@ ZTEST(cbor_decode_test5, test_value_range)
13301355
zassert_equal(ZCBOR_ERR_WRONG_RANGE, cbor_decode_ValueRange(payload_value_range11_inv,
13311356
sizeof(payload_value_range11_inv), &output, &out_len), NULL);
13321357
// HIGH_ELEM_COUNT because the entry is optional, so decoding continues to the end of the list.
1333-
zassert_equal(ARR_ERR5, cbor_decode_ValueRange(payload_value_range12_inv,
1334-
sizeof(payload_value_range12_inv), &output, &out_len), NULL);
1358+
ret = cbor_decode_ValueRange(payload_value_range12_inv,
1359+
sizeof(payload_value_range12_inv), &output, &out_len);
1360+
zassert_equal(ARR_ERR5, ret, "%s != %s\n", zcbor_error_str(ARR_ERR5), zcbor_error_str(ret));
13351361
}
13361362

13371363

tests/scripts/test_zcbor.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,5 +1300,120 @@ def test_invalid_identifiers0(self):
13001300
self.assertTrue(decoded.a_z_tstr)
13011301

13021302

1303+
def cp_from_cddl(cddl):
1304+
return zcbor.CddlParser.from_cddl(cddl, default_max_qty=3)
1305+
1306+
1307+
class TestParsingErrors(TestCase):
1308+
def cddl_parsing_error_test(self, invalid_cddl, valid_cddl, message_regex=None):
1309+
"""Check that invalid CDDL raises an error and check that a valid CDDL variant passes."""
1310+
self.assertTrue(cp_from_cddl(valid_cddl))
1311+
if message_regex is not None:
1312+
self.assertRaisesRegex(
1313+
zcbor.CddlParsingError, message_regex, cp_from_cddl, invalid_cddl
1314+
)
1315+
else:
1316+
self.assertRaises(zcbor.CddlParsingError, cp_from_cddl, invalid_cddl)
1317+
1318+
def test_invalid_cddl(self):
1319+
"""Check that certain CDDL formatting errors are caught."""
1320+
1321+
# Two values
1322+
self.cddl_parsing_error_test(
1323+
"foo = 1 .eq 2", "foo = int .eq 2", r".*Attempting to set value.*"
1324+
)
1325+
1326+
self.cddl_parsing_error_test(
1327+
"foo = float .eq 2",
1328+
"foo = float .eq 2.0",
1329+
r"Type of \.eq value does not match type of element",
1330+
)
1331+
1332+
self.cddl_parsing_error_test(
1333+
'foo = ?int .default "hello"',
1334+
'foo = ?tstr .default "hello"',
1335+
r"Type of \.default value does not match type of element",
1336+
)
1337+
1338+
self.cddl_parsing_error_test(
1339+
'foo = tstr .default "hello"',
1340+
'foo = ?tstr .default "hello"',
1341+
r"zcbor currently supports \.default only with the \? quantifier",
1342+
)
1343+
1344+
self.cddl_parsing_error_test("foo = {int}", "foo = {1 => int}", r"Missing map key")
1345+
self.cddl_parsing_error_test(
1346+
"bar = (int) foo = {bar}", "bar = (1 => int) foo = {bar}", r"Missing map key"
1347+
)
1348+
1349+
self.cddl_parsing_error_test(
1350+
"foo = 'hello'..2",
1351+
"foo = 1..2",
1352+
r"zcbor does not support type BSTR in ranges:\n'hello'\.\.2",
1353+
)
1354+
1355+
self.cddl_parsing_error_test(
1356+
"foo = int .size -1 .. 2",
1357+
"foo = int .size 1 .. 2",
1358+
r"Size range must contain only non-negative integers\.",
1359+
)
1360+
self.cddl_parsing_error_test(
1361+
f"foo = bool .size 1", f"foo = int .size 1", r"\.size cannot be applied to BOOL"
1362+
)
1363+
self.cddl_parsing_error_test(
1364+
f"foo = [] .size 1", f"foo = int .size 1", r"\.size cannot be applied to LIST"
1365+
)
1366+
self.cddl_parsing_error_test(
1367+
f"foo = int .size uint .. 2",
1368+
f"foo = int .size 1 .. 2",
1369+
r"Range values must be unambiguous\.",
1370+
)
1371+
self.cddl_parsing_error_test(
1372+
f"foo = int .size -2",
1373+
f"foo = int .size 2",
1374+
r"Value must be a non-negative integer, not NINT\.",
1375+
)
1376+
1377+
for ctrl_op in (".lt", ".gt", ".ge", ".le"):
1378+
self.cddl_parsing_error_test(
1379+
f"foo = bool {ctrl_op} 1",
1380+
f"foo = int {ctrl_op} 1",
1381+
r"Value range needs a number, got BOOL",
1382+
)
1383+
self.cddl_parsing_error_test(
1384+
f"foo = [] {ctrl_op} 1",
1385+
f"foo = int {ctrl_op} 1",
1386+
r"Value range needs a number, got LIST",
1387+
)
1388+
self.cddl_parsing_error_test(
1389+
f"foo = int {ctrl_op} 2.0",
1390+
f"foo = int {ctrl_op} 2",
1391+
r"Value must be an integer, not FLOAT\.",
1392+
)
1393+
1394+
for ctrl_op in (".size", ".lt", ".gt", ".ge", ".le"):
1395+
self.cddl_parsing_error_test(
1396+
f"foo = int {ctrl_op} uint",
1397+
f"foo = int {ctrl_op} 1",
1398+
r"Value must be unambiguous\.",
1399+
)
1400+
self.cddl_parsing_error_test(
1401+
f"foo = int {ctrl_op} 1 {ctrl_op} 2",
1402+
f"foo = int {ctrl_op} 1",
1403+
rf"Element already has {ctrl_op} modifier\.",
1404+
)
1405+
self.cddl_parsing_error_test(
1406+
f"""
1407+
foo = int {ctrl_op} bar
1408+
bar = +3
1409+
""",
1410+
f"""
1411+
foo = int {ctrl_op} bar
1412+
bar = 3
1413+
""",
1414+
r"Cannot use value with quantifier here\.",
1415+
)
1416+
1417+
13031418
if __name__ == "__main__":
13041419
main()

0 commit comments

Comments
 (0)