Files
wehub-resource-sync f36e2104d8
tests / ragflow_tests_infinity (push) Has been cancelled
tests / ragflow_tests_elasticsearch (push) Has been cancelled
sep-tests / ragflow_preflight (push) Has been cancelled
sep-tests / ragflow_tests_infinity (push) Has been cancelled
sep-tests / ragflow_tests_elasticsearch (push) Has been cancelled
tests / ragflow_preflight (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:16:49 +08:00

143 lines
4.1 KiB
Go

//
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package canvas
import (
"encoding/json"
"strings"
"testing"
"time"
)
func TestChannelEmitter_EmitAndClose(t *testing.T) {
em := NewChannelEmitter(4)
ch := em.(*channelEmitter).Channel()
evs := []StreamEvent{
{Event: "node_start", TaskID: "t1", Component: "begin_0"},
{Event: "message", TaskID: "t1", Component: "llm_0",
Data: map[string]any{"delta": "hello"}},
{Event: "node_finish", TaskID: "t1", Component: "begin_0",
Data: map[string]any{"ok": true}},
}
for _, ev := range evs {
if err := em.Emit(ev); err != nil {
t.Fatalf("Emit %q: %v", ev.Event, err)
}
}
if err := em.Close(); err != nil {
t.Fatalf("Close: %v", err)
}
var got []StreamEvent
for ev := range ch {
got = append(got, ev)
}
if len(got) != len(evs) {
t.Fatalf("got %d events, want %d", len(got), len(evs))
}
for i, ev := range got {
if ev.Event != evs[i].Event || ev.TaskID != evs[i].TaskID ||
ev.Component != evs[i].Component {
t.Fatalf("event %d: got %+v, want %+v", i, ev, evs[i])
}
}
}
func TestChannelEmitter_NonBlockingDrop(t *testing.T) {
// Buffer of 1 with no reader; the second Emit must return nil
// immediately (drop on full) rather than block.
em := NewChannelEmitter(1)
if err := em.Emit(StreamEvent{Event: "e1", TaskID: "t"}); err != nil {
t.Fatalf("Emit 1: %v", err)
}
done := make(chan struct{})
go func() {
if err := em.Emit(StreamEvent{Event: "e2", TaskID: "t"}); err != nil {
t.Errorf("Emit 2: %v", err)
}
close(done)
}()
select {
case <-done:
case <-time.After(200 * time.Millisecond):
t.Fatal("Emit blocked despite non-blocking contract")
}
// The first event is still buffered; the second was dropped.
ch := em.(*channelEmitter).Channel()
first := <-ch
if first.Event != "e1" {
t.Fatalf("first buffered event = %q, want e1", first.Event)
}
}
func TestFormatSSE(t *testing.T) {
ev := StreamEvent{
Event: "message",
TaskID: "task_42",
Component: "llm_0",
Data: map[string]any{
"delta": "héllo, 世界",
"index": 7,
},
}
got := FormatSSE(ev)
if !strings.HasPrefix(got, "data: ") {
t.Fatalf("SSE frame must start with 'data: '; got %q", got)
}
if !strings.HasSuffix(got, "\n\n") {
t.Fatalf("SSE frame must end with '\\n\\n'; got %q", got)
}
body := strings.TrimPrefix(got, "data: ")
body = strings.TrimSuffix(body, "\n\n")
// Body must be valid JSON and round-trip the Data field.
var decoded map[string]any
if err := json.Unmarshal([]byte(body), &decoded); err != nil {
t.Fatalf("SSE body is not JSON: %v\nbody: %q", err, body)
}
if decoded["delta"] != "héllo, 世界" {
t.Fatalf("delta round-trip: got %q, want %q", decoded["delta"], "héllo, 世界")
}
if v, _ := decoded["index"].(float64); v != 7 {
t.Fatalf("index round-trip: got %v, want 7", decoded["index"])
}
}
func TestFormatSSE_EmptyData(t *testing.T) {
// Empty Data must still produce a valid frame, not panic.
got := FormatSSE(StreamEvent{Event: "node_start", TaskID: "t"})
if !strings.HasPrefix(got, "data: ") || !strings.HasSuffix(got, "\n\n") {
t.Fatalf("empty Data frame malformed: %q", got)
}
}
func TestChannelEmitter_CloseIdempotentCheck(t *testing.T) {
// Emitting after Close must panic — callers should not emit on a
// closed emitter. This is the desired Go-idiomatic signal.
em := NewChannelEmitter(1)
ch := em.(*channelEmitter).Channel()
if err := em.Close(); err != nil {
t.Fatalf("Close: %v", err)
}
// Drain to confirm the channel is closed.
if _, ok := <-ch; ok {
t.Fatal("channel not closed after Close()")
}
}