From 121292af4dfa5f27361f25a98f1de165c82c18b4 Mon Sep 17 00:00:00 2001 From: JamesWrigley Date: Mon, 8 Jul 2024 19:47:30 +0200 Subject: [PATCH] Add support for Message(::Memory) on Julia 1.11 This is necessary because `IOBuffer.data` changed to being a `Memory` in 1.11. Also added a bunch of tests to cover the untested `Message` constructors (which is how this wasn't caught earlier). Found with JET.jl. --- docs/src/_changelog.md | 6 +++++ src/message.jl | 7 ++++-- test/runtests.jl | 51 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/docs/src/_changelog.md b/docs/src/_changelog.md index 367e16c..d125358 100644 --- a/docs/src/_changelog.md +++ b/docs/src/_changelog.md @@ -7,6 +7,12 @@ CurrentModule = ZMQ This documents notable changes in ZMQ.jl. The format is based on [Keep a Changelog](https://keepachangelog.com). +## Unreleased + +### Added +- Support for creating [`Message`](@ref)'s from the new `Memory` type in Julia + 1.11 ([#244]). + ## [v1.2.6] - 2024-06-13 ### Added diff --git a/src/message.jl b/src/message.jl index c6f4060..f1849c0 100644 --- a/src/message.jl +++ b/src/message.jl @@ -103,12 +103,15 @@ mutable struct Message <: AbstractArray{UInt8,1} Message(p, pointer(p.string)+p.offset, sizeof(p)) @doc """ - Message(a::Array) + Message(a::T) where T <: DenseVector Create a message with an array as a buffer (for send). Note: the same ownership semantics as for [`Message(m::String)`](@ref) apply. + + Usually `a` will be a 1D `Array`/`Vector`, but on 1.11+ it can also be a + `Memory`. """ - Message(a::Array) = Message(a, pointer(a), sizeof(a)) + Message(a::T) where T <: DenseVector = Message(a, pointer(a), sizeof(a)) @doc """ Message(io::IOBuffer) diff --git a/test/runtests.jl b/test/runtests.jl index 8668cfa..09d89ff 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -132,6 +132,57 @@ end # ZMQ.close(s1); ZMQ.close(s2) # should happen when context is closed ZMQ.close(ZMQ._context) # immediately close global context rather than waiting for exit + @test !isopen(s1) + @test !isopen(s2) +end + +# Test all the send constructors +@testset "Message" begin + s1 = Socket(PUB) + s2 = Socket(SUB) + ZMQ.subscribe(s2, "") + ZMQ.bind(s1, "tcp://*:5555") + ZMQ.connect(s2, "tcp://localhost:5555") + + # Message(::Int) - construct from buffer size + data = rand(UInt8, 10) + m1 = Message(10) + copy!(m1, data) + ZMQ.send(s1, m1) + @test ZMQ.recv(s2) == data + + # Message(::Any, ::Ptr, ::Int) - construct from pointer to existing data + buffer = rand(UInt8, 10) + m2 = Message(buffer, pointer(buffer), length(buffer)) + ZMQ.send(s1, m2) + @test ZMQ.recv(s2) == buffer + + # Message(::String) + str_msg = "foobar" + m3 = Message(str_msg) + ZMQ.send(s1, m3) + @test String(ZMQ.recv(s2)) == str_msg + + # Message(::SubString) + m4 = Message(str_msg[1:3]) + ZMQ.send(s1, m4) + @test String(ZMQ.recv(s2)) == str_msg[1:3] + + # Message(::DenseVector) - construct from array + buffer2 = rand(UInt8, 10) + m5 = Message(buffer2) + ZMQ.send(s1, m5) + @test ZMQ.recv(s2) == buffer2 + + # Message(::IOBuffer) + buffer3 = rand(UInt8, 10) + iobuf = IOBuffer(buffer3) + m6 = Message(iobuf) + ZMQ.send(s1, m6) + @test ZMQ.recv(s2) == buffer3 + + close(s1) + close(s2) end @testset "ZMQ resource management" begin