2023-05-18 08:24:17 +00:00
|
|
|
{.used.}
|
|
|
|
|
2022-07-01 18:19:57 +00:00
|
|
|
# Nim-Libp2p
|
2023-01-20 14:47:40 +00:00
|
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
2022-07-01 18:19:57 +00:00
|
|
|
# Licensed under either of
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
|
|
# at your option.
|
|
|
|
# This file may not be copied, modified, or distributed except according to
|
|
|
|
# those terms.
|
2020-07-13 12:43:07 +00:00
|
|
|
|
2021-05-21 16:27:01 +00:00
|
|
|
import unittest2
|
2020-07-13 12:43:07 +00:00
|
|
|
import ../libp2p/protobuf/minprotobuf
|
|
|
|
import stew/byteutils, strutils
|
|
|
|
|
|
|
|
suite "MinProtobuf test suite":
|
|
|
|
const VarintVectors = [
|
|
|
|
"0800", "0801", "08ffffffff07", "08ffffffff0f", "08ffffffffffffffff7f",
|
2024-06-11 15:18:06 +00:00
|
|
|
"08ffffffffffffffffff01",
|
2020-07-13 12:43:07 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
const VarintValues = [
|
2024-06-11 15:18:06 +00:00
|
|
|
0x0'u64, 0x1'u64, 0x7FFF_FFFF'u64, 0xFFFF_FFFF'u64, 0x7FFF_FFFF_FFFF_FFFF'u64,
|
|
|
|
0xFFFF_FFFF_FFFF_FFFF'u64,
|
2020-07-13 12:43:07 +00:00
|
|
|
]
|
|
|
|
|
2024-06-11 15:18:06 +00:00
|
|
|
const Fixed32Vectors =
|
|
|
|
["0d00000000", "0d01000000", "0dffffff7f", "0dddccbbaa", "0dffffffff"]
|
2020-07-13 12:43:07 +00:00
|
|
|
|
2024-06-11 15:18:06 +00:00
|
|
|
const Fixed32Values =
|
|
|
|
[0x0'u32, 0x1'u32, 0x7FFF_FFFF'u32, 0xAABB_CCDD'u32, 0xFFFF_FFFF'u32]
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
const Fixed64Vectors = [
|
|
|
|
"090000000000000000", "090100000000000000", "09ffffff7f00000000",
|
|
|
|
"09ddccbbaa00000000", "09ffffffff00000000", "09ffffffffffffff7f",
|
2024-06-11 15:18:06 +00:00
|
|
|
"099988ffeeddccbbaa", "09ffffffffffffffff",
|
2020-07-13 12:43:07 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
const Fixed64Values = [
|
|
|
|
0x0'u64, 0x1'u64, 0x7FFF_FFFF'u64, 0xAABB_CCDD'u64, 0xFFFF_FFFF'u64,
|
2024-06-11 15:18:06 +00:00
|
|
|
0x7FFF_FFFF_FFFF_FFFF'u64, 0xAABB_CCDD_EEFF_8899'u64, 0xFFFF_FFFF_FFFF_FFFF'u64,
|
2020-07-13 12:43:07 +00:00
|
|
|
]
|
|
|
|
|
2024-06-11 15:18:06 +00:00
|
|
|
const LengthVectors =
|
|
|
|
["0a00", "0a0161", "0a026162", "0a0461626364", "0a086162636465666768"]
|
2020-07-13 12:43:07 +00:00
|
|
|
|
2024-06-11 15:18:06 +00:00
|
|
|
const LengthValues = ["", "a", "ab", "abcd", "abcdefgh"]
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
## This vector values was tested with `protoc` and related proto file.
|
|
|
|
|
|
|
|
## syntax = "proto2";
|
|
|
|
## message testmsg {
|
|
|
|
## repeated uint64 d = 1 [packed=true];
|
|
|
|
## repeated uint64 d = 2 [packed=true];
|
|
|
|
## }
|
|
|
|
const PackedVarintVector =
|
|
|
|
"0a1f0001ffffffff07ffffffff0fffffffffffffffff7fffffffffffffffffff0112020001"
|
|
|
|
## syntax = "proto2";
|
|
|
|
## message testmsg {
|
|
|
|
## repeated sfixed32 d = 1 [packed=true];
|
|
|
|
## repeated sfixed32 d = 2 [packed=true];
|
|
|
|
## }
|
|
|
|
const PackedFixed32Vector =
|
|
|
|
"0a140000000001000000ffffff7fddccbbaaffffffff12080000000001000000"
|
|
|
|
## syntax = "proto2";
|
|
|
|
## message testmsg {
|
|
|
|
## repeated sfixed64 d = 1 [packed=true];
|
|
|
|
## repeated sfixed64 d = 2 [packed=true];
|
|
|
|
## }
|
|
|
|
const PackedFixed64Vector =
|
|
|
|
"""0a4000000000000000000100000000000000ffffff7f00000000ddccbbaa00000000
|
|
|
|
ffffffff00000000ffffffffffffff7f9988ffeeddccbbaaffffffffffffffff1210
|
|
|
|
00000000000000000100000000000000"""
|
|
|
|
|
|
|
|
proc getVarintEncodedValue(value: uint64): seq[byte] =
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
pb.write(1, value)
|
|
|
|
pb.finish()
|
|
|
|
return pb.buffer
|
|
|
|
|
2021-12-16 10:05:20 +00:00
|
|
|
proc getVarintDecodedValue(data: openArray[byte]): uint64 =
|
2020-07-13 12:43:07 +00:00
|
|
|
var value: uint64
|
|
|
|
var pb = initProtoBuffer(data)
|
|
|
|
let res = pb.getField(1, value)
|
2020-07-15 08:25:39 +00:00
|
|
|
doAssert(res.isOk() == true and res.get() == true)
|
2020-07-13 12:43:07 +00:00
|
|
|
value
|
|
|
|
|
|
|
|
proc getFixed32EncodedValue(value: float32): seq[byte] =
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
pb.write(1, value)
|
|
|
|
pb.finish()
|
|
|
|
return pb.buffer
|
|
|
|
|
2021-12-16 10:05:20 +00:00
|
|
|
proc getFixed32DecodedValue(data: openArray[byte]): uint32 =
|
2020-07-13 12:43:07 +00:00
|
|
|
var value: float32
|
|
|
|
var pb = initProtoBuffer(data)
|
|
|
|
let res = pb.getField(1, value)
|
2020-07-15 08:25:39 +00:00
|
|
|
doAssert(res.isOk() == true and res.get() == true)
|
2020-07-13 12:43:07 +00:00
|
|
|
cast[uint32](value)
|
|
|
|
|
|
|
|
proc getFixed64EncodedValue(value: float64): seq[byte] =
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
pb.write(1, value)
|
|
|
|
pb.finish()
|
|
|
|
return pb.buffer
|
|
|
|
|
2021-12-16 10:05:20 +00:00
|
|
|
proc getFixed64DecodedValue(data: openArray[byte]): uint64 =
|
2020-07-13 12:43:07 +00:00
|
|
|
var value: float64
|
|
|
|
var pb = initProtoBuffer(data)
|
|
|
|
let res = pb.getField(1, value)
|
2020-07-15 08:25:39 +00:00
|
|
|
doAssert(res.isOk() == true and res.get() == true)
|
2020-07-13 12:43:07 +00:00
|
|
|
cast[uint64](value)
|
|
|
|
|
|
|
|
proc getLengthEncodedValue(value: string): seq[byte] =
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
pb.write(1, value)
|
|
|
|
pb.finish()
|
|
|
|
return pb.buffer
|
|
|
|
|
|
|
|
proc getLengthEncodedValue(value: seq[byte]): seq[byte] =
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
pb.write(1, value)
|
|
|
|
pb.finish()
|
|
|
|
return pb.buffer
|
|
|
|
|
2021-12-16 10:05:20 +00:00
|
|
|
proc getLengthDecodedValue(data: openArray[byte]): string =
|
2020-07-13 12:43:07 +00:00
|
|
|
var value = newString(len(data))
|
|
|
|
var valueLen = 0
|
|
|
|
var pb = initProtoBuffer(data)
|
|
|
|
let res = pb.getField(1, value, valueLen)
|
2020-07-15 08:25:39 +00:00
|
|
|
doAssert(res.isOk() == true and res.get() == true)
|
2020-07-13 12:43:07 +00:00
|
|
|
value.setLen(valueLen)
|
|
|
|
value
|
|
|
|
|
2024-06-11 15:18:06 +00:00
|
|
|
proc isFullZero[T: byte | char](data: openArray[T]): bool =
|
2020-07-13 12:43:07 +00:00
|
|
|
for ch in data:
|
|
|
|
if int(ch) != 0:
|
|
|
|
return false
|
|
|
|
return true
|
|
|
|
|
2021-12-16 10:05:20 +00:00
|
|
|
proc corruptHeader(data: var openArray[byte], index: int) =
|
2020-07-13 12:43:07 +00:00
|
|
|
var values = [3, 4, 6]
|
|
|
|
data[0] = data[0] and 0xF8'u8
|
|
|
|
data[0] = data[0] or byte(values[index mod len(values)])
|
|
|
|
|
|
|
|
test "[varint] edge values test":
|
|
|
|
for i in 0 ..< len(VarintValues):
|
|
|
|
let data = getVarintEncodedValue(VarintValues[i])
|
|
|
|
check:
|
|
|
|
toHex(data) == VarintVectors[i]
|
|
|
|
getVarintDecodedValue(data) == VarintValues[i]
|
|
|
|
|
|
|
|
test "[varint] mixing many values with same field number test":
|
|
|
|
for i in 0 ..< len(VarintValues):
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
for k in 0 ..< len(VarintValues):
|
|
|
|
let index = (i + k + 1) mod len(VarintValues)
|
|
|
|
pb.write(1, VarintValues[index])
|
|
|
|
pb.finish()
|
|
|
|
check getVarintDecodedValue(pb.buffer) == VarintValues[i]
|
|
|
|
|
|
|
|
test "[varint] incorrect values test":
|
|
|
|
for i in 0 ..< len(VarintValues):
|
|
|
|
var value: uint64
|
|
|
|
var data = getVarintEncodedValue(VarintValues[i])
|
|
|
|
# corrupting
|
|
|
|
data.setLen(len(data) - 1)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[varint] non-existent field test":
|
|
|
|
for i in 0 ..< len(VarintValues):
|
|
|
|
var value: uint64
|
|
|
|
var data = getVarintEncodedValue(VarintValues[i])
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(2, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[varint] corrupted header test":
|
|
|
|
for i in 0 ..< len(VarintValues):
|
|
|
|
for k in 0 ..< 3:
|
|
|
|
var value: uint64
|
|
|
|
var data = getVarintEncodedValue(VarintValues[i])
|
|
|
|
data.corruptHeader(k)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[varint] empty buffer test":
|
|
|
|
var value: uint64
|
|
|
|
var pb = initProtoBuffer()
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[varint] Repeated field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
pb1.write(1, VarintValues[1])
|
|
|
|
pb1.write(1, VarintValues[2])
|
|
|
|
pb1.write(2, VarintValues[3])
|
|
|
|
pb1.write(1, VarintValues[4])
|
|
|
|
pb1.write(1, VarintValues[5])
|
|
|
|
pb1.finish()
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[uint64]
|
|
|
|
var fieldarr2: seq[uint64]
|
|
|
|
var fieldarr3: seq[uint64]
|
|
|
|
let r1 = pb2.getRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 1
|
|
|
|
len(fieldarr1) == 4
|
|
|
|
fieldarr1[0] == VarintValues[1]
|
|
|
|
fieldarr1[1] == VarintValues[2]
|
|
|
|
fieldarr1[2] == VarintValues[4]
|
|
|
|
fieldarr1[3] == VarintValues[5]
|
|
|
|
fieldarr2[0] == VarintValues[3]
|
|
|
|
|
|
|
|
test "[varint] Repeated packed field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
pb1.writePacked(1, VarintValues)
|
|
|
|
pb1.writePacked(2, VarintValues[0 .. 1])
|
|
|
|
pb1.finish()
|
|
|
|
check:
|
|
|
|
toHex(pb1.buffer) == PackedVarintVector
|
|
|
|
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[uint64]
|
|
|
|
var fieldarr2: seq[uint64]
|
|
|
|
var fieldarr3: seq[uint64]
|
|
|
|
let r1 = pb2.getPackedRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getPackedRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getPackedRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 2
|
|
|
|
len(fieldarr1) == 6
|
|
|
|
fieldarr1[0] == VarintValues[0]
|
|
|
|
fieldarr1[1] == VarintValues[1]
|
|
|
|
fieldarr1[2] == VarintValues[2]
|
|
|
|
fieldarr1[3] == VarintValues[3]
|
|
|
|
fieldarr1[4] == VarintValues[4]
|
|
|
|
fieldarr1[5] == VarintValues[5]
|
|
|
|
fieldarr2[0] == VarintValues[0]
|
|
|
|
fieldarr2[1] == VarintValues[1]
|
|
|
|
|
|
|
|
test "[fixed32] edge values test":
|
|
|
|
for i in 0 ..< len(Fixed32Values):
|
|
|
|
let data = getFixed32EncodedValue(cast[float32](Fixed32Values[i]))
|
|
|
|
check:
|
|
|
|
toHex(data) == Fixed32Vectors[i]
|
|
|
|
getFixed32DecodedValue(data) == Fixed32Values[i]
|
|
|
|
|
|
|
|
test "[fixed32] mixing many values with same field number test":
|
|
|
|
for i in 0 ..< len(Fixed32Values):
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
for k in 0 ..< len(Fixed32Values):
|
|
|
|
let index = (i + k + 1) mod len(Fixed32Values)
|
|
|
|
pb.write(1, cast[float32](Fixed32Values[index]))
|
|
|
|
pb.finish()
|
|
|
|
check getFixed32DecodedValue(pb.buffer) == Fixed32Values[i]
|
|
|
|
|
|
|
|
test "[fixed32] incorrect values test":
|
|
|
|
for i in 0 ..< len(Fixed32Values):
|
|
|
|
var value: float32
|
|
|
|
var data = getFixed32EncodedValue(float32(Fixed32Values[i]))
|
|
|
|
# corrupting
|
|
|
|
data.setLen(len(data) - 1)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed32] non-existent field test":
|
|
|
|
for i in 0 ..< len(Fixed32Values):
|
|
|
|
var value: float32
|
|
|
|
var data = getFixed32EncodedValue(float32(Fixed32Values[i]))
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(2, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed32] corrupted header test":
|
|
|
|
for i in 0 ..< len(Fixed32Values):
|
|
|
|
for k in 0 ..< 3:
|
|
|
|
var value: float32
|
|
|
|
var data = getFixed32EncodedValue(float32(Fixed32Values[i]))
|
|
|
|
data.corruptHeader(k)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed32] empty buffer test":
|
|
|
|
var value: float32
|
|
|
|
var pb = initProtoBuffer()
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed32] Repeated field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
pb1.write(1, cast[float32](Fixed32Values[0]))
|
|
|
|
pb1.write(1, cast[float32](Fixed32Values[1]))
|
|
|
|
pb1.write(2, cast[float32](Fixed32Values[2]))
|
|
|
|
pb1.write(1, cast[float32](Fixed32Values[3]))
|
|
|
|
pb1.write(1, cast[float32](Fixed32Values[4]))
|
|
|
|
pb1.finish()
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[float32]
|
|
|
|
var fieldarr2: seq[float32]
|
|
|
|
var fieldarr3: seq[float32]
|
|
|
|
let r1 = pb2.getRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 1
|
|
|
|
len(fieldarr1) == 4
|
|
|
|
cast[uint32](fieldarr1[0]) == Fixed64Values[0]
|
|
|
|
cast[uint32](fieldarr1[1]) == Fixed64Values[1]
|
|
|
|
cast[uint32](fieldarr1[2]) == Fixed64Values[3]
|
|
|
|
cast[uint32](fieldarr1[3]) == Fixed64Values[4]
|
|
|
|
cast[uint32](fieldarr2[0]) == Fixed64Values[2]
|
|
|
|
|
|
|
|
test "[fixed32] Repeated packed field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
var values = newSeq[float32](len(Fixed32Values))
|
|
|
|
for i in 0 ..< len(values):
|
|
|
|
values[i] = cast[float32](Fixed32Values[i])
|
|
|
|
pb1.writePacked(1, values)
|
|
|
|
pb1.writePacked(2, values[0 .. 1])
|
|
|
|
pb1.finish()
|
|
|
|
check:
|
|
|
|
toHex(pb1.buffer) == PackedFixed32Vector
|
|
|
|
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[float32]
|
|
|
|
var fieldarr2: seq[float32]
|
|
|
|
var fieldarr3: seq[float32]
|
|
|
|
let r1 = pb2.getPackedRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getPackedRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getPackedRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 2
|
|
|
|
len(fieldarr1) == 5
|
|
|
|
cast[uint32](fieldarr1[0]) == Fixed32Values[0]
|
|
|
|
cast[uint32](fieldarr1[1]) == Fixed32Values[1]
|
|
|
|
cast[uint32](fieldarr1[2]) == Fixed32Values[2]
|
|
|
|
cast[uint32](fieldarr1[3]) == Fixed32Values[3]
|
|
|
|
cast[uint32](fieldarr1[4]) == Fixed32Values[4]
|
|
|
|
cast[uint32](fieldarr2[0]) == Fixed32Values[0]
|
|
|
|
cast[uint32](fieldarr2[1]) == Fixed32Values[1]
|
|
|
|
|
|
|
|
test "[fixed64] edge values test":
|
|
|
|
for i in 0 ..< len(Fixed64Values):
|
|
|
|
let data = getFixed64EncodedValue(cast[float64](Fixed64Values[i]))
|
|
|
|
check:
|
|
|
|
toHex(data) == Fixed64Vectors[i]
|
|
|
|
getFixed64DecodedValue(data) == Fixed64Values[i]
|
|
|
|
|
|
|
|
test "[fixed64] mixing many values with same field number test":
|
|
|
|
for i in 0 ..< len(Fixed64Values):
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
for k in 0 ..< len(Fixed64Values):
|
|
|
|
let index = (i + k + 1) mod len(Fixed64Values)
|
|
|
|
pb.write(1, cast[float64](Fixed64Values[index]))
|
|
|
|
pb.finish()
|
|
|
|
check getFixed64DecodedValue(pb.buffer) == Fixed64Values[i]
|
|
|
|
|
|
|
|
test "[fixed64] incorrect values test":
|
|
|
|
for i in 0 ..< len(Fixed64Values):
|
|
|
|
var value: float32
|
|
|
|
var data = getFixed64EncodedValue(cast[float64](Fixed64Values[i]))
|
|
|
|
# corrupting
|
|
|
|
data.setLen(len(data) - 1)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed64] non-existent field test":
|
|
|
|
for i in 0 ..< len(Fixed64Values):
|
|
|
|
var value: float64
|
|
|
|
var data = getFixed64EncodedValue(cast[float64](Fixed64Values[i]))
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(2, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed64] corrupted header test":
|
|
|
|
for i in 0 ..< len(Fixed64Values):
|
|
|
|
for k in 0 ..< 3:
|
|
|
|
var value: float64
|
|
|
|
var data = getFixed64EncodedValue(cast[float64](Fixed64Values[i]))
|
|
|
|
data.corruptHeader(k)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed64] empty buffer test":
|
|
|
|
var value: float64
|
|
|
|
var pb = initProtoBuffer()
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[fixed64] Repeated field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
pb1.write(1, cast[float64](Fixed64Values[2]))
|
|
|
|
pb1.write(1, cast[float64](Fixed64Values[3]))
|
|
|
|
pb1.write(2, cast[float64](Fixed64Values[4]))
|
|
|
|
pb1.write(1, cast[float64](Fixed64Values[5]))
|
|
|
|
pb1.write(1, cast[float64](Fixed64Values[6]))
|
|
|
|
pb1.finish()
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[float64]
|
|
|
|
var fieldarr2: seq[float64]
|
|
|
|
var fieldarr3: seq[float64]
|
|
|
|
let r1 = pb2.getRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 1
|
|
|
|
len(fieldarr1) == 4
|
|
|
|
cast[uint64](fieldarr1[0]) == Fixed64Values[2]
|
|
|
|
cast[uint64](fieldarr1[1]) == Fixed64Values[3]
|
|
|
|
cast[uint64](fieldarr1[2]) == Fixed64Values[5]
|
|
|
|
cast[uint64](fieldarr1[3]) == Fixed64Values[6]
|
|
|
|
cast[uint64](fieldarr2[0]) == Fixed64Values[4]
|
|
|
|
|
|
|
|
test "[fixed64] Repeated packed field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
var values = newSeq[float64](len(Fixed64Values))
|
|
|
|
for i in 0 ..< len(values):
|
|
|
|
values[i] = cast[float64](Fixed64Values[i])
|
|
|
|
pb1.writePacked(1, values)
|
|
|
|
pb1.writePacked(2, values[0 .. 1])
|
|
|
|
pb1.finish()
|
|
|
|
let expect = PackedFixed64Vector.multiReplace(("\n", ""), (" ", ""))
|
|
|
|
check:
|
|
|
|
toHex(pb1.buffer) == expect
|
|
|
|
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[float64]
|
|
|
|
var fieldarr2: seq[float64]
|
|
|
|
var fieldarr3: seq[float64]
|
|
|
|
let r1 = pb2.getPackedRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getPackedRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getPackedRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 2
|
|
|
|
len(fieldarr1) == 8
|
|
|
|
cast[uint64](fieldarr1[0]) == Fixed64Values[0]
|
|
|
|
cast[uint64](fieldarr1[1]) == Fixed64Values[1]
|
|
|
|
cast[uint64](fieldarr1[2]) == Fixed64Values[2]
|
|
|
|
cast[uint64](fieldarr1[3]) == Fixed64Values[3]
|
|
|
|
cast[uint64](fieldarr1[4]) == Fixed64Values[4]
|
|
|
|
cast[uint64](fieldarr1[5]) == Fixed64Values[5]
|
|
|
|
cast[uint64](fieldarr1[6]) == Fixed64Values[6]
|
|
|
|
cast[uint64](fieldarr1[7]) == Fixed64Values[7]
|
|
|
|
cast[uint64](fieldarr2[0]) == Fixed64Values[0]
|
|
|
|
cast[uint64](fieldarr2[1]) == Fixed64Values[1]
|
|
|
|
|
|
|
|
test "[length] edge values test":
|
|
|
|
for i in 0 ..< len(LengthValues):
|
|
|
|
let data1 = getLengthEncodedValue(LengthValues[i])
|
|
|
|
let data2 = getLengthEncodedValue(cast[seq[byte]](LengthValues[i]))
|
|
|
|
check:
|
|
|
|
toHex(data1) == LengthVectors[i]
|
|
|
|
toHex(data2) == LengthVectors[i]
|
|
|
|
check:
|
|
|
|
getLengthDecodedValue(data1) == LengthValues[i]
|
|
|
|
getLengthDecodedValue(data2) == LengthValues[i]
|
|
|
|
|
|
|
|
test "[length] mixing many values with same field number test":
|
|
|
|
for i in 0 ..< len(LengthValues):
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
var pb2 = initProtoBuffer()
|
|
|
|
for k in 0 ..< len(LengthValues):
|
|
|
|
let index = (i + k + 1) mod len(LengthValues)
|
|
|
|
pb1.write(1, LengthValues[index])
|
|
|
|
pb2.write(1, cast[seq[byte]](LengthValues[index]))
|
|
|
|
pb1.finish()
|
|
|
|
pb2.finish()
|
|
|
|
check getLengthDecodedValue(pb1.buffer) == LengthValues[i]
|
|
|
|
check getLengthDecodedValue(pb2.buffer) == LengthValues[i]
|
|
|
|
|
|
|
|
test "[length] incorrect values test":
|
|
|
|
for i in 0 ..< len(LengthValues):
|
|
|
|
var value = newSeq[byte](len(LengthValues[i]))
|
|
|
|
var valueLen = 0
|
|
|
|
var data = getLengthEncodedValue(LengthValues[i])
|
|
|
|
# corrupting
|
|
|
|
data.setLen(len(data) - 1)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value, valueLen)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[length] non-existent field test":
|
|
|
|
for i in 0 ..< len(LengthValues):
|
|
|
|
var value = newSeq[byte](len(LengthValues[i]))
|
|
|
|
var valueLen = 0
|
|
|
|
var data = getLengthEncodedValue(LengthValues[i])
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(2, value, valueLen)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
valueLen == 0
|
|
|
|
|
|
|
|
test "[length] corrupted header test":
|
|
|
|
for i in 0 ..< len(LengthValues):
|
|
|
|
for k in 0 ..< 3:
|
|
|
|
var value = newSeq[byte](len(LengthValues[i]))
|
|
|
|
var valueLen = 0
|
|
|
|
var data = getLengthEncodedValue(LengthValues[i])
|
|
|
|
data.corruptHeader(k)
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value, valueLen)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isErr() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[length] empty buffer test":
|
|
|
|
var value = newSeq[byte](len(LengthValues[0]))
|
|
|
|
var valueLen = 0
|
|
|
|
var pb = initProtoBuffer()
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value, valueLen)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
valueLen == 0
|
|
|
|
|
|
|
|
test "[length] buffer overflow test":
|
|
|
|
for i in 1 ..< len(LengthValues):
|
|
|
|
let data = getLengthEncodedValue(LengthValues[i])
|
|
|
|
|
|
|
|
var value = newString(len(LengthValues[i]) - 1)
|
|
|
|
var valueLen = 0
|
|
|
|
var pb = initProtoBuffer(data)
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb.getField(1, value, valueLen)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
valueLen == len(LengthValues[i])
|
|
|
|
isFullZero(value) == true
|
|
|
|
|
|
|
|
test "[length] mix of buffer overflow and normal fields test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
pb1.write(1, "TEST10")
|
|
|
|
pb1.write(1, "TEST20")
|
|
|
|
pb1.write(1, "TEST")
|
|
|
|
pb1.write(1, "TEST30")
|
|
|
|
pb1.write(1, "SOME")
|
|
|
|
pb1.finish()
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var value = newString(4)
|
|
|
|
var valueLen = 0
|
2020-07-15 08:25:39 +00:00
|
|
|
let res = pb2.getField(1, value, valueLen)
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
res.isOk() == true
|
|
|
|
res.get() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
value == "SOME"
|
|
|
|
|
|
|
|
test "[length] too big message test":
|
|
|
|
var pb1 = initProtoBuffer()
|
2022-11-15 13:01:14 +00:00
|
|
|
var bigString = newString(pb1.maxSize + 1)
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
for i in 0 ..< len(bigString):
|
|
|
|
bigString[i] = 'A'
|
|
|
|
pb1.write(1, bigString)
|
|
|
|
pb1.finish()
|
2022-11-15 13:01:14 +00:00
|
|
|
block:
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var value = newString(pb1.maxSize + 1)
|
|
|
|
var valueLen = 0
|
|
|
|
let res = pb2.getField(1, value, valueLen)
|
|
|
|
check:
|
|
|
|
res.isErr() == true
|
|
|
|
|
|
|
|
block:
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer, maxSize = uint.high)
|
|
|
|
var value = newString(pb1.maxSize + 1)
|
|
|
|
var valueLen = 0
|
|
|
|
let res = pb2.getField(1, value, valueLen)
|
|
|
|
check:
|
|
|
|
res.isErr() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
test "[length] Repeated field test":
|
|
|
|
var pb1 = initProtoBuffer()
|
|
|
|
pb1.write(1, "TEST1")
|
|
|
|
pb1.write(1, "TEST2")
|
|
|
|
pb1.write(2, "TEST5")
|
|
|
|
pb1.write(1, "TEST3")
|
|
|
|
pb1.write(1, "TEST4")
|
|
|
|
pb1.finish()
|
|
|
|
var pb2 = initProtoBuffer(pb1.buffer)
|
|
|
|
var fieldarr1: seq[seq[byte]]
|
|
|
|
var fieldarr2: seq[seq[byte]]
|
|
|
|
var fieldarr3: seq[seq[byte]]
|
|
|
|
let r1 = pb2.getRepeatedField(1, fieldarr1)
|
|
|
|
let r2 = pb2.getRepeatedField(2, fieldarr2)
|
|
|
|
let r3 = pb2.getRepeatedField(3, fieldarr3)
|
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r1.get() == true
|
|
|
|
r2.get() == true
|
|
|
|
r3.get() == false
|
2020-07-13 12:43:07 +00:00
|
|
|
len(fieldarr3) == 0
|
|
|
|
len(fieldarr2) == 1
|
|
|
|
len(fieldarr1) == 4
|
|
|
|
cast[string](fieldarr1[0]) == "TEST1"
|
|
|
|
cast[string](fieldarr1[1]) == "TEST2"
|
|
|
|
cast[string](fieldarr1[2]) == "TEST3"
|
|
|
|
cast[string](fieldarr1[3]) == "TEST4"
|
|
|
|
cast[string](fieldarr2[0]) == "TEST5"
|
|
|
|
|
|
|
|
test "Different value types in one message with same field number test":
|
|
|
|
proc getEncodedValue(): seq[byte] =
|
|
|
|
var pb = initProtoBuffer()
|
|
|
|
pb.write(1, VarintValues[1])
|
|
|
|
pb.write(2, cast[float32](Fixed32Values[1]))
|
|
|
|
pb.write(3, cast[float64](Fixed64Values[1]))
|
|
|
|
pb.write(4, LengthValues[1])
|
|
|
|
|
|
|
|
pb.write(1, VarintValues[2])
|
|
|
|
pb.write(2, cast[float32](Fixed32Values[2]))
|
|
|
|
pb.write(3, cast[float64](Fixed64Values[2]))
|
|
|
|
pb.write(4, LengthValues[2])
|
|
|
|
|
|
|
|
pb.write(1, cast[float32](Fixed32Values[3]))
|
|
|
|
pb.write(2, cast[float64](Fixed64Values[3]))
|
|
|
|
pb.write(3, LengthValues[3])
|
|
|
|
pb.write(4, VarintValues[3])
|
|
|
|
|
|
|
|
pb.write(1, cast[float64](Fixed64Values[4]))
|
|
|
|
pb.write(2, LengthValues[4])
|
|
|
|
pb.write(3, VarintValues[4])
|
|
|
|
pb.write(4, cast[float32](Fixed32Values[4]))
|
|
|
|
|
|
|
|
pb.write(1, VarintValues[1])
|
|
|
|
pb.write(2, cast[float32](Fixed32Values[1]))
|
|
|
|
pb.write(3, cast[float64](Fixed64Values[1]))
|
|
|
|
pb.write(4, LengthValues[1])
|
|
|
|
pb.finish()
|
|
|
|
pb.buffer
|
|
|
|
|
|
|
|
let msg = getEncodedValue()
|
|
|
|
let pb = initProtoBuffer(msg)
|
|
|
|
var varintValue: uint64
|
|
|
|
var fixed32Value: float32
|
|
|
|
var fixed64Value: float64
|
|
|
|
var lengthValue = newString(10)
|
|
|
|
var lengthSize: int
|
|
|
|
|
2020-07-15 08:25:39 +00:00
|
|
|
let r1 = pb.getField(1, varintValue)
|
|
|
|
let r2 = pb.getField(2, fixed32Value)
|
|
|
|
let r3 = pb.getField(3, fixed64Value)
|
|
|
|
let r4 = pb.getField(4, lengthValue, lengthSize)
|
|
|
|
|
2020-07-13 12:43:07 +00:00
|
|
|
check:
|
2020-07-15 08:25:39 +00:00
|
|
|
r1.isOk() == true
|
|
|
|
r2.isOk() == true
|
|
|
|
r3.isOk() == true
|
|
|
|
r4.isOk() == true
|
2020-07-13 12:43:07 +00:00
|
|
|
|
|
|
|
lengthValue.setLen(lengthSize)
|
|
|
|
|
|
|
|
check:
|
|
|
|
varintValue == VarintValues[1]
|
|
|
|
cast[uint32](fixed32Value) == Fixed32Values[1]
|
|
|
|
cast[uint64](fixed64Value) == Fixed64Values[1]
|
|
|
|
lengthValue == LengthValues[1]
|