mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
test for cbor, based on appendix A test vector
This commit is contained in:
parent
27ab6af573
commit
06b58d36d1
4 changed files with 1136 additions and 0 deletions
638
src/cbor/tests/appendix_a.json
Normal file
638
src/cbor/tests/appendix_a.json
Normal file
|
|
@ -0,0 +1,638 @@
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"cbor": "AA==",
|
||||||
|
"hex": "00",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "AQ==",
|
||||||
|
"hex": "01",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "Cg==",
|
||||||
|
"hex": "0a",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "Fw==",
|
||||||
|
"hex": "17",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "GBg=",
|
||||||
|
"hex": "1818",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "GBk=",
|
||||||
|
"hex": "1819",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "GGQ=",
|
||||||
|
"hex": "1864",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "GQPo",
|
||||||
|
"hex": "1903e8",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "GgAPQkA=",
|
||||||
|
"hex": "1a000f4240",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1000000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "GwAAAOjUpRAA",
|
||||||
|
"hex": "1b000000e8d4a51000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1000000000000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "G///////////",
|
||||||
|
"hex": "1bffffffffffffffff",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 18446744073709551615
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "wkkBAAAAAAAAAAA=",
|
||||||
|
"hex": "c249010000000000000000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 18446744073709551616
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "O///////////",
|
||||||
|
"hex": "3bffffffffffffffff",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -18446744073709551616
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "w0kBAAAAAAAAAAA=",
|
||||||
|
"hex": "c349010000000000000000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -18446744073709551617
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "IA==",
|
||||||
|
"hex": "20",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "KQ==",
|
||||||
|
"hex": "29",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "OGM=",
|
||||||
|
"hex": "3863",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "OQPn",
|
||||||
|
"hex": "3903e7",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+QAA",
|
||||||
|
"hex": "f90000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 0.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+YAA",
|
||||||
|
"hex": "f98000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -0.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+TwA",
|
||||||
|
"hex": "f93c00",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+z/xmZmZmZma",
|
||||||
|
"hex": "fb3ff199999999999a",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+T4A",
|
||||||
|
"hex": "f93e00",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+Xv/",
|
||||||
|
"hex": "f97bff",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 65504.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+kfDUAA=",
|
||||||
|
"hex": "fa47c35000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 100000.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+n9///8=",
|
||||||
|
"hex": "fa7f7fffff",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 3.4028234663852886e+38
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+3435DyIAHWc",
|
||||||
|
"hex": "fb7e37e43c8800759c",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 1.0e+300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+QAB",
|
||||||
|
"hex": "f90001",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 5.960464477539063e-08
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+QQA",
|
||||||
|
"hex": "f90400",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": 6.103515625e-05
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+cQA",
|
||||||
|
"hex": "f9c400",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -4.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+8AQZmZmZmZm",
|
||||||
|
"hex": "fbc010666666666666",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": -4.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+XwA",
|
||||||
|
"hex": "f97c00",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "Infinity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+X4A",
|
||||||
|
"hex": "f97e00",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "NaN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+fwA",
|
||||||
|
"hex": "f9fc00",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "-Infinity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+n+AAAA=",
|
||||||
|
"hex": "fa7f800000",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "Infinity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+n/AAAA=",
|
||||||
|
"hex": "fa7fc00000",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "NaN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+v+AAAA=",
|
||||||
|
"hex": "faff800000",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "-Infinity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+3/wAAAAAAAA",
|
||||||
|
"hex": "fb7ff0000000000000",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "Infinity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+3/4AAAAAAAA",
|
||||||
|
"hex": "fb7ff8000000000000",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "NaN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+//wAAAAAAAA",
|
||||||
|
"hex": "fbfff0000000000000",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "-Infinity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "9A==",
|
||||||
|
"hex": "f4",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "9Q==",
|
||||||
|
"hex": "f5",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "9g==",
|
||||||
|
"hex": "f6",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "9w==",
|
||||||
|
"hex": "f7",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "8A==",
|
||||||
|
"hex": "f0",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "simple(16)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+Bg=",
|
||||||
|
"hex": "f818",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "simple(24)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "+P8=",
|
||||||
|
"hex": "f8ff",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "simple(255)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg==",
|
||||||
|
"hex": "c074323031332d30332d32315432303a30343a30305a",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "0(\"2013-03-21T20:04:00Z\")"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "wRpRS2ew",
|
||||||
|
"hex": "c11a514b67b0",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "1(1363896240)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "wftB1FLZ7CAAAA==",
|
||||||
|
"hex": "c1fb41d452d9ec200000",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "1(1363896240.5)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "10QBAgME",
|
||||||
|
"hex": "d74401020304",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "23(h'01020304')"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "2BhFZElFVEY=",
|
||||||
|
"hex": "d818456449455446",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "24(h'6449455446')"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "2CB2aHR0cDovL3d3dy5leGFtcGxlLmNvbQ==",
|
||||||
|
"hex": "d82076687474703a2f2f7777772e6578616d706c652e636f6d",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "32(\"http://www.example.com\")"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "QA==",
|
||||||
|
"hex": "40",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "h''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "RAECAwQ=",
|
||||||
|
"hex": "4401020304",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "h'01020304'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "YA==",
|
||||||
|
"hex": "60",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "YWE=",
|
||||||
|
"hex": "6161",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "ZElFVEY=",
|
||||||
|
"hex": "6449455446",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": "IETF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "YiJc",
|
||||||
|
"hex": "62225c",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": "\"\\"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "YsO8",
|
||||||
|
"hex": "62c3bc",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": "ü"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "Y+awtA==",
|
||||||
|
"hex": "63e6b0b4",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": "水"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "ZPCQhZE=",
|
||||||
|
"hex": "64f0908591",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": "𐅑"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gA==",
|
||||||
|
"hex": "80",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gwECAw==",
|
||||||
|
"hex": "83010203",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gwGCAgOCBAU=",
|
||||||
|
"hex": "8301820203820405",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "mBkBAgMEBQYHCAkKCwwNDg8QERITFBUWFxgYGBk=",
|
||||||
|
"hex": "98190102030405060708090a0b0c0d0e0f101112131415161718181819",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "oA==",
|
||||||
|
"hex": "a0",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "ogECAwQ=",
|
||||||
|
"hex": "a201020304",
|
||||||
|
"roundtrip": true,
|
||||||
|
"diagnostic": "{1: 2, 3: 4}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "omFhAWFiggID",
|
||||||
|
"hex": "a26161016162820203",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": {
|
||||||
|
"a": 1,
|
||||||
|
"b": [
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gmFhoWFiYWM=",
|
||||||
|
"hex": "826161a161626163",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": [
|
||||||
|
"a",
|
||||||
|
{
|
||||||
|
"b": "c"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "pWFhYUFhYmFCYWNhQ2FkYURhZWFF",
|
||||||
|
"hex": "a56161614161626142616361436164614461656145",
|
||||||
|
"roundtrip": true,
|
||||||
|
"decoded": {
|
||||||
|
"a": "A",
|
||||||
|
"b": "B",
|
||||||
|
"c": "C",
|
||||||
|
"d": "D",
|
||||||
|
"e": "E"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "X0IBAkMDBAX/",
|
||||||
|
"hex": "5f42010243030405ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"diagnostic": "(_ h'0102', h'030405')"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "f2VzdHJlYWRtaW5n/w==",
|
||||||
|
"hex": "7f657374726561646d696e67ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": "streaming"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "n/8=",
|
||||||
|
"hex": "9fff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "nwGCAgOfBAX//w==",
|
||||||
|
"hex": "9f018202039f0405ffff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "nwGCAgOCBAX/",
|
||||||
|
"hex": "9f01820203820405ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gwGCAgOfBAX/",
|
||||||
|
"hex": "83018202039f0405ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gwGfAgP/ggQF",
|
||||||
|
"hex": "83019f0203ff820405",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "nwECAwQFBgcICQoLDA0ODxAREhMUFRYXGBgYGf8=",
|
||||||
|
"hex": "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "v2FhAWFinwID//8=",
|
||||||
|
"hex": "bf61610161629f0203ffff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": {
|
||||||
|
"a": 1,
|
||||||
|
"b": [
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "gmFhv2FiYWP/",
|
||||||
|
"hex": "826161bf61626163ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": [
|
||||||
|
"a",
|
||||||
|
{
|
||||||
|
"b": "c"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cbor": "v2NGdW71Y0FtdCH/",
|
||||||
|
"hex": "bf6346756ef563416d7421ff",
|
||||||
|
"roundtrip": false,
|
||||||
|
"decoded": {
|
||||||
|
"Fun": true,
|
||||||
|
"Amt": -2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
13
src/cbor/tests/dune
Normal file
13
src/cbor/tests/dune
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
(executable
|
||||||
|
(name t_appendix_a)
|
||||||
|
(libraries yojson containers containers.cbor))
|
||||||
|
|
||||||
|
(rule
|
||||||
|
(targets t_appendix_a.out)
|
||||||
|
(action
|
||||||
|
(with-stdout-to %{targets}
|
||||||
|
(run ./t_appendix_a.exe ./appendix_a.json))))
|
||||||
|
|
||||||
|
(rule
|
||||||
|
(alias runtest)
|
||||||
|
(action (diff ./t_appendix_a.expected ./t_appendix_a.out)))
|
||||||
322
src/cbor/tests/t_appendix_a.expected
Normal file
322
src/cbor/tests/t_appendix_a.expected
Normal file
|
|
@ -0,0 +1,322 @@
|
||||||
|
decoded into 0
|
||||||
|
> RUN test "00"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 1
|
||||||
|
> RUN test "01"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 10
|
||||||
|
> RUN test "0a"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 23
|
||||||
|
> RUN test "17"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 24
|
||||||
|
> RUN test "1818"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 25
|
||||||
|
> RUN test "1819"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 100
|
||||||
|
> RUN test "1864"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 1000
|
||||||
|
> RUN test "1903e8"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 1000000
|
||||||
|
> RUN test "1a000f4240"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 1000000000000
|
||||||
|
> RUN test "1b000000e8d4a51000"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into -1
|
||||||
|
> SKIP "1bffffffffffffffff" (reason: (requires int64 loss of precision))
|
||||||
|
decoded into 2(h'010000000000000000')
|
||||||
|
> SKIP "c249010000000000000000" (reason: (bigint))
|
||||||
|
decoded into 0
|
||||||
|
> SKIP "3bffffffffffffffff" (reason: (requires int64, loss of precision))
|
||||||
|
decoded into 3(h'010000000000000000')
|
||||||
|
> RUN test "c349010000000000000000"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Intlit ("-18446744073709551617")
|
||||||
|
expect: OK
|
||||||
|
decoded into -1
|
||||||
|
> RUN test "20"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into -10
|
||||||
|
> RUN test "29"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into -100
|
||||||
|
> RUN test "3863"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into -1000
|
||||||
|
> RUN test "3903e7"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into 0.
|
||||||
|
> RUN test "f90000"
|
||||||
|
TODO: compare with `Float (0.)
|
||||||
|
expect: OK
|
||||||
|
decoded into -0.
|
||||||
|
> RUN test "f98000"
|
||||||
|
TODO: compare with `Float (-0.)
|
||||||
|
expect: OK
|
||||||
|
decoded into 1.
|
||||||
|
> RUN test "f93c00"
|
||||||
|
TODO: compare with `Float (1.)
|
||||||
|
expect: OK
|
||||||
|
decoded into 1.1
|
||||||
|
> RUN test "fb3ff199999999999a"
|
||||||
|
TODO: compare with `Float (1.1)
|
||||||
|
expect: OK
|
||||||
|
decoded into 1.5
|
||||||
|
> RUN test "f93e00"
|
||||||
|
TODO: compare with `Float (1.5)
|
||||||
|
expect: OK
|
||||||
|
decoded into 65504.
|
||||||
|
> RUN test "f97bff"
|
||||||
|
TODO: compare with `Float (65504.)
|
||||||
|
expect: OK
|
||||||
|
decoded into 100000.
|
||||||
|
> RUN test "fa47c35000"
|
||||||
|
TODO: compare with `Float (100000.)
|
||||||
|
expect: OK
|
||||||
|
decoded into 3.40282346639e+38
|
||||||
|
> RUN test "fa7f7fffff"
|
||||||
|
TODO: compare with `Float (3.40282346639e+38)
|
||||||
|
expect: OK
|
||||||
|
decoded into 1e+300
|
||||||
|
> RUN test "fb7e37e43c8800759c"
|
||||||
|
TODO: compare with `Float (1e+300)
|
||||||
|
expect: OK
|
||||||
|
decoded into 5.96046447754e-08
|
||||||
|
> RUN test "f90001"
|
||||||
|
TODO: compare with `Float (5.96046447754e-08)
|
||||||
|
expect: OK
|
||||||
|
decoded into 6.103515625e-05
|
||||||
|
> RUN test "f90400"
|
||||||
|
TODO: compare with `Float (6.103515625e-05)
|
||||||
|
expect: OK
|
||||||
|
decoded into -4.
|
||||||
|
> RUN test "f9c400"
|
||||||
|
TODO: compare with `Float (-4.)
|
||||||
|
expect: OK
|
||||||
|
decoded into -4.1
|
||||||
|
> RUN test "fbc010666666666666"
|
||||||
|
TODO: compare with `Float (-4.1)
|
||||||
|
expect: OK
|
||||||
|
decoded into inf
|
||||||
|
> RUN test "f97c00"
|
||||||
|
OK
|
||||||
|
decoded into nan
|
||||||
|
> RUN test "f97e00"
|
||||||
|
OK
|
||||||
|
decoded into -inf
|
||||||
|
> RUN test "f9fc00"
|
||||||
|
OK
|
||||||
|
decoded into inf
|
||||||
|
> RUN test "fa7f800000"
|
||||||
|
OK
|
||||||
|
decoded into nan
|
||||||
|
> RUN test "fa7fc00000"
|
||||||
|
OK
|
||||||
|
decoded into -inf
|
||||||
|
> RUN test "faff800000"
|
||||||
|
OK
|
||||||
|
decoded into inf
|
||||||
|
> RUN test "fb7ff0000000000000"
|
||||||
|
OK
|
||||||
|
decoded into nan
|
||||||
|
> RUN test "fb7ff8000000000000"
|
||||||
|
OK
|
||||||
|
decoded into -inf
|
||||||
|
> RUN test "fbfff0000000000000"
|
||||||
|
OK
|
||||||
|
decoded into false
|
||||||
|
> RUN test "f4"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Bool (false)
|
||||||
|
expect: OK
|
||||||
|
decoded into true
|
||||||
|
> RUN test "f5"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Bool (true)
|
||||||
|
expect: OK
|
||||||
|
decoded into null
|
||||||
|
> RUN test "f6"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Null
|
||||||
|
expect: OK
|
||||||
|
decoded into undefined
|
||||||
|
> RUN test "f7"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into simple(16)
|
||||||
|
> RUN test "f0"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into simple(24)
|
||||||
|
> RUN test "f818"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into simple(255)
|
||||||
|
> RUN test "f8ff"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into 0("2013-03-21T20:04:00Z")
|
||||||
|
> RUN test "c074323031332d30332d32315432303a30343a30305a"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into 1(1363896240)
|
||||||
|
> RUN test "c11a514b67b0"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into 1(1363896240.5)
|
||||||
|
> RUN test "c1fb41d452d9ec200000"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into 23(h'01020304')
|
||||||
|
> RUN test "d74401020304"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into 24(h'6449455446')
|
||||||
|
> RUN test "d818456449455446"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into 32("http://www.example.com")
|
||||||
|
> RUN test "d82076687474703a2f2f7777772e6578616d706c652e636f6d"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into h''
|
||||||
|
> RUN test "40"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into h'01020304'
|
||||||
|
> RUN test "4401020304"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into ""
|
||||||
|
> RUN test "60"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into "a"
|
||||||
|
> RUN test "6161"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into "IETF"
|
||||||
|
> RUN test "6449455446"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into "\"\\"
|
||||||
|
> RUN test "62225c"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into "\195\188"
|
||||||
|
> RUN test "62c3bc"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into "\230\176\180"
|
||||||
|
> RUN test "63e6b0b4"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into "\240\144\133\145"
|
||||||
|
> RUN test "64f0908591"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into []
|
||||||
|
> RUN test "80"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, 2, 3]
|
||||||
|
> RUN test "83010203"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, [2, 3], [4, 5]]
|
||||||
|
> RUN test "8301820203820405"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||||
|
18, 19, 20, 21, 22, 23, 24, 25]
|
||||||
|
> RUN test "98190102030405060708090a0b0c0d0e0f101112131415161718181819"
|
||||||
|
roundtrip ok
|
||||||
|
expect: OK
|
||||||
|
decoded into {}
|
||||||
|
> RUN test "a0"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Assoc ([])
|
||||||
|
expect: OK
|
||||||
|
decoded into {1: 2, 3: 4}
|
||||||
|
> RUN test "a201020304"
|
||||||
|
roundtrip ok
|
||||||
|
OK
|
||||||
|
decoded into {"a": 1, "b": [2, 3]}
|
||||||
|
> RUN test "a26161016162820203"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Assoc ([("a", `Int (1));
|
||||||
|
("b", `List ([`Int (2); `Int (3)]))])
|
||||||
|
expect: OK
|
||||||
|
decoded into ["a", {"b": "c"}]
|
||||||
|
> RUN test "826161a161626163"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Assoc ([("b", `String ("c"))])
|
||||||
|
expect: OK
|
||||||
|
decoded into {"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"}
|
||||||
|
> RUN test "a56161614161626142616361436164614461656145"
|
||||||
|
roundtrip ok
|
||||||
|
TODO: compare with `Assoc ([("a", `String ("A")); ("b", `String ("B"));
|
||||||
|
("c", `String ("C")); ("d", `String ("D"));
|
||||||
|
("e", `String ("E"))])
|
||||||
|
expect: OK
|
||||||
|
decoded into h'0102030405'
|
||||||
|
> SKIP "5f42010243030405ff" (reason: (requires representation of indefinite length))
|
||||||
|
decoded into "streaming"
|
||||||
|
> RUN test "7f657374726561646d696e67ff"
|
||||||
|
expect: OK
|
||||||
|
decoded into []
|
||||||
|
> RUN test "9fff"
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, [2, 3], [4, 5]]
|
||||||
|
> RUN test "9f018202039f0405ffff"
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, [2, 3], [4, 5]]
|
||||||
|
> RUN test "9f01820203820405ff"
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, [2, 3], [4, 5]]
|
||||||
|
> RUN test "83018202039f0405ff"
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, [2, 3], [4, 5]]
|
||||||
|
> RUN test "83019f0203ff820405"
|
||||||
|
expect: OK
|
||||||
|
decoded into [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||||
|
18, 19, 20, 21, 22, 23, 24, 25]
|
||||||
|
> RUN test "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff"
|
||||||
|
expect: OK
|
||||||
|
decoded into {"a": 1, "b": [2, 3]}
|
||||||
|
> RUN test "bf61610161629f0203ffff"
|
||||||
|
TODO: compare with `Assoc ([("a", `Int (1));
|
||||||
|
("b", `List ([`Int (2); `Int (3)]))])
|
||||||
|
expect: OK
|
||||||
|
decoded into ["a", {"b": "c"}]
|
||||||
|
> RUN test "826161bf61626163ff"
|
||||||
|
TODO: compare with `Assoc ([("b", `String ("c"))])
|
||||||
|
expect: OK
|
||||||
|
decoded into {"Fun": true, "Amt": -2}
|
||||||
|
> RUN test "bf6346756ef563416d7421ff"
|
||||||
|
TODO: compare with `Assoc ([("Fun", `Bool (true)); ("Amt", `Int (-2))])
|
||||||
|
expect: OK
|
||||||
|
|
||||||
|
|
||||||
|
#####
|
||||||
|
OK: 78 ok, 4 skip
|
||||||
163
src/cbor/tests/t_appendix_a.ml
Normal file
163
src/cbor/tests/t_appendix_a.ml
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
module J = Yojson.Safe
|
||||||
|
module Fmt = CCFormat
|
||||||
|
module Cbor = Containers_cbor
|
||||||
|
|
||||||
|
type json = Yojson.Safe.t
|
||||||
|
|
||||||
|
let pp_json = J.pretty_print ~std:true
|
||||||
|
let spf = Printf.sprintf
|
||||||
|
|
||||||
|
module Test = struct
|
||||||
|
type expect =
|
||||||
|
| Diagnostic of string
|
||||||
|
| Decoded of json
|
||||||
|
|
||||||
|
type t = {
|
||||||
|
hex: string;
|
||||||
|
raw: string;
|
||||||
|
expect: expect;
|
||||||
|
roundtrip: bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pp_expect out = function
|
||||||
|
| Diagnostic s -> Fmt.fprintf out "(diagnostic %S)" s
|
||||||
|
| Decoded j -> Fmt.fprintf out "(@[decoded:@ %a@])" J.pp j
|
||||||
|
|
||||||
|
let pp out (self:t) =
|
||||||
|
Fmt.fprintf out "{@[hex: %S,@ expected: %a,@ roundtrip: %b@]}"
|
||||||
|
self.hex pp_expect self.expect self.roundtrip
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
let extract_tests (j:json) : Test.t list =
|
||||||
|
let l = J.Util.to_list j in
|
||||||
|
List.map (fun o ->
|
||||||
|
let o = J.Util.to_assoc o in
|
||||||
|
let hex = J.Util.to_string @@ List.assoc "hex" o in
|
||||||
|
let raw = CCString.of_hex_exn @@ hex in
|
||||||
|
let roundtrip = J.Util.to_bool @@ List.assoc "roundtrip" o in
|
||||||
|
let expect =
|
||||||
|
match List.assoc_opt "decoded" o, List.assoc_opt "diagnostic" o with
|
||||||
|
| None, Some (`String s) -> Test.Diagnostic s
|
||||||
|
| Some o, _ -> Test.Decoded o
|
||||||
|
| _ -> failwith "cannot find expected result"
|
||||||
|
in
|
||||||
|
{Test.hex; raw; expect; roundtrip}
|
||||||
|
) l
|
||||||
|
|
||||||
|
(* a few tests we need to skip *)
|
||||||
|
let skip = [
|
||||||
|
"c249010000000000000000", "(bigint)";
|
||||||
|
"1BFFFFFFFFFFFFFFFF", "(requires int64, loss of precision)";
|
||||||
|
"3bffffffffffffffff", "(requires int64, loss of precision)";
|
||||||
|
"1bffffffffffffffff", "(requires int64 loss of precision)";
|
||||||
|
"5f42010243030405ff", "(requires representation of indefinite length)";
|
||||||
|
]
|
||||||
|
|
||||||
|
type count = {
|
||||||
|
mutable n_ok: int;
|
||||||
|
mutable n_err: int;
|
||||||
|
mutable n_skip: int;
|
||||||
|
}
|
||||||
|
|
||||||
|
let run_test (c:count) (t:Test.t) : unit =
|
||||||
|
try
|
||||||
|
match Cbor.decode_exn t.raw with
|
||||||
|
| exception e ->
|
||||||
|
c.n_err <- c.n_err + 1;
|
||||||
|
Fmt.printf "error when decoding %S: %s@." t.hex (Printexc.to_string e)
|
||||||
|
| cbor ->
|
||||||
|
Fmt.printf " decoded into %a@." Cbor.pp_diagnostic cbor;
|
||||||
|
|
||||||
|
(* do we skip the rest of the test? *)
|
||||||
|
match List.assoc_opt t.hex skip with
|
||||||
|
| Some reason ->
|
||||||
|
c.n_skip <- 1 + c.n_skip;
|
||||||
|
Fmt.printf "> @{<Yellow>SKIP@} %S (reason: %s)@." t.hex reason
|
||||||
|
|
||||||
|
| None ->
|
||||||
|
Fmt.printf "> RUN test %S@." t.hex;
|
||||||
|
|
||||||
|
(* check roundtrip, except on floats because we always use float64 *)
|
||||||
|
if t.roundtrip && (match cbor with `Float _ -> false | _ -> true) then (
|
||||||
|
let hex' = Cbor.encode cbor |> CCString.to_hex in
|
||||||
|
if hex' <> t.hex then (
|
||||||
|
Fmt.printf " @[<v>@{<Red>mismatch@} on roundtrip:@ from %S@ to %S@]@."
|
||||||
|
t.hex hex';
|
||||||
|
c.n_err <- c.n_err + 1;
|
||||||
|
raise Exit;
|
||||||
|
) else (
|
||||||
|
Fmt.printf " roundtrip ok@.";
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
begin match t.expect with
|
||||||
|
| Test.Diagnostic s ->
|
||||||
|
let s' = Cbor.to_string_diagnostic cbor in
|
||||||
|
(* adjust display *)
|
||||||
|
let s' = match s' with
|
||||||
|
| "inf" -> "Infinity"
|
||||||
|
| "-inf" -> "-Infinity"
|
||||||
|
| "nan" -> "NaN"
|
||||||
|
| _ -> s'
|
||||||
|
in
|
||||||
|
if s=s' then (
|
||||||
|
c.n_ok <- c.n_ok + 1;
|
||||||
|
Fmt.printf " @{<Green>OK@}@."
|
||||||
|
) else (
|
||||||
|
Fmt.printf " @{<Red>ERR@}: expected diagnostic %S, got %S@." s s';
|
||||||
|
c.n_err <- c.n_err + 1;
|
||||||
|
)
|
||||||
|
| Test.Decoded j ->
|
||||||
|
let rec compare_cj (cbor:Cbor.t) (j:json) =
|
||||||
|
match cbor, j with
|
||||||
|
| `Int i, `Int j -> i=j
|
||||||
|
| `Text s1, `String s2 -> s1=s2
|
||||||
|
| `Array l1, `List l2 ->
|
||||||
|
List.length l1 = List.length l2 &&
|
||||||
|
List.for_all2 compare_cj l1 l2
|
||||||
|
| _ ->
|
||||||
|
Fmt.printf " TODO: compare with %a@." J.pp j;
|
||||||
|
true
|
||||||
|
in
|
||||||
|
|
||||||
|
let ok = compare_cj cbor j in
|
||||||
|
|
||||||
|
if ok then (
|
||||||
|
c.n_ok <- 1 + c.n_ok;
|
||||||
|
Fmt.printf " expect: @{<Green>OK@}@."
|
||||||
|
) else (
|
||||||
|
c.n_err <- 1 + c.n_err;
|
||||||
|
Fmt.printf " expect: @{<Red>ERROR@} (got %a, expected %a)@."
|
||||||
|
Cbor.pp_diagnostic cbor J.pp j
|
||||||
|
)
|
||||||
|
end
|
||||||
|
with Exit -> ()
|
||||||
|
|
||||||
|
let run_tests (l:Test.t list) =
|
||||||
|
let c = {n_err=0; n_ok=0; n_skip=0} in
|
||||||
|
List.iter (run_test c) l;
|
||||||
|
|
||||||
|
let total = c.n_err + c.n_ok + c.n_skip in
|
||||||
|
if total <> List.length l then
|
||||||
|
Fmt.printf "@{<Blue>warning@}: ran %d tests, for list of %d tests@."
|
||||||
|
total (List.length l);
|
||||||
|
|
||||||
|
if c.n_err > 0 then (
|
||||||
|
Fmt.printf "@.@.#####@.@{<Red>FAIL@}: %d errors, %d ok, %d skip@."
|
||||||
|
c.n_err c.n_ok c.n_skip;
|
||||||
|
exit 1
|
||||||
|
) else (
|
||||||
|
Fmt.printf "@.@.#####@.@{<Green>OK@}: %d ok, %d skip@." c.n_ok c.n_skip;
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
let () =
|
||||||
|
let color = try Sys.getenv "COLOR"="1" with _ -> false in
|
||||||
|
if color then CCFormat.set_color_default true;
|
||||||
|
let content = CCIO.File.read_exn Sys.argv.(1) in
|
||||||
|
let j = Yojson.Safe.from_string content in
|
||||||
|
let tests = extract_tests j in
|
||||||
|
(*Format.printf "tests: %a@." (Fmt.Dump.list Test.pp) tests;*)
|
||||||
|
run_tests tests;
|
||||||
|
()
|
||||||
Loading…
Add table
Reference in a new issue