280 lines
No EOL
7.2 KiB
Nim
280 lines
No EOL
7.2 KiB
Nim
import unittest
|
|
import sequtils
|
|
|
|
import protobuf_serialization
|
|
|
|
type
|
|
MyEnum = enum
|
|
ME1, ME2, ME3
|
|
|
|
Test1 = object
|
|
a: uint
|
|
b: string
|
|
c: char
|
|
|
|
Test3 = object
|
|
g {.sfixed32.}: int
|
|
h: int
|
|
i: Test1
|
|
j: string
|
|
k: bool
|
|
l: MyInt
|
|
|
|
MyInt = distinct int
|
|
|
|
proc to*(bytes: var seq[byte], ty: typedesc[MyInt]): MyInt =
|
|
|
|
var value: int
|
|
|
|
var shiftAmount = 0
|
|
|
|
for i in 0 ..< len(bytes):
|
|
value += int(bytes[i]) shl shiftAmount
|
|
shiftAmount += 8
|
|
|
|
result = MyInt(value)
|
|
|
|
proc toBytes*(value: MyInt): seq[byte] =
|
|
var value = value.int
|
|
|
|
while value > 0:
|
|
result.add byte(value and 0b1111_1111)
|
|
value = value shr 8
|
|
|
|
proc `==`(a, b: MyInt): bool {.borrow.}
|
|
|
|
suite "Test Varint Encoding":
|
|
test "Can encode/decode enum field":
|
|
var proto = newProtoBuffer()
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(ME3)
|
|
proto.encodeField(ME2)
|
|
|
|
var output = proto.output
|
|
assert output == @[8.byte, 4, 16, 2]
|
|
|
|
var offset = 0
|
|
|
|
let decodedME3 = decodeField(output, MyEnum, offset, bytesProcessed)
|
|
assert decodedME3.value == ME3
|
|
assert decodedME3.index == 1
|
|
|
|
let decodedME2 = decodeField(output, MyEnum, offset, bytesProcessed)
|
|
assert decodedME2.value == ME2
|
|
assert decodedME2.index == 2
|
|
|
|
test "Can encode/decode negative number field":
|
|
var proto = newProtoBuffer()
|
|
let num = -153452
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(num)
|
|
|
|
var output = proto.output
|
|
assert output == @[8.byte, 215, 221, 18]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, int, offset, bytesProcessed)
|
|
assert decoded.value == num
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode distinct number field":
|
|
var proto = newProtoBuffer()
|
|
let num = 114151.MyInt
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(num)
|
|
|
|
var output = proto.output
|
|
assert output == @[10.byte, 3, 231, 189, 1]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, MyInt, offset, bytesProcessed)
|
|
assert decoded.value.int == num.int
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode float32 number field":
|
|
var proto = newProtoBuffer()
|
|
let num = float32(1234.164423)
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(num)
|
|
|
|
var output = proto.output
|
|
assert output == @[13.byte, 67, 69, 154, 68]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, float32, offset, bytesProcessed)
|
|
assert decoded.value == num
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode float64 number field":
|
|
var proto = newProtoBuffer()
|
|
let num = 12343121537452.1644232341'f64
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(num)
|
|
|
|
var output = proto.output
|
|
assert output == @[9.byte, 84, 88, 211, 191, 182, 115, 166, 66]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, float64, offset, bytesProcessed)
|
|
assert decoded.value == num
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode bool field":
|
|
var proto = newProtoBuffer()
|
|
let boolean = true
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(boolean)
|
|
|
|
var output = proto.output
|
|
assert output == @[8.byte, 1]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, bool, offset, bytesProcessed)
|
|
assert bytesProcessed == 2
|
|
assert decoded.value == boolean
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode char field":
|
|
var proto = newProtoBuffer()
|
|
let charVal = 'G'
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(charVal)
|
|
|
|
var output = proto.output
|
|
assert output == @[8.byte, ord(charVal).byte]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, char, offset, bytesProcessed)
|
|
assert bytesProcessed == 2
|
|
assert decoded.value == charVal
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode unsigned number field":
|
|
var proto = newProtoBuffer()
|
|
let num = 123151.uint
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(num)
|
|
|
|
var output = proto.output
|
|
assert output == @[8.byte, 143, 194, 7]
|
|
var offset = 0
|
|
|
|
let decoded = decodeField(output, uint, offset, bytesProcessed)
|
|
assert decoded.value == num
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode string field":
|
|
var proto = newProtoBuffer()
|
|
let str = "hey this is a string"
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(str)
|
|
|
|
var output = proto.output
|
|
assert output == @[10.byte, 20, 104, 101, 121, 32, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, string, offset, bytesProcessed)
|
|
assert decoded.value == str
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode char seq field":
|
|
var proto = newProtoBuffer()
|
|
let charSeq = "hey this is a string".toSeq
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(charSeq)
|
|
|
|
var output = proto.output
|
|
assert output == @[10.byte, 20, 104, 101, 121, 32, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, seq[char], offset, bytesProcessed)
|
|
assert decoded.value == charSeq
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode uint8 seq field":
|
|
var proto = newProtoBuffer()
|
|
let uint8Seq = cast[seq[uint8]]("hey this is a string".toSeq)
|
|
var bytesProcessed: int
|
|
|
|
proto.encodeField(uint8Seq)
|
|
|
|
var output = proto.output
|
|
assert output == @[10.byte, 20, 104, 101, 121, 32, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103]
|
|
|
|
var offset = 0
|
|
let decoded = decodeField(output, seq[uint8], offset, bytesProcessed)
|
|
assert decoded.value == uint8Seq
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode object field":
|
|
var proto = newProtoBuffer()
|
|
|
|
let obj = Test3(g: 300, h: 200, i: Test1(a: 100, b: "this is a test", c: 'H'), j: "testing", k: true, l: 124521.MyInt)
|
|
|
|
proto.encodeField(obj)
|
|
var offset, bytesProcessed: int
|
|
|
|
var output = proto.output
|
|
let decoded = decodeField(output, Test3, offset, bytesProcessed)
|
|
assert decoded.value == obj
|
|
assert decoded.index == 1
|
|
|
|
test "Can encode/decode object":
|
|
var proto = newProtoBuffer()
|
|
|
|
let obj = Test3(g: 300, h: 200, i: Test1(a: 100, b: "this is a test", c: 'H'), j: "testing", k: true, l: 124521.MyInt)
|
|
|
|
proto.encode(obj)
|
|
var output = proto.output
|
|
let decoded = output.decode(Test3)
|
|
assert decoded == obj
|
|
|
|
test "Can encode/decode out of order object":
|
|
var proto = newProtoBuffer()
|
|
|
|
let obj = Test3(g: 400, h: 100, i: Test1(a: 100, b: "this is a test", c: 'H'), j: "testing", k: true, l: 14514.MyInt)
|
|
proto.encodeField(6, 14514.MyInt)
|
|
proto.encodeField(2, 100)
|
|
proto.encodeField(4, "testing")
|
|
proto.encodeField(1, 400)
|
|
proto.encodeField(3, Test1(a: 100, b: "this is a test", c: 'H'))
|
|
proto.encodeField(5, true)
|
|
|
|
var output = proto.output
|
|
let decoded = output.decode(Test3)
|
|
|
|
assert decoded == obj
|
|
|
|
test "Empty object field does not get encoded":
|
|
var proto = newProtoBuffer()
|
|
|
|
let obj = Test1()
|
|
proto.encodeField(1, obj)
|
|
|
|
var output = proto.output
|
|
assert output.len == 0
|
|
|
|
let decoded = output.decode(Test1)
|
|
assert decoded == obj
|
|
|
|
test "Empty object does not get encoded":
|
|
var proto = newProtoBuffer()
|
|
|
|
let obj = Test1()
|
|
proto.encode(obj)
|
|
|
|
var output = proto.output
|
|
assert output.len == 0
|
|
|
|
let decoded = output.decode(Test1)
|
|
assert decoded == obj |