RPMsg inter-partition messaging
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

test(space): expand test suites for CCSDS and space protocol packages

+195 -7
+40
test/test_rpmsg.ml
··· 79 79 Alcotest.(check int) 80 80 "recv max" Rpmsg.Endpoint.max_message_size (String.length received) 81 81 82 + (* -- transport boundary cases from virtio_rpmsg_bus.c -- *) 83 + 84 + let test_send_recv_single_byte = 85 + with_pipe @@ fun ~source ~sink -> 86 + let ep = Rpmsg.Endpoint.of_source_sink ~source ~sink in 87 + Rpmsg.Endpoint.send ep "\x42"; 88 + match Rpmsg.Endpoint.recv ep ~max_size:256 with 89 + | None -> Alcotest.fail "expected message" 90 + | Some received -> 91 + Alcotest.(check int) "len" 1 (String.length received); 92 + Alcotest.(check string) "byte" "\x42" received 93 + 94 + let test_send_recv_null_payload = 95 + (* All-zero payload — exercises the transport with null bytes that could be 96 + confused with message terminators on buggy implementations. *) 97 + with_pipe @@ fun ~source ~sink -> 98 + let ep = Rpmsg.Endpoint.of_source_sink ~source ~sink in 99 + let msg = String.make 16 '\x00' in 100 + Rpmsg.Endpoint.send ep msg; 101 + match Rpmsg.Endpoint.recv ep ~max_size:256 with 102 + | None -> Alcotest.fail "expected message" 103 + | Some received -> 104 + Alcotest.(check int) "len" 16 (String.length received); 105 + Alcotest.(check string) "null payload" msg received 106 + 107 + let test_send_recv_high_bytes = 108 + (* All-0xFF payload — high bytes that could trip sign-extension bugs. *) 109 + with_pipe @@ fun ~source ~sink -> 110 + let ep = Rpmsg.Endpoint.of_source_sink ~source ~sink in 111 + let msg = String.make 16 '\xff' in 112 + Rpmsg.Endpoint.send ep msg; 113 + match Rpmsg.Endpoint.recv ep ~max_size:256 with 114 + | None -> Alcotest.fail "expected message" 115 + | Some received -> 116 + Alcotest.(check int) "len" 16 (String.length received); 117 + Alcotest.(check string) "0xFF payload" msg received 118 + 82 119 (* -- endpoint close -- *) 83 120 84 121 let test_endpoint_close = ··· 111 148 Alcotest.test_case "send/recv" `Quick test_send_recv; 112 149 Alcotest.test_case "binary" `Quick test_send_recv_binary; 113 150 Alcotest.test_case "max size" `Quick test_send_max_size; 151 + Alcotest.test_case "single byte" `Quick test_send_recv_single_byte; 152 + Alcotest.test_case "null payload" `Quick test_send_recv_null_payload; 153 + Alcotest.test_case "0xFF payload" `Quick test_send_recv_high_bytes; 114 154 Alcotest.test_case "endpoint close" `Quick test_endpoint_close; 115 155 Alcotest.test_case "ctrl open fails on macOS" `Quick 116 156 test_ctrl_open_fails_macos;
+155 -7
test/test_wire.ml
··· 1 1 (** Tests for Rpmsg wire codec. 2 2 3 - Upstream test vectors from Linux kernel: 3 + Upstream test vectors from Linux kernel [include/uapi/linux/rpmsg.h]: 4 4 - struct rpmsg_endpoint_info: name[32], __u32 src, __u32 dst 5 - - Total size: 40 bytes 5 + - Total size: 40 bytes (RPMSG_NAME_SIZE + 2 * sizeof(__u32)) 6 + - RPMSG_ADDR_ANY = 0xFFFFFFFF 6 7 - RPMSG_CREATE_EPT_IOCTL = _IOW(0xb5, 0x1, struct rpmsg_endpoint_info) 7 - - RPMSG_DESTROY_EPT_IOCTL = _IOW(0xb5, 0x2, struct rpmsg_endpoint_info) *) 8 + - RPMSG_DESTROY_EPT_IOCTL = _IOW(0xb5, 0x2, struct rpmsg_endpoint_info) 9 + - RPMSG_CREATE_DEV_IOCTL = _IOW(0xb5, 0x3, struct rpmsg_endpoint_info) 10 + - RPMSG_RELEASE_DEV_IOCTL = _IOW(0xb5, 0x4, struct rpmsg_endpoint_info) *) 11 + 12 + (* RPMSG_ADDR_ANY from include/uapi/linux/rpmsg.h *) 13 + let rpmsg_addr_any = 0xFFFFFFFF 14 + 15 + (* _IOW(type, nr, size) from include/uapi/asm-generic/ioctl.h *) 16 + let _iow typ nr size = (1 lsl 30) lor (size lsl 16) lor (typ lsl 8) lor nr 8 17 9 18 (* -- struct size -- *) 10 19 ··· 60 69 Alcotest.(check int) "src" 42 decoded.src; 61 70 Alcotest.(check int) "dst" 43 decoded.dst 62 71 72 + (* -- known binary vectors from kernel struct layout -- *) 73 + 74 + (** Build a raw 40-byte rpmsg_endpoint_info in kernel layout: name[32] 75 + (null-padded) || src:u32le || dst:u32le *) 76 + let make_raw_info name src dst = 77 + let buf = Bytes.make 40 '\x00' in 78 + let len = min (String.length name) 31 in 79 + Bytes.blit_string name 0 buf 0 len; 80 + (* src: uint32 little-endian at offset 32 *) 81 + Bytes.set buf 32 (Char.chr (src land 0xFF)); 82 + Bytes.set buf 33 (Char.chr ((src lsr 8) land 0xFF)); 83 + Bytes.set buf 34 (Char.chr ((src lsr 16) land 0xFF)); 84 + Bytes.set buf 35 (Char.chr ((src lsr 24) land 0xFF)); 85 + (* dst: uint32 little-endian at offset 36 *) 86 + Bytes.set buf 36 (Char.chr (dst land 0xFF)); 87 + Bytes.set buf 37 (Char.chr ((dst lsr 8) land 0xFF)); 88 + Bytes.set buf 38 (Char.chr ((dst lsr 16) land 0xFF)); 89 + Bytes.set buf 39 (Char.chr ((dst lsr 24) land 0xFF)); 90 + buf 91 + 92 + let test_decode_known_vector () = 93 + (* Kernel self-test default: rpmsg-client-sample with RPMSG_ADDR_ANY *) 94 + let raw = make_raw_info "rpmsg-client-sample" rpmsg_addr_any rpmsg_addr_any in 95 + let decoded = Wire.Codec.decode Rpmsg.endpoint_info_codec raw 0 in 96 + Alcotest.(check bool) 97 + "name" true 98 + (String.sub decoded.name 0 19 = "rpmsg-client-sample"); 99 + Alcotest.(check int) "src" rpmsg_addr_any decoded.src; 100 + Alcotest.(check int) "dst" rpmsg_addr_any decoded.dst 101 + 102 + let test_encode_known_vector () = 103 + (* Encode and verify exact byte layout matches kernel struct *) 104 + let info = 105 + Rpmsg. 106 + { 107 + name = "rpmsg-client-sample"; 108 + src = rpmsg_addr_any; 109 + dst = rpmsg_addr_any; 110 + } 111 + in 112 + let buf = Bytes.create 40 in 113 + Wire.Codec.encode Rpmsg.endpoint_info_codec info buf 0; 114 + let expected = 115 + make_raw_info "rpmsg-client-sample" rpmsg_addr_any rpmsg_addr_any 116 + in 117 + Alcotest.(check string) 118 + "wire bytes" (Bytes.to_string expected) (Bytes.to_string buf) 119 + 120 + let test_decode_openamp_vector () = 121 + (* OpenAMP demo channel: name="rpmsg-openamp-demo-channel", src=1024, dst=1025 122 + Common on Zynq UltraScale+ and STM32MP1 targets. *) 123 + let raw = make_raw_info "rpmsg-openamp-demo-channel" 1024 1025 in 124 + let decoded = Wire.Codec.decode Rpmsg.endpoint_info_codec raw 0 in 125 + Alcotest.(check bool) 126 + "name" true 127 + (String.sub decoded.name 0 26 = "rpmsg-openamp-demo-channel"); 128 + Alcotest.(check int) "src" 1024 decoded.src; 129 + Alcotest.(check int) "dst" 1025 decoded.dst 130 + 131 + let test_encode_openamp_vector () = 132 + let info = 133 + Rpmsg.{ name = "rpmsg-openamp-demo-channel"; src = 1024; dst = 1025 } 134 + in 135 + let buf = Bytes.create 40 in 136 + Wire.Codec.encode Rpmsg.endpoint_info_codec info buf 0; 137 + let expected = make_raw_info "rpmsg-openamp-demo-channel" 1024 1025 in 138 + Alcotest.(check string) 139 + "wire bytes" (Bytes.to_string expected) (Bytes.to_string buf) 140 + 141 + (* -- RPMSG_ADDR_ANY boundary -- *) 142 + 143 + let test_codec_addr_any () = 144 + (* RPMSG_ADDR_ANY (0xFFFFFFFF) is passed as src/dst when creating endpoints 145 + with rpmsg_create_ept() in the kernel. *) 146 + let info = 147 + Rpmsg.{ name = "test"; src = rpmsg_addr_any; dst = rpmsg_addr_any } 148 + in 149 + let buf = Bytes.create 40 in 150 + Wire.Codec.encode Rpmsg.endpoint_info_codec info buf 0; 151 + let decoded = Wire.Codec.decode Rpmsg.endpoint_info_codec buf 0 in 152 + Alcotest.(check int) "src ADDR_ANY" rpmsg_addr_any decoded.src; 153 + Alcotest.(check int) "dst ADDR_ANY" rpmsg_addr_any decoded.dst 154 + 155 + let test_codec_zero_addrs () = 156 + let info = Rpmsg.{ name = "test"; src = 0; dst = 0 } in 157 + let buf = Bytes.create 40 in 158 + Wire.Codec.encode Rpmsg.endpoint_info_codec info buf 0; 159 + let decoded = Wire.Codec.decode Rpmsg.endpoint_info_codec buf 0 in 160 + Alcotest.(check int) "src 0" 0 decoded.src; 161 + Alcotest.(check int) "dst 0" 0 decoded.dst 162 + 163 + (* -- name edge cases -- *) 164 + 165 + let test_codec_empty_name () = 166 + (* Empty name should produce 32 null bytes in the name field *) 167 + let info = Rpmsg.{ name = ""; src = 1; dst = 2 } in 168 + let buf = Bytes.create 40 in 169 + Wire.Codec.encode Rpmsg.endpoint_info_codec info buf 0; 170 + for i = 0 to 31 do 171 + Alcotest.(check char) (Fmt.str "name[%d]" i) '\x00' (Bytes.get buf i) 172 + done; 173 + let decoded = Wire.Codec.decode Rpmsg.endpoint_info_codec buf 0 in 174 + Alcotest.(check int) "src" 1 decoded.src; 175 + Alcotest.(check int) "dst" 2 decoded.dst 176 + 177 + let test_codec_name_null_terminated () = 178 + (* Verify byte 31 is always \x00 regardless of name length. 179 + The kernel requires null termination: name[RPMSG_NAME_SIZE - 1] = '\0'. *) 180 + let info = Rpmsg.{ name = String.make 32 'A'; src = 0; dst = 0 } in 181 + let buf = Bytes.create 40 in 182 + Wire.Codec.encode Rpmsg.endpoint_info_codec info buf 0; 183 + Alcotest.(check char) "byte 31 is null" '\x00' (Bytes.get buf 31); 184 + Alcotest.(check char) "byte 30 is A" 'A' (Bytes.get buf 30) 185 + 63 186 (* -- ioctl command values -- *) 64 187 65 188 let test_ioctl_create_cmd () = 66 189 (* _IOW(0xb5, 0x1, 40) = (1 << 30) | (40 << 16) | (0xb5 << 8) | 1 *) 67 - let expected = (1 lsl 30) lor (40 lsl 16) lor (0xb5 lsl 8) lor 1 in 190 + let expected = _iow 0xb5 0x1 40 in 68 191 Alcotest.(check int) "create cmd" expected 0x4028b501 69 192 70 193 let test_ioctl_destroy_cmd () = 71 - let expected = (1 lsl 30) lor (40 lsl 16) lor (0xb5 lsl 8) lor 2 in 194 + let expected = _iow 0xb5 0x2 40 in 72 195 Alcotest.(check int) "destroy cmd" expected 0x4028b502 73 196 197 + let test_ioctl_create_dev_cmd () = 198 + (* RPMSG_CREATE_DEV_IOCTL, added in Linux 6.0 (commit 85a0679e586e) *) 199 + let expected = _iow 0xb5 0x3 40 in 200 + Alcotest.(check int) "create dev cmd" expected 0x4028b503 201 + 202 + let test_ioctl_release_dev_cmd () = 203 + (* RPMSG_RELEASE_DEV_IOCTL, added in Linux 6.0 (commit 85a0679e586e) *) 204 + let expected = _iow 0xb5 0x4 40 in 205 + Alcotest.(check int) "release dev cmd" expected 0x4028b504 206 + 74 207 let suite = 75 208 [ 76 209 ( "wire", ··· 80 213 Alcotest.test_case "short name" `Quick test_codec_short_name; 81 214 Alcotest.test_case "max name" `Quick test_codec_max_name; 82 215 Alcotest.test_case "name truncation" `Quick test_codec_name_truncation; 83 - Alcotest.test_case "ioctl create cmd" `Quick test_ioctl_create_cmd; 84 - Alcotest.test_case "ioctl destroy cmd" `Quick test_ioctl_destroy_cmd; 216 + Alcotest.test_case "decode client-sample" `Quick 217 + test_decode_known_vector; 218 + Alcotest.test_case "encode client-sample" `Quick 219 + test_encode_known_vector; 220 + Alcotest.test_case "decode openamp-demo" `Quick 221 + test_decode_openamp_vector; 222 + Alcotest.test_case "encode openamp-demo" `Quick 223 + test_encode_openamp_vector; 224 + Alcotest.test_case "ADDR_ANY roundtrip" `Quick test_codec_addr_any; 225 + Alcotest.test_case "zero addresses" `Quick test_codec_zero_addrs; 226 + Alcotest.test_case "empty name" `Quick test_codec_empty_name; 227 + Alcotest.test_case "null terminated" `Quick 228 + test_codec_name_null_terminated; 229 + Alcotest.test_case "ioctl CREATE_EPT" `Quick test_ioctl_create_cmd; 230 + Alcotest.test_case "ioctl DESTROY_EPT" `Quick test_ioctl_destroy_cmd; 231 + Alcotest.test_case "ioctl CREATE_DEV" `Quick test_ioctl_create_dev_cmd; 232 + Alcotest.test_case "ioctl RELEASE_DEV" `Quick test_ioctl_release_dev_cmd; 85 233 ] ); 86 234 ]