The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

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

add tests for new socket ops

+133
+133
tests/socket_ops.ml
··· 1 + open Printf 2 + 3 + let () = 4 + let queue_depth = 128 in 5 + let t = Uring.create ~queue_depth () in 6 + 7 + (* Create server socket - Unix.socket is necessary as io_uring doesn't have socket creation *) 8 + let server_sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in 9 + Unix.set_nonblock server_sock; 10 + printf "Server socket created\n"; 11 + 12 + (* Create an address to bind to *) 13 + let addr = Unix.ADDR_INET (Unix.inet_addr_loopback, 0) in 14 + 15 + (* Use io_uring for bind operation *) 16 + let bind_result = 17 + match Uring.bind t server_sock addr () with 18 + | None -> failwith "Failed to submit bind operation" 19 + | Some _job -> 20 + let _submitted = Uring.submit t in 21 + match Uring.wait t with 22 + | Uring.None -> failwith "No completion for bind" 23 + | Uring.Some { result; data = _ } -> 24 + if result < 0 then begin 25 + Uring.close t server_sock () |> ignore; 26 + Uring.submit t |> ignore; 27 + Uring.exit t; 28 + let err = Uring.error_of_errno (-result) in 29 + failwith (sprintf "Bind failed: %s" (Unix.error_message err)) 30 + end else 31 + result 32 + in 33 + printf "Bind completed with result: %d\n" bind_result; 34 + 35 + (* Use io_uring for listen operation *) 36 + let backlog = 10 in 37 + let listen_result = 38 + match Uring.listen t server_sock backlog () with 39 + | None -> failwith "Failed to submit listen operation" 40 + | Some _job -> 41 + let _submitted = Uring.submit t in 42 + match Uring.wait t with 43 + | Uring.None -> failwith "No completion for listen" 44 + | Uring.Some { result; data = _ } -> 45 + if result < 0 then begin 46 + Uring.close t server_sock () |> ignore; 47 + Uring.submit t |> ignore; 48 + Uring.exit t; 49 + let err = Uring.error_of_errno (-result) in 50 + failwith (sprintf "Listen failed: %s" (Unix.error_message err)) 51 + end else 52 + result 53 + in 54 + printf "Listen completed with result: %d\n" listen_result; 55 + 56 + (* Get the actual bound port - Unix.getsockname is necessary for socket introspection *) 57 + let actual_addr = Unix.getsockname server_sock in 58 + let port = match actual_addr with 59 + | Unix.ADDR_INET (_, p) -> p 60 + | _ -> failwith "Unexpected address type" 61 + in 62 + printf "Socket bound and listening on port: %d\n" port; 63 + 64 + (* Test connecting to the bound socket *) 65 + printf "Testing connection to the bound socket...\n"; 66 + 67 + (* Create client socket - Unix.socket is necessary as io_uring doesn't have socket creation *) 68 + let client_sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in 69 + Unix.set_nonblock client_sock; 70 + printf "Client socket created\n"; 71 + 72 + (* Use io_uring for connect operation *) 73 + let connect_addr = Unix.ADDR_INET (Unix.inet_addr_loopback, port) in 74 + let connect_result = 75 + match Uring.connect t client_sock connect_addr () with 76 + | None -> failwith "Failed to submit connect operation" 77 + | Some _job -> 78 + let _submitted = Uring.submit t in 79 + match Uring.wait t with 80 + | Uring.None -> failwith "No completion for connect" 81 + | Uring.Some { result; data = _ } -> 82 + (* Connect may return -EINPROGRESS for non-blocking sockets, which is normal *) 83 + if result < 0 && result <> (-115) (* -EINPROGRESS *) then begin 84 + Uring.close t client_sock () |> ignore; 85 + Uring.close t server_sock () |> ignore; 86 + Uring.submit t |> ignore; 87 + Uring.exit t; 88 + let err = Uring.error_of_errno (-result) in 89 + failwith (sprintf "Connect failed: %s (errno: %d)" (Unix.error_message err) (-result)) 90 + end else 91 + result 92 + in 93 + 94 + if connect_result = 0 || connect_result = (-115) then 95 + printf "Connect initiated successfully (result: %d)\n" connect_result 96 + else 97 + printf "Connect completed with result: %d\n" connect_result; 98 + 99 + (* Get the client socket's local port - Unix.getsockname is necessary for socket introspection *) 100 + let client_addr = Unix.getsockname client_sock in 101 + let client_port = match client_addr with 102 + | Unix.ADDR_INET (_, p) -> p 103 + | _ -> failwith "Unexpected address type" 104 + in 105 + printf "Client socket connected from port: %d to port: %d\n" client_port port; 106 + 107 + (* Clean up using io_uring close operations *) 108 + begin match Uring.close t client_sock () with 109 + | None -> failwith "Failed to submit close for client socket" 110 + | Some _ -> () 111 + end; 112 + 113 + begin match Uring.close t server_sock () with 114 + | None -> failwith "Failed to submit close for server socket" 115 + | Some _ -> () 116 + end; 117 + 118 + let _submitted = Uring.submit t in 119 + 120 + (* Wait for both close operations to complete *) 121 + let rec wait_closes pending = 122 + if pending > 0 then 123 + match Uring.wait t with 124 + | Uring.None -> failwith "No completion for close" 125 + | Uring.Some { result; data = _ } -> 126 + if result < 0 then 127 + printf "Close warning: %s\n" (Unix.error_message (Uring.error_of_errno (-result))); 128 + wait_closes (pending - 1) 129 + in 130 + wait_closes 2; 131 + 132 + Uring.exit t; 133 + printf "Test completed successfully!\n"