From c8ddc47264dc8a2fbdcd0db0032041d45df8000c Mon Sep 17 00:00:00 2001 From: Mandar Chitre Date: Sat, 30 Sep 2023 02:13:04 +0800 Subject: [PATCH] test: add doctests --- docs/src/index.md | 8 +- test/runtests.jl | 191 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 180 insertions(+), 19 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index d262151..c944c32 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -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: @@ -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 @@ -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: @@ -267,5 +267,5 @@ bytes = Vector{UInt8}(pdu) pdu2 = OuterPDU2(bytes) @assert pdu2.y == pdu.y -@assert pdu2 == pdu +@assert pdu == pdu2 ``` diff --git a/test/runtests.jl b/test/runtests.jl index 5a62bf8..d36f7e0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -112,20 +112,20 @@ 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 @@ -133,12 +133,12 @@ end @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 @@ -146,13 +146,13 @@ end @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 @@ -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