You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
3.2 KiB

package directstream
import (
"context"
"errors"
"testing"
)
type poolTicketEndpoint struct {
ticket string
claims TicketClaims
status TicketServiceSnapshot
consumeErr error
heartbeats int
events int
releases int
closes int
}
func (e *poolTicketEndpoint) ConsumeTicket(_ context.Context, ticket string, _ TicketBinding) (TicketClaims, error) {
if e.consumeErr != nil {
return TicketClaims{}, e.consumeErr
}
if ticket != e.ticket {
return TicketClaims{}, ErrInvalidTicket
}
return e.claims, nil
}
func (e *poolTicketEndpoint) ReleaseDirectWriter(context.Context, TicketBinding) error {
e.releases++
return nil
}
func (e *poolTicketEndpoint) HeartbeatDirectStream(context.Context, TicketBinding) error {
e.heartbeats++
return nil
}
func (e *poolTicketEndpoint) RecordDirectStreamEvent(context.Context, TicketBinding, SessionEvent) error {
e.events++
return nil
}
func (e *poolTicketEndpoint) CloseDirectStream(context.Context, TicketBinding) error {
e.closes++
return nil
}
func (e *poolTicketEndpoint) Status(context.Context) (TicketServiceSnapshot, error) {
return e.status, nil
}
func TestTicketSocketPoolRoutesLifecycleToConsumingAuthority(t *testing.T) {
base := &poolTicketEndpoint{ticket: "base", claims: TicketClaims{SessionID: "base-session", Channel: "CH01"}}
clone := &poolTicketEndpoint{ticket: "clone", claims: TicketClaims{SessionID: "clone-session", Channel: "CH18"}}
pool := newTicketSocketPool([]ticketEndpoint{base, clone})
binding := TicketBinding{SessionID: "clone-session", Channel: "CH18"}
claims, err := pool.ConsumeTicket(context.Background(), "clone", binding)
if err != nil || claims.SessionID != "clone-session" {
t.Fatalf("consume clone ticket = %#v, %v", claims, err)
}
if err := pool.RecordDirectStreamEvent(context.Background(), binding, SessionEvent{Type: SessionEventConnected}); err != nil {
t.Fatal(err)
}
if err := pool.HeartbeatDirectStream(context.Background(), binding); err != nil {
t.Fatal(err)
}
if err := pool.ReleaseDirectWriter(context.Background(), binding); err != nil {
t.Fatal(err)
}
if err := pool.CloseDirectStream(context.Background(), binding); err != nil {
t.Fatal(err)
}
if base.heartbeats != 0 || base.events != 0 || base.releases != 0 || base.closes != 0 {
t.Fatalf("base lifecycle was called: %#v", base)
}
if clone.heartbeats != 1 || clone.events != 1 || clone.releases != 1 || clone.closes != 1 {
t.Fatalf("clone lifecycle calls = %#v", clone)
}
if err := pool.HeartbeatDirectStream(context.Background(), binding); !errors.Is(err, ErrTicketBindingInactive) {
t.Fatalf("heartbeat after close error = %v", err)
}
}
func TestTicketSocketPoolAggregatesReachableAuthorities(t *testing.T) {
base := &poolTicketEndpoint{status: TicketServiceSnapshot{ActiveBindings: 1, MaxActiveBindings: 256, Consumed: 2}}
clone := &poolTicketEndpoint{status: TicketServiceSnapshot{ActiveBindings: 2, MaxActiveBindings: 128, Consumed: 3}}
pool := newTicketSocketPool([]ticketEndpoint{base, clone})
status, err := pool.Status(context.Background())
if err != nil {
t.Fatal(err)
}
if status.ActiveBindings != 3 || status.MaxActiveBindings != 384 || status.Consumed != 5 {
t.Fatalf("aggregate status = %#v", status)
}
}