135 lines
3.8 KiB
Go
135 lines
3.8 KiB
Go
/*
|
|
* Copyright 2026 CloudWeGo Authors
|
|
*
|
|
* 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 tool
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/cloudwego/eino/internal/core"
|
|
)
|
|
|
|
func TestInterrupt(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("basic interrupt", func(t *testing.T) {
|
|
err := Interrupt(ctx, "test info")
|
|
assert.Error(t, err)
|
|
|
|
var signal *core.InterruptSignal
|
|
assert.True(t, errors.As(err, &signal))
|
|
assert.Equal(t, "test info", signal.Info)
|
|
assert.True(t, signal.IsRootCause)
|
|
})
|
|
}
|
|
|
|
func TestStatefulInterrupt(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("stateful interrupt", func(t *testing.T) {
|
|
type myState struct {
|
|
Value int
|
|
}
|
|
state := &myState{Value: 42}
|
|
|
|
err := StatefulInterrupt(ctx, "test info", state)
|
|
assert.Error(t, err)
|
|
|
|
var signal *core.InterruptSignal
|
|
assert.True(t, errors.As(err, &signal))
|
|
assert.Equal(t, "test info", signal.Info)
|
|
assert.Equal(t, state, signal.State)
|
|
assert.True(t, signal.IsRootCause)
|
|
})
|
|
}
|
|
|
|
func TestCompositeInterrupt(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("no sub errors falls back to StatefulInterrupt", func(t *testing.T) {
|
|
err := CompositeInterrupt(ctx, "composite info", "my state")
|
|
assert.Error(t, err)
|
|
|
|
var signal *core.InterruptSignal
|
|
assert.True(t, errors.As(err, &signal))
|
|
assert.Equal(t, "composite info", signal.Info)
|
|
assert.Equal(t, "my state", signal.State)
|
|
assert.True(t, signal.IsRootCause)
|
|
assert.Empty(t, signal.Subs)
|
|
})
|
|
|
|
t.Run("with InterruptSignal sub error", func(t *testing.T) {
|
|
subSignal, _ := core.Interrupt(ctx, "sub info", "sub state", nil)
|
|
|
|
err := CompositeInterrupt(ctx, "composite info", "my state", subSignal)
|
|
assert.Error(t, err)
|
|
|
|
var signal *core.InterruptSignal
|
|
assert.True(t, errors.As(err, &signal))
|
|
assert.Equal(t, "composite info", signal.Info)
|
|
assert.Equal(t, "my state", signal.State)
|
|
assert.Len(t, signal.Subs, 1)
|
|
assert.Equal(t, "sub info", signal.Subs[0].Info)
|
|
})
|
|
|
|
t.Run("with non-interrupt error returns error", func(t *testing.T) {
|
|
nonInterruptErr := errors.New("regular error")
|
|
|
|
err := CompositeInterrupt(ctx, "composite info", "my state", nonInterruptErr)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "composite interrupt but one of the sub error is not interrupt error")
|
|
|
|
var signal *core.InterruptSignal
|
|
assert.False(t, errors.As(err, &signal))
|
|
})
|
|
|
|
t.Run("with multiple sub errors", func(t *testing.T) {
|
|
subSignal1, _ := core.Interrupt(ctx, "sub1 info", nil, nil)
|
|
subSignal2, _ := core.Interrupt(ctx, "sub2 info", nil, nil)
|
|
|
|
err := CompositeInterrupt(ctx, "composite info", nil, subSignal1, subSignal2)
|
|
assert.Error(t, err)
|
|
|
|
var signal *core.InterruptSignal
|
|
assert.True(t, errors.As(err, &signal))
|
|
assert.Len(t, signal.Subs, 2)
|
|
})
|
|
}
|
|
|
|
func TestGetInterruptState(t *testing.T) {
|
|
t.Run("not interrupted returns false", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
wasInterrupted, hasState, state := GetInterruptState[string](ctx)
|
|
assert.False(t, wasInterrupted)
|
|
assert.False(t, hasState)
|
|
assert.Empty(t, state)
|
|
})
|
|
}
|
|
|
|
func TestGetResumeContext(t *testing.T) {
|
|
t.Run("not resume target returns false", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
isResumeTarget, hasData, data := GetResumeContext[string](ctx)
|
|
assert.False(t, isResumeTarget)
|
|
assert.False(t, hasData)
|
|
assert.Empty(t, data)
|
|
})
|
|
}
|