Skip to content

Commit

Permalink
test: add doctests
Browse files Browse the repository at this point in the history
  • Loading branch information
mchitre committed Sep 29, 2023
1 parent 940f27a commit c8ddc47
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 19 deletions.
8 changes: 4 additions & 4 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ bytes = Vector{UInt8}(pdu)

pdu2 = MyLessSimplePDU(bytes)
@assert pdu2.b == "hello world! how are you?"
@assert pdu2 == pdu
@assert pdu == pdu2
```

We can also define field lengths that depend on the value of preceding fields. For example, if we happened to know that the length of string `b` is always `2a`, we can declare:
Expand Down Expand Up @@ -212,7 +212,7 @@ pdu = MyVectorPDU(1, [1.0, 2.0, 3.0])
bytes = Vector{UInt8}(pdu)
@assert length(bytes) == 2 + 3 * sizeof(Float64)
pdu2 = MyVectorPDU(bytes)
@assert pdu2 == pdu
@assert pdu == pdu2
```

## PDUs with nested PDUs
Expand Down Expand Up @@ -240,7 +240,7 @@ bytes = Vector{UInt8}(pdu)
pdu2 = OuterPDU(bytes)

@assert pdu2.y == pdu.y # inner PDU matches
@assert pdu2 == pdu # so does the outer PDU
@assert pdu == pdu # so does the outer PDU2
```

We can infer sizes of variable length fields in nested PDUs too:
Expand All @@ -267,5 +267,5 @@ bytes = Vector{UInt8}(pdu)
pdu2 = OuterPDU2(bytes)

@assert pdu2.y == pdu.y
@assert pdu2 == pdu
@assert pdu == pdu2
```
191 changes: 176 additions & 15 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,47 +112,47 @@ end

@testset "nested" begin

struct InnerPDU <: PDU
struct InnerPDU3 <: PDU
a::UInt16
b::String
end

struct OuterPDU <: PDU
struct OuterPDU3 <: PDU
n::UInt16
inner::InnerPDU
inner::InnerPDU3
end

f1in = InnerPDU(0x1234, "hello")
f1 = OuterPDU(0x5678, f1in)
f1in = InnerPDU3(0x1234, "hello")
f1 = OuterPDU3(0x5678, f1in)
buf = Vector{UInt8}(f1)
f2 = OuterPDU(buf)
f2 = OuterPDU3(buf)

@test f1.n == f2.n
@test f1.inner == f2.inner
@test f1 == f2
@test length(buf) == 10
@test buf == [0x56, 0x78, 0x12, 0x34, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f]

Base.length(::Type{InnerPDU}, ::Val{:b}, info) = info.get(:a)
Base.length(::Type{InnerPDU3}, ::Val{:b}, info) = info.get(:a)

f1in = InnerPDU(0x05, "hello")
f1 = OuterPDU(0x5678, f1in)
f1in = InnerPDU3(0x05, "hello")
f1 = OuterPDU3(0x5678, f1in)
buf = Vector{UInt8}(f1)
f2 = OuterPDU(buf)
f2 = OuterPDU3(buf)

@test f1.n == f2.n
@test f1.inner == f2.inner
@test f1 == f2
@test length(buf) == 9
@test buf == [0x56, 0x78, 0x00, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f]

Base.length(::Type{InnerPDU}, ::Val{:b}, info) = info.length - 2
Base.length(::Type{OuterPDU}, ::Val{:inner}, info) = info.length - 2
Base.length(::Type{InnerPDU3}, ::Val{:b}, info) = info.length - 2
Base.length(::Type{OuterPDU3}, ::Val{:inner}, info) = info.length - 2

f1in = InnerPDU(0x1234, "hello")
f1 = OuterPDU(0x5678, f1in)
f1in = InnerPDU3(0x1234, "hello")
f1 = OuterPDU3(0x5678, f1in)
buf = Vector{UInt8}(f1)
f2 = OuterPDU(buf)
f2 = OuterPDU3(buf)

@test f1.n == f2.n
@test f1.inner == f2.inner
Expand All @@ -161,3 +161,164 @@ end
@test buf == [0x56, 0x78, 0x12, 0x34, 0x68, 0x65, 0x6c, 0x6c, 0x6f]

end

@testset "docs" begin

Base.@kwdef struct EthernetFrame <: PDU
dstaddr::NTuple{6,UInt8} # fixed length
srcaddr::NTuple{6,UInt8} # fixed length
ethtype::UInt16 # fixed length
payload::Vector{UInt8} # variable length
crc::UInt32 = 0 # fixed length
end

Base.length(::Type{EthernetFrame}, ::Val{:payload}, info) = info.length - 18

frame = EthernetFrame(
dstaddr = (0x01, 0x02, 0x03, 0x04, 0x05, 0x06),
srcaddr = (0x11, 0x12, 0x13, 0x14, 0x15, 0x16),
ethtype = 0x0800,
payload = [0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14]
)

bytes = Vector{UInt8}(frame)
decoded = EthernetFrame(bytes)
@test frame == decoded

struct MySimplePDU <: PDU
a::Int16
b::UInt8
c::UInt8
d::NTuple{2,Int32}
e::Float32
f::Float64
end

pdu = MySimplePDU(1, 2, 3, (4,5), 6f0, 7.0)
bytes = Vector{UInt8}(pdu)
@test bytes == UInt8[0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x40, 0xc0, 0x00, 0x00, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

ProtocolDataUnits.byteorder(::Type{MySimplePDU}) = LITTLE_ENDIAN

bytes = Vector{UInt8}(pdu)
@test bytes == UInt8[0x01, 0x00, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40]

pdu2 = MySimplePDU(bytes)
@test pdu == pdu2

struct MyLessSimplePDU <: PDU
a::Int16
b::String
end

pdu = MyLessSimplePDU(1, "hello world!")
bytes = Vector{UInt8}(pdu)
pdu2 = MyLessSimplePDU(bytes)
@test pdu == pdu2

Base.length(::Type{MyLessSimplePDU}, ::Val{:b}, info) = 14

bytes = Vector{UInt8}(pdu)
@test length(bytes) == 16

pdu2 = MyLessSimplePDU(bytes)
@test pdu == pdu2

pdu = MyLessSimplePDU(1, "hello world! how are you?")

bytes = Vector{UInt8}(pdu)
@test length(bytes) == 16

pdu2 = MyLessSimplePDU(bytes)
@test pdu2.b == "hello world! h"

Base.length(::Type{MyLessSimplePDU}, ::Val{:b}, info) = info.length - 2

bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + length("hello world! how are you?")

pdu2 = MyLessSimplePDU(bytes)
@test pdu2.b == "hello world! how are you?"
@test pdu == pdu2

Base.length(::Type{MyLessSimplePDU}, ::Val{:b}, info) = 2 * info.get(:a)

pdu = MyLessSimplePDU(6, "hello world!")

bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + 2*6

pdu2 = MyLessSimplePDU(bytes)
@test pdu2.b == "hello world!"

pdu = MyLessSimplePDU(8, "hello world!")
bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + 2*8
pdu2 = MyLessSimplePDU(bytes)
@test pdu2.b == "hello world!"

pdu = MyLessSimplePDU(4, "hello world!")
bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + 2*4
pdu2 = MyLessSimplePDU(bytes)
@test pdu2.b == "hello wo"

struct MyVectorPDU <: PDU
a::Int16
b::Vector{Float64}
end

Base.length(::Type{MyVectorPDU}, ::Val{:b}, info) = (info.length - 2) ÷ sizeof(Float64)

pdu = MyVectorPDU(1, [1.0, 2.0, 3.0])
bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + 3 * sizeof(Float64)
pdu2 = MyVectorPDU(bytes)
@test pdu == pdu2

struct InnerPDU <: PDU
a::Int8
b::Float32
end

struct OuterPDU <: PDU
x::Int16
y::InnerPDU
z::Int8
end

pdu = OuterPDU(1, InnerPDU(2, 3f0), 4)

bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + (1 + 4) + 1

pdu2 = OuterPDU(bytes)

@test pdu2.y == pdu.y # inner PDU matches
@test pdu == pdu2 # so does the outer PDU

struct InnerPDU2 <: PDU
a::Int8
b::String
end

struct OuterPDU2 <: PDU
x::Int16
y::InnerPDU2
z::Int8
end

Base.length(::Type{InnerPDU2}, ::Val{:b}, info) = info.length - 1
Base.length(::Type{OuterPDU2}, ::Val{:y}, info) = info.length - 3

pdu = OuterPDU2(1, InnerPDU2(2, "hello world!"), 4)

bytes = Vector{UInt8}(pdu)
@test length(bytes) == 2 + (1 + 12) + 1

pdu2 = OuterPDU2(bytes)

@test pdu2.y == pdu.y
@test pdu == pdu2

end

0 comments on commit c8ddc47

Please sign in to comment.