Bytesrw adapter for Eio
ocaml codec
0
fork

Configure Feed

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

at 39f2189d53d4e8200addfa10188b7651d353cbce 216 lines 7.3 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(* Test reading from a mock flow *) 7let test_reader_basic () = 8 Eio_main.run @@ fun _env -> 9 let test_data = "Hello, World!" in 10 let flow = Eio.Flow.string_source test_data in 11 let reader = Bytesrw_eio.bytes_reader_of_flow flow in 12 13 (* Read first slice *) 14 let slice1 = Bytesrw.Bytes.Reader.read reader in 15 Alcotest.(check bool) 16 "slice is not eod" false 17 (Bytesrw.Bytes.Slice.is_eod slice1); 18 19 let read_data = 20 Bytes.sub_string 21 (Bytesrw.Bytes.Slice.bytes slice1) 22 (Bytesrw.Bytes.Slice.first slice1) 23 (Bytesrw.Bytes.Slice.length slice1) 24 in 25 Alcotest.(check string) "data matches" test_data read_data; 26 27 (* Next read should be eod *) 28 let slice2 = Bytesrw.Bytes.Reader.read reader in 29 Alcotest.(check bool) 30 "second read is eod" true 31 (Bytesrw.Bytes.Slice.is_eod slice2) 32 33(* Test reading with custom slice length *) 34let test_reader_custom_slice_length () = 35 Eio_main.run @@ fun _env -> 36 let test_data = "Hello, World!" in 37 let flow = Eio.Flow.string_source test_data in 38 let slice_length = 5 in 39 let reader = Bytesrw_eio.bytes_reader_of_flow ~slice_length flow in 40 41 (* Read should respect slice_length as maximum *) 42 let slice = Bytesrw.Bytes.Reader.read reader in 43 Alcotest.(check bool) 44 "slice length <= custom size" true 45 (Bytesrw.Bytes.Slice.length slice <= slice_length) 46 47(* Test reading empty flow *) 48let test_reader_empty () = 49 Eio_main.run @@ fun _env -> 50 let flow = Eio.Flow.string_source "" in 51 let reader = Bytesrw_eio.bytes_reader_of_flow flow in 52 53 let slice = Bytesrw.Bytes.Reader.read reader in 54 Alcotest.(check bool) 55 "empty flow returns eod" true 56 (Bytesrw.Bytes.Slice.is_eod slice) 57 58(* Test writing to a mock flow *) 59let test_writer_basic () = 60 Eio_main.run @@ fun _env -> 61 let buf = Buffer.create 100 in 62 let flow = Eio.Flow.buffer_sink buf in 63 let writer = Bytesrw_eio.bytes_writer_of_flow flow in 64 65 let test_data = "Hello, World!" in 66 let bytes = Bytes.of_string test_data in 67 let slice = 68 Bytesrw.Bytes.Slice.make bytes ~first:0 ~length:(Bytes.length bytes) 69 in 70 71 Bytesrw.Bytes.Writer.write writer slice; 72 73 let written = Buffer.contents buf in 74 Alcotest.(check string) "written data matches" test_data written 75 76(* Test writing with custom slice length *) 77let test_writer_custom_slice_length () = 78 Eio_main.run @@ fun _env -> 79 let buf = Buffer.create 100 in 80 let flow = Eio.Flow.buffer_sink buf in 81 let slice_length = 8 in 82 let writer = Bytesrw_eio.bytes_writer_of_flow ~slice_length flow in 83 84 let test_data = "Hello, World!" in 85 let bytes = Bytes.of_string test_data in 86 let slice = 87 Bytesrw.Bytes.Slice.make bytes ~first:0 ~length:(Bytes.length bytes) 88 in 89 90 Bytesrw.Bytes.Writer.write writer slice; 91 92 let written = Buffer.contents buf in 93 Alcotest.(check string) 94 "written data matches regardless of slice_length" test_data written 95 96(* Test writing eod slice (should be no-op) *) 97let test_writer_eod () = 98 Eio_main.run @@ fun _env -> 99 let buf = Buffer.create 100 in 100 let flow = Eio.Flow.buffer_sink buf in 101 let writer = Bytesrw_eio.bytes_writer_of_flow flow in 102 103 Bytesrw.Bytes.Writer.write writer Bytesrw.Bytes.Slice.eod; 104 105 let written = Buffer.contents buf in 106 Alcotest.(check string) "eod writes nothing" "" written 107 108(* Test writing partial slice *) 109let test_writer_partial_slice () = 110 Eio_main.run @@ fun _env -> 111 let buf = Buffer.create 100 in 112 let flow = Eio.Flow.buffer_sink buf in 113 let writer = Bytesrw_eio.bytes_writer_of_flow flow in 114 115 let test_data = "Hello, World!" in 116 let bytes = Bytes.of_string test_data in 117 (* Write only "World" *) 118 let slice = Bytesrw.Bytes.Slice.make bytes ~first:7 ~length:5 in 119 120 Bytesrw.Bytes.Writer.write writer slice; 121 122 let written = Buffer.contents buf in 123 Alcotest.(check string) "partial slice written" "World" written 124 125(* Test multiple reads to ensure data isolation - buffers from previous reads 126 should not be corrupted by subsequent reads *) 127let test_reader_multiple_reads () = 128 Eio_main.run @@ fun _env -> 129 let test_data = "ABCDEFGHIJ" in 130 (* 10 bytes *) 131 let flow = Eio.Flow.string_source test_data in 132 let reader = Bytesrw_eio.bytes_reader_of_flow ~slice_length:5 flow in 133 134 (* Read first 5 bytes *) 135 let slice1 = Bytesrw.Bytes.Reader.read reader in 136 let bytes1 = Bytesrw.Bytes.Slice.bytes slice1 in 137 let data1 = 138 Bytes.sub_string bytes1 139 (Bytesrw.Bytes.Slice.first slice1) 140 (Bytesrw.Bytes.Slice.length slice1) 141 in 142 143 (* Read next 5 bytes *) 144 let slice2 = Bytesrw.Bytes.Reader.read reader in 145 let data2 = 146 Bytes.sub_string 147 (Bytesrw.Bytes.Slice.bytes slice2) 148 (Bytesrw.Bytes.Slice.first slice2) 149 (Bytesrw.Bytes.Slice.length slice2) 150 in 151 152 (* Critical test: verify first read's data is STILL intact after second read 153 This would fail if we were reusing buffers or if Cstruct.to_bytes created a view *) 154 let data1_check = 155 Bytes.sub_string bytes1 156 (Bytesrw.Bytes.Slice.first slice1) 157 (Bytesrw.Bytes.Slice.length slice1) 158 in 159 160 Alcotest.(check string) "first read" "ABCDE" data1; 161 Alcotest.(check string) "second read" "FGHIJ" data2; 162 Alcotest.(check string) 163 "first read still intact after second" "ABCDE" data1_check 164 165(* Test round-trip: write then read *) 166let test_roundtrip () = 167 Eio_main.run @@ fun _env -> 168 let test_data = "Round-trip test data" in 169 170 (* Write to buffer *) 171 let buf = Buffer.create 100 in 172 let write_flow = Eio.Flow.buffer_sink buf in 173 let writer = Bytesrw_eio.bytes_writer_of_flow write_flow in 174 175 let bytes = Bytes.of_string test_data in 176 let slice = 177 Bytesrw.Bytes.Slice.make bytes ~first:0 ~length:(Bytes.length bytes) 178 in 179 Bytesrw.Bytes.Writer.write writer slice; 180 181 (* Read back from buffer *) 182 let read_flow = Eio.Flow.string_source (Buffer.contents buf) in 183 let reader = Bytesrw_eio.bytes_reader_of_flow read_flow in 184 185 let read_slice = Bytesrw.Bytes.Reader.read reader in 186 let read_data = 187 Bytes.sub_string 188 (Bytesrw.Bytes.Slice.bytes read_slice) 189 (Bytesrw.Bytes.Slice.first read_slice) 190 (Bytesrw.Bytes.Slice.length read_slice) 191 in 192 193 Alcotest.(check string) "round-trip data matches" test_data read_data 194 195let () = 196 Alcotest.run "Bytesrw_eio" 197 [ 198 ( "reader", 199 [ 200 Alcotest.test_case "basic read" `Quick test_reader_basic; 201 Alcotest.test_case "custom slice length" `Quick 202 test_reader_custom_slice_length; 203 Alcotest.test_case "empty flow" `Quick test_reader_empty; 204 Alcotest.test_case "multiple reads data isolation" `Quick 205 test_reader_multiple_reads; 206 ] ); 207 ( "writer", 208 [ 209 Alcotest.test_case "basic write" `Quick test_writer_basic; 210 Alcotest.test_case "custom slice length" `Quick 211 test_writer_custom_slice_length; 212 Alcotest.test_case "eod write" `Quick test_writer_eod; 213 Alcotest.test_case "partial slice" `Quick test_writer_partial_slice; 214 ] ); 215 ("integration", [ Alcotest.test_case "round-trip" `Quick test_roundtrip ]); 216 ]