Files

86 lines
3.5 KiB
Go

package callruntime
import (
"context"
"errors"
"strings"
"testing"
"time"
"github.com/CyCoreSystems/ari/v5"
)
type eventSubscription struct{ events chan ari.Event }
func (s eventSubscription) Events() <-chan ari.Event { return s.events }
func (s eventSubscription) Cancel() {}
func events(values ...ari.Event) eventSubscription {
s := eventSubscription{make(chan ari.Event, len(values))}
for _, event := range values {
s.events <- event
}
close(s.events)
return s
}
func TestWaitForAnswerUsesOnlyTargetChannel(t *testing.T) {
for _, tc := range []struct {
name string
event ari.Event
wantError string
}{
{name: "stasis", event: &ari.StasisStart{EventData: ari.EventData{Type: "StasisStart"}, Channel: ari.ChannelData{ID: "call"}}},
{name: "up", event: &ari.ChannelStateChange{EventData: ari.EventData{Type: "ChannelStateChange"}, Channel: ari.ChannelData{ID: "call", State: "Up"}}},
{name: "hangup", event: &ari.ChannelHangupRequest{EventData: ari.EventData{Type: "ChannelHangupRequest"}, Channel: ari.ChannelData{ID: "call", State: "Down"}, Cause: 17}, wantError: "cause=17"},
{name: "destroyed", event: &ari.ChannelDestroyed{EventData: ari.EventData{Type: "ChannelDestroyed"}, Channel: ari.ChannelData{ID: "call"}}, wantError: "ended before StasisStart"},
} {
t.Run(tc.name, func(t *testing.T) {
other := &ari.StasisStart{EventData: ari.EventData{Type: "StasisStart"}, Channel: ari.ChannelData{ID: "another-call"}}
err := waitForStasisStart(context.Background(), events(nil, other, tc.event), "call", time.Second)
if tc.wantError == "" && err != nil {
t.Fatal(err)
}
if tc.wantError != "" && (err == nil || !strings.Contains(err.Error(), tc.wantError)) {
t.Fatalf("unexpected answer result: %v", err)
}
})
}
if err := waitForStasisStart(context.Background(), events(), "call", time.Second); err == nil || !strings.Contains(err.Error(), "subscription closed") {
t.Fatal("closed subscription accepted")
}
ctx, cancel := context.WithCancel(context.Background())
cancel()
if err := waitForStasisStart(ctx, eventSubscription{make(chan ari.Event)}, "call", time.Second); !errors.Is(err, context.Canceled) {
t.Fatalf("cancellation lost: %v", err)
}
}
func TestLifecycleCancellationIsScopedToChannel(t *testing.T) {
for _, kind := range []string{"ChannelHangupRequest", "ChannelDestroyed"} {
t.Run(kind, func(t *testing.T) {
var event ari.Event
if kind == "ChannelDestroyed" {
event = &ari.ChannelDestroyed{EventData: ari.EventData{Type: kind}, Channel: ari.ChannelData{ID: "call"}}
} else {
event = &ari.ChannelHangupRequest{EventData: ari.EventData{Type: kind}, Channel: ari.ChannelData{ID: "call"}}
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
other := &ari.ChannelDestroyed{EventData: ari.EventData{Type: "ChannelDestroyed"}, Channel: ari.ChannelData{ID: "other"}}
watchChannelLifecycle(ctx, events(other, event), "call", cancel)
if !errors.Is(ctx.Err(), context.Canceled) {
t.Fatal("matching hangup failed to cancel")
}
})
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
watchChannelLifecycle(ctx, events(&ari.ChannelDestroyed{EventData: ari.EventData{Type: "ChannelDestroyed"}, Channel: ari.ChannelData{ID: "other"}}), "call", cancel)
if ctx.Err() != nil {
t.Fatal("another call ended this call")
}
watchChannelLifecycle(ctx, events(nil), "call", cancel)
cancel()
watchChannelLifecycle(ctx, eventSubscription{make(chan ari.Event)}, "call", cancel)
}