From 2eba43e632053c3d0f2e0c6b7763501d536c30a3 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 4 Apr 2024 15:54:13 -0400 Subject: [PATCH] test: add websocket masking tests --- tests/unit/ws/dune | 6 ++++++ tests/unit/ws/masked.data | Bin 0 -> 6971 bytes tests/unit/ws/t_ws.expected | 0 tests/unit/ws/t_ws.ml | 21 +++++++++++++++++++ tests/unit/ws/t_ws_q.ml | 39 ++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 tests/unit/ws/dune create mode 100644 tests/unit/ws/masked.data create mode 100644 tests/unit/ws/t_ws.expected create mode 100644 tests/unit/ws/t_ws.ml create mode 100644 tests/unit/ws/t_ws_q.ml diff --git a/tests/unit/ws/dune b/tests/unit/ws/dune new file mode 100644 index 00000000..e190baf5 --- /dev/null +++ b/tests/unit/ws/dune @@ -0,0 +1,6 @@ + +(tests + (names t_ws t_ws_q) + (package tiny_httpd) + (deps masked.data) + (libraries tiny_httpd.ws qcheck-core qcheck-core.runner test_util)) diff --git a/tests/unit/ws/masked.data b/tests/unit/ws/masked.data new file mode 100644 index 0000000000000000000000000000000000000000..db1bf872f0489fbbc839f7d4f42e0da2def3a79d GIT binary patch literal 6971 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 K(f)^Sr~eC;VZtE* literal 0 HcmV?d00001 diff --git a/tests/unit/ws/t_ws.expected b/tests/unit/ws/t_ws.expected new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/ws/t_ws.ml b/tests/unit/ws/t_ws.ml new file mode 100644 index 00000000..3bde8eba --- /dev/null +++ b/tests/unit/ws/t_ws.ml @@ -0,0 +1,21 @@ +open Test_util + +let read_file file : string = + let buf = Buffer.create 32 in + let ic = open_in_bin file in + Buffer.add_channel buf ic (in_channel_length ic); + Buffer.contents buf + +let apply_masking = Tiny_httpd_ws.Private_.apply_masking + +let decode ~key b = + let buf = Bytes.copy b in + apply_masking ~mask_key:key buf 0 (Bytes.length buf); + buf + +let () = + let key = "\x57\x7d\xfd\x95" |> Bytes.unsafe_of_string in + let content = read_file "masked.data" in + let decoded = decode ~key (Bytes.unsafe_of_string content) in + print_endline (Bytes.unsafe_to_string decoded); + () diff --git a/tests/unit/ws/t_ws_q.ml b/tests/unit/ws/t_ws_q.ml new file mode 100644 index 00000000..6243a973 --- /dev/null +++ b/tests/unit/ws/t_ws_q.ml @@ -0,0 +1,39 @@ +open Test_util + +let apply_masking = Tiny_httpd_ws.Private_.apply_masking + +let decode ~key b = + let buf = Bytes.copy b in + apply_masking ~mask_key:key buf 0 (Bytes.length buf); + buf + +let ppb b = Printf.sprintf "%S" (Bytes.unsafe_to_string b) + +let () = + add_qcheck + @@ QCheck.Test.make ~count:10_000 + Q.( + pair (bytes_of_size (Gen.return 4)) (bytes_of_size Gen.(0 -- 6000)) + (* |> Q.add_stat ("b.size", fun (_k, b) -> Bytes.length b) *) + |> Q.add_shrink_invariant (fun (k, _) -> Bytes.length k = 4)) + (fun (key, b) -> + Q.assume (Bytes.length key = 4); + let b2 = decode ~key b in + + let is_zero = + Bytes.equal key (Bytes.unsafe_of_string "\x00\x00\x00\x00") + in + + if Bytes.length b >= 2 && not is_zero then ( + (* key must modify the byte vec *) + let are_eq = Bytes.equal b b2 in + if are_eq then + Q.Test.fail_reportf "key=%s, expected different: b=%S b2=%S" + (ppb key) (ppb b) (ppb b2) + ); + + let b3 = decode ~key b2 in + assert (Bytes.equal b b3); + true) + +let () = run_qcheck_and_exit ()