okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

nekomimi.petopenai_api: fast paths for chat tool fragments and claude deltas, requests wait for a draining connection, parallel and tool-call benchmark6b24755

main
5.4 KiB166 linesraw
1//// Hard process death cannot execute callback cleanup; real socket ownership,
2//// receive deadlines, responses split at every byte, connection reuse, and
3//// certificate verification require native transport probes beyond daemon
4//// output.
5
6import albedo/openai_api/transport
7import gleam/bit_array
8import gleam/list
9import gleam/string
10import gleam/string_tree
11import gleeunit/should
12
13type Fixture
14
15type Owner
16
17type Mode {
18  CloseDelimited
19  ChunkedTrickle
20  ContentLength
21  KeepAlive
22  DropSecond
23  SlowEnd
24}
25
26@external(erlang, "albedo_openai_transport_test_server", "start")
27fn start(mode: Mode) -> Fixture
28
29@external(erlang, "albedo_openai_transport_test_server", "start_tls")
30fn start_tls(mode: Mode) -> Fixture
31
32@external(erlang, "albedo_openai_transport_test_server", "url")
33fn url(fixture: Fixture) -> String
34
35@external(erlang, "albedo_openai_transport_test_server", "trust")
36fn trust(fixture: Fixture) -> Nil
37
38@external(erlang, "albedo_openai_transport_test_server", "distrust")
39fn distrust() -> Nil
40
41@external(erlang, "albedo_openai_transport_test_server", "owner_after_headers")
42fn owner_after_headers(fixture: Fixture) -> Owner
43
44@external(erlang, "albedo_openai_transport_test_server", "kill_owner")
45fn kill_owner(owner: Owner) -> Bool
46
47@external(erlang, "albedo_openai_transport_test_server", "await_closed")
48fn await_closed(fixture: Fixture) -> Bool
49
50@external(erlang, "albedo_openai_transport_test_server", "stop")
51fn stop(fixture: Fixture) -> Nil
52
53pub fn close_delimited_transport_releases_owned_sockets_test() -> Nil {
54  let killed = start(CloseDelimited)
55  let owner = owner_after_headers(killed)
56  kill_owner(owner) |> should.be_true
57  await_closed(killed) |> should.be_true
58  stop(killed)
59
60  let idle = start(CloseDelimited)
61  let assert Ok(connection) =
62    transport.open(url(idle), [], string_tree.new(), 2000)
63  let assert Ok(transport.Headers(200, _, False)) =
64    transport.receive(connection)
65  transport.receive(connection) |> should.equal(Error(transport.TimedOut))
66  transport.close(connection)
67  await_closed(idle) |> should.be_true
68  stop(idle)
69}
70
71pub fn plain_http_bodies_end_where_their_framing_says_test() -> Nil {
72  use mode <- list.each([ChunkedTrickle, ContentLength])
73  let fixture = start(mode)
74  get(url(fixture)) |> should.equal(Ok(<<"hello world, all">>))
75  stop(fixture)
76}
77
78/// The fixture closes its listener after one connection, so the second
79/// request succeeds only on the connection the first one left open.
80pub fn a_finished_response_leaves_its_connection_for_the_next_request_test() -> Nil {
81  let fixture = start(KeepAlive)
82  get(url(fixture)) |> should.equal(Ok(<<"hello world, all">>))
83  get(url(fixture)) |> should.equal(Ok(<<"hello world, all">>))
84  stop(fixture)
85}
86
87pub fn a_kept_connection_the_server_dropped_is_replaced_test() -> Nil {
88  let fixture = start(DropSecond)
89  get(url(fixture)) |> should.equal(Ok(<<"hello world, all">>))
90  get(url(fixture)) |> should.equal(Ok(<<"hello world, all">>))
91  stop(fixture)
92}
93
94/// A stream that has its last event returns before the chunked terminator,
95/// which the fixture sends 10 ms later. A request sent at once waits for
96/// that connection instead of opening one the fixture would refuse.
97pub fn a_finished_exchange_keeps_its_connection_before_the_response_ends_test() -> Nil {
98  let fixture = start(SlowEnd)
99  first_chunk(url(fixture), Ok) |> should.equal(Ok(<<"hello world, all">>))
100  first_chunk(url(fixture), Ok) |> should.equal(Ok(<<"hello world, all">>))
101  stop(fixture)
102}
103
104pub fn a_failed_exchange_closes_its_connection_test() -> Nil {
105  let fixture = start(SlowEnd)
106  first_chunk(url(fixture), fn(_) { Error(Nil) }) |> should.equal(Error(Nil))
107  await_closed(fixture) |> should.be_true
108  stop(fixture)
109}
110
111pub fn https_verifies_the_server_certificate_test() -> Nil {
112  let untrusted = start_tls(KeepAlive)
113  let assert Error(transport.TransportError(reason)) =
114    transport.open(url(untrusted), [], string_tree.new(), 2000)
115  string.contains(reason, "Unknown CA") |> should.be_true
116  stop(untrusted)
117
118  let trusted = start_tls(KeepAlive)
119  trust(trusted)
120  let first = get(url(trusted))
121  let second = get(url(trusted))
122  distrust()
123  stop(trusted)
124  first |> should.equal(Ok(<<"hello world, all">>))
125  second |> should.equal(Ok(<<"hello world, all">>))
126}
127
128/// One request read to its end and closed.
129fn get(url: String) -> Result(BitArray, transport.Error) {
130  let assert Ok(connection) = transport.open(url, [], string_tree.new(), 2000)
131  let read = {
132    let assert Ok(transport.Headers(200, _, False)) =
133      transport.receive(connection)
134    body(connection, <<>>)
135  }
136  transport.close(connection)
137  read
138}
139
140/// One request whose exchange ends after the first body chunk, as `finish`
141/// says.
142fn first_chunk(
143  url: String,
144  finish: fn(BitArray) -> Result(BitArray, Nil),
145) -> Result(BitArray, Nil) {
146  let assert Ok(connection) = transport.open(url, [], string_tree.new(), 2000)
147  use <- transport.with_connection(connection)
148  let assert Ok(transport.Headers(200, _, False)) =
149    transport.receive(connection)
150  let assert Ok(transport.Data(bytes, False)) = transport.receive(connection)
151  finish(bytes)
152}
153
154fn body(
155  connection: transport.Connection,
156  read: BitArray,
157) -> Result(BitArray, transport.Error) {
158  case transport.receive(connection) {
159    Ok(transport.Data(bytes, True)) -> Ok(bit_array.append(read, bytes))
160    Ok(transport.Data(bytes, False)) ->
161      body(connection, bit_array.append(read, bytes))
162    Ok(transport.Headers(..)) ->
163      Error(transport.TransportError("headers again"))
164    Error(error) -> Error(error)
165  }
166}