76 lines
2.2 KiB
Go
76 lines
2.2 KiB
Go
package asterisk
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/CyCoreSystems/ari/v5"
|
|
)
|
|
|
|
type delayedTeardownChannel struct {
|
|
ari.Channel
|
|
reads, hangups int
|
|
}
|
|
|
|
func (c *delayedTeardownChannel) Hangup(key *ari.Key, _ string) error {
|
|
if key.ID != "owned-call" {
|
|
return errors.New("wrong channel")
|
|
}
|
|
c.hangups++
|
|
return nil
|
|
}
|
|
func (c *delayedTeardownChannel) Data(key *ari.Key) (*ari.ChannelData, error) {
|
|
if key.ID != "owned-call" {
|
|
return nil, errors.New("wrong channel")
|
|
}
|
|
c.reads++
|
|
if c.reads < 3 {
|
|
return &ari.ChannelData{ID: key.ID}, nil
|
|
}
|
|
return nil, nativeHTTPStatusError{code: 404}
|
|
}
|
|
|
|
func TestNativeCloseWaitsForExactChannelAsynchronousTeardown(t *testing.T) {
|
|
channel := &delayedTeardownChannel{}
|
|
call := &NativeCall{verifyEnd: true, outbound: ari.NewChannelHandle(ari.NewKey(ari.ChannelKey, "owned-call"), channel, nil)}
|
|
if err := call.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !call.EndConfirmed() || channel.reads != 3 || channel.hangups != 1 {
|
|
t.Fatalf("only the exact channel 404 confirms end; reads=%d hangups=%d confirmed=%v", channel.reads, channel.hangups, call.EndConfirmed())
|
|
}
|
|
if err := call.Close(); err != nil || channel.hangups != 1 {
|
|
t.Fatal("Close must never repeat Hangup")
|
|
}
|
|
}
|
|
|
|
func TestNativeEndReadbackKeepsUncertaintyVisible(t *testing.T) {
|
|
for _, scenario := range []string{"still-present", "HTTP-error", "transport-error"} {
|
|
t.Run(scenario, func(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
|
|
defer cancel()
|
|
reads, err := awaitNativeChannelEnd(ctx, func() error {
|
|
switch scenario {
|
|
case "HTTP-error":
|
|
return nativeHTTPStatusError{code: 503}
|
|
case "transport-error":
|
|
return errors.New("read unavailable")
|
|
}
|
|
return nil
|
|
})
|
|
if err == nil || reads < 1 {
|
|
t.Fatalf("missing terminal evidence must fail explicitly: reads=%d error=%v", reads, err)
|
|
}
|
|
if scenario == "still-present" && (!errors.Is(err, context.DeadlineExceeded) || !strings.Contains(err.Error(), "channel still present")) {
|
|
t.Fatalf("deadline must retain pending-channel evidence: %v", err)
|
|
}
|
|
if scenario != "still-present" && reads != 1 {
|
|
t.Fatal("failed read is not silently retried")
|
|
}
|
|
})
|
|
}
|
|
}
|