Skip to content

Commit ec2b79c

Browse files
authored
test: add regression test for non-blocking stream (#1031)
**Description** This adds a regression test in tests/e2e that ensures that stream=true requests are handled in a streaming manner. **Related Issues/PRs (if applicable)** Follow up on #1026 --------- Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent de415d4 commit ec2b79c

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

tests/e2e/testdata/testupstream.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,20 @@ spec:
4242
value: some-cool-model
4343
backendRefs:
4444
- name: translation-testupstream-cool-model-backend
45-
weight: 100
4645
- matches:
4746
- headers:
4847
- type: Exact
4948
name: x-ai-eg-model
5049
value: another-cool-model
5150
backendRefs:
5251
- name: translation-testupstream-another-cool-model-backend
53-
weight: 100
52+
- matches:
53+
- headers:
54+
- type: Exact
55+
name: x-ai-eg-model
56+
value: whatever-model
57+
backendRefs:
58+
- name: translation-testupstream-cool-model-backend
5459
---
5560
apiVersion: aigateway.envoyproxy.io/v1alpha1
5661
kind: AIServiceBackend

tests/e2e/testupstream_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"testing"
1515
"time"
1616

17+
openaigo "github.com/openai/openai-go"
18+
"github.com/openai/openai-go/option"
1719
"github.com/stretchr/testify/require"
1820

1921
"github.com/envoyproxy/ai-gateway/tests/internal/testupstreamlib"
@@ -163,4 +165,75 @@ func TestWithTestUpstream(t *testing.T) {
163165
return true
164166
}, 10*time.Second, 1*time.Second)
165167
})
168+
169+
// This is a regression test that ensures that stream=true requests are processed in a streaming manner.
170+
// https://github.com/envoyproxy/ai-gateway/pull/1026
171+
//
172+
// We have almost identical test in the tests/extproc.
173+
t.Run("stream non blocking", func(t *testing.T) {
174+
fwd := requireNewHTTPPortForwarder(t, egNamespace, egSelector, egDefaultServicePort)
175+
defer fwd.kill()
176+
// This receives a stream of 20 event messages. The testuptream server sleeps 200 ms between each message.
177+
// Therefore, if envoy fails to process the response in a streaming manner, the test will fail taking more than 4 seconds.
178+
client := openaigo.NewClient(
179+
option.WithBaseURL(fwd.address()+"/v1/"),
180+
option.WithHeader(testupstreamlib.ResponseTypeKey, "sse"),
181+
option.WithHeader(testupstreamlib.ResponseBodyHeaderKey,
182+
base64.StdEncoding.EncodeToString([]byte(
183+
`
184+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" This"},"logprobs":null,"finish_reason":null}],"usage":null}
185+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
186+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
187+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
188+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
189+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" This"},"logprobs":null,"finish_reason":null}],"usage":null}
190+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
191+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
192+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
193+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
194+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" This"},"logprobs":null,"finish_reason":null}],"usage":null}
195+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
196+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
197+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
198+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
199+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" This"},"logprobs":null,"finish_reason":null}],"usage":null}
200+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null}
201+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null}
202+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null}
203+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null}
204+
{"id":"chatcmpl-B8ZKlXBoEXZVTtv3YBmewxuCpNW7b","object":"chat.completion.chunk","created":1741382147,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_06737a9306","choices":[],"usage":{"prompt_tokens":25,"completion_tokens":61,"total_tokens":86,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
205+
[DONE]
206+
`,
207+
))),
208+
)
209+
210+
// NewStreaming below will block until the first event is received, so take the time before calling it.
211+
start := time.Now()
212+
stream := client.Chat.Completions.NewStreaming(t.Context(), openaigo.ChatCompletionNewParams{
213+
Messages: []openaigo.ChatCompletionMessageParamUnion{
214+
openaigo.UserMessage("Say this is a test"),
215+
},
216+
Model: "whatever-model",
217+
})
218+
219+
defer func() {
220+
_ = stream.Close()
221+
}()
222+
223+
asserted := false
224+
for stream.Next() {
225+
chunk := stream.Current()
226+
fmt.Println(chunk)
227+
if len(chunk.Choices) == 0 || chunk.Choices[0].Delta.Content == "" {
228+
continue
229+
}
230+
t.Logf("%v: %v", time.Now(), chunk.Choices[0].Delta.Content)
231+
// Check each event is received less than a second after the previous one.
232+
require.Less(t, time.Since(start), time.Second)
233+
start = time.Now()
234+
asserted = true
235+
}
236+
require.NoError(t, stream.Err())
237+
require.True(t, asserted)
238+
})
166239
}

0 commit comments

Comments
 (0)