Documentation
¶
Overview ¶
Package testutil holds fixtures shared by tests across this module: locally signed tokens, synthetic media providers, canned track layouts and FakeSFU, a loopback stand-in for the SFU signalling websocket.
It replaces the upstream videosdk/utils.go, which was a production file that imported testing and the SFU integration harness. Nothing here reaches off the loopback interface or needs a running SFU.
Index ¶
- Constants
- Variables
- func GetFakeAudioTrack(tInfo *sfu_models.TrackInfo) (*track.Local, error)
- func GetFakeSimulcastTracks(tInfo *sfu_models.TrackInfo, codecCapability webrtc.RTPCodecCapability) ([]webrtc.TrackLocal, error)
- func NextRPCRequest[T any](f *FakeSFU, timeout time.Duration) (T, error)
- func NextRequestOf[T any](f *FakeSFU, timeout time.Duration) (T, error)
- type FakeAudioProvider
- type FakeSFU
- func (f *FakeSFU) Close()
- func (f *FakeSFU) CloseConnection() error
- func (f *FakeSFU) NextRequest(timeout time.Duration) (*sfu_events.SfuRequest, error)
- func (f *FakeSFU) Send(event *sfu_events.SfuEvent, timeout time.Duration) error
- func (f *FakeSFU) URL() string
- func (f *FakeSFU) WsEndpoint() string
- type FakeSFUOption
- type FakeVideoProvider
- type SignalRPC
- type TokenDetails
Constants ¶
const DefaultCallType = "default"
DefaultCallType is the call type Stream creates by default.
Variables ¶
var RidToTestVideoLayer = map[string]*sfu_models.VideoLayer{ "q": { Rid: "q", VideoDimension: &sfu_models.VideoDimension{Width: 320, Height: 180}, Bitrate: 200, Fps: 30, Quality: sfu_models.VideoQuality_VIDEO_QUALITY_LOW_UNSPECIFIED, }, "h": { Rid: "h", VideoDimension: &sfu_models.VideoDimension{Width: 640, Height: 360}, Bitrate: 600, Fps: 30, Quality: sfu_models.VideoQuality_VIDEO_QUALITY_MID, }, "f": { Rid: "f", VideoDimension: &sfu_models.VideoDimension{Width: 1280, Height: 720}, Bitrate: 1200, Fps: 30, Quality: sfu_models.VideoQuality_VIDEO_QUALITY_HIGH, }, }
RidToTestVideoLayer maps the three simulcast rids to the layer definitions tests publish.
Functions ¶
func GetFakeAudioTrack ¶
func GetFakeAudioTrack(tInfo *sfu_models.TrackInfo) (*track.Local, error)
GetFakeAudioTrack builds an Opus track fed by silence.
func GetFakeSimulcastTracks ¶
func GetFakeSimulcastTracks(tInfo *sfu_models.TrackInfo, codecCapability webrtc.RTPCodecCapability) ([]webrtc.TrackLocal, error)
GetFakeSimulcastTracks builds one track per layer declared on tInfo.
func NextRPCRequest ¶
NextRPCRequest returns the next twirp signalling request of type T, skipping the other RPCs that arrive in between.
Types ¶
type FakeAudioProvider ¶
type FakeAudioProvider struct {
// contains filtered or unexported fields
}
FakeAudioProvider emits fixed-size 20 ms samples of silence.
func NewFakeAudioProvider ¶
func NewFakeAudioProvider(codecCapability webrtc.RTPCodecCapability) *FakeAudioProvider
func (*FakeAudioProvider) Close ¶
func (b *FakeAudioProvider) Close() error
func (*FakeAudioProvider) CurrentAudioLevel ¶
func (b *FakeAudioProvider) CurrentAudioLevel() uint8
func (*FakeAudioProvider) NextSample ¶
func (*FakeAudioProvider) OnBind ¶
func (b *FakeAudioProvider) OnBind() error
func (*FakeAudioProvider) OnUnbind ¶
func (b *FakeAudioProvider) OnUnbind() error
type FakeSFU ¶
type FakeSFU struct {
// Requests receives every SfuRequest the client sends over the websocket,
// in order. Read it with NextRequest or NextRequestOf.
Requests chan *sfu_events.SfuRequest
// RPCRequests receives every twirp signalling request the client sends, in
// order. Read it with NextRPCRequest.
RPCRequests chan any
// Authorizations receives the Authorization header of every twirp request,
// which is where the SFU token the client was handed has to end up.
Authorizations chan string
// Connects receives once per accepted websocket connection, so a test can
// tell a reconnect happened, and Closes once per connection that goes away
// again, so a test can tell the client dropped one.
Connects chan struct{}
Closes chan struct{}
// contains filtered or unexported fields
}
FakeSFU is the SFU signalling surface, reduced to what a client needs to complete a join and negotiate: the websocket that answers a JoinRequest with a JoinResponse and a HealthCheckRequest with a HealthCheckResponse, plus the twirp SignalServer RPCs. Everything the client sends is recorded for the test to assert on, and the fake can push arbitrary SfuEvents back.
The zero configuration is a cooperative SFU: joins succeed with an empty call state and every RPC answers with an empty successful response. Use the With... options to make it uncooperative.
func NewFakeSFU ¶
func NewFakeSFU(opts ...FakeSFUOption) *FakeSFU
NewFakeSFU starts a fake SFU. Close it when the test is done.
func (*FakeSFU) Close ¶
func (f *FakeSFU) Close()
Close shuts the server down and drops the client connection.
func (*FakeSFU) CloseConnection ¶
CloseConnection drops the current websocket connection without stopping the server, so the client sees its signal connection die and can re-dial.
func (*FakeSFU) NextRequest ¶
func (f *FakeSFU) NextRequest(timeout time.Duration) (*sfu_events.SfuRequest, error)
NextRequest returns the next request the client sent, or an error if none arrives within timeout.
func (*FakeSFU) Send ¶
Send pushes an event to the connected client, waiting up to timeout for a client to show up.
It writes to the most recent connection. After a reconnect, wait for that connection's JoinRequest before sending: the fake records a request only once the connection carrying it is installed.
func (*FakeSFU) WsEndpoint ¶
WsEndpoint is the ws:// URL a signal client dials.
type FakeSFUOption ¶
type FakeSFUOption func(*FakeSFU)
FakeSFUOption configures a FakeSFU. Options are applied before the server accepts anything, so the fake's behaviour is fixed by the time a client can observe it.
func WithJoinHandler ¶
func WithJoinHandler(handler func(*sfu_events.JoinRequest) *sfu_events.SfuEvent) FakeSFUOption
WithJoinHandler replaces the whole answer to a JoinRequest, so a test can answer with an SfuEvent_Error, answer conditionally on the request, or return nil to answer nothing at all and let the client's join time out.
func WithJoinResponse ¶
func WithJoinResponse(resp *sfu_events.JoinResponse) FakeSFUOption
WithJoinResponse sets the JoinResponse the fake answers a JoinRequest with.
func WithSignalRPC ¶
func WithSignalRPC(rpc SignalRPC) FakeSFUOption
WithSignalRPC overrides the twirp signalling RPC answers.
type FakeVideoProvider ¶
type FakeVideoProvider struct {
// contains filtered or unexported fields
}
FakeVideoProvider emits fixed-size samples at roughly 30 fps.
func NewFakeVideoProvider ¶
func NewFakeVideoProvider() *FakeVideoProvider
func (*FakeVideoProvider) Close ¶
func (b *FakeVideoProvider) Close() error
func (*FakeVideoProvider) NextSample ¶
func (*FakeVideoProvider) OnBind ¶
func (b *FakeVideoProvider) OnBind() error
func (*FakeVideoProvider) OnUnbind ¶
func (b *FakeVideoProvider) OnUnbind() error
type SignalRPC ¶
type SignalRPC struct {
SetPublisher func(context.Context, *sfu_signal_rpc.SetPublisherRequest) (*sfu_signal_rpc.SetPublisherResponse, error)
SendAnswer func(context.Context, *sfu_signal_rpc.SendAnswerRequest) (*sfu_signal_rpc.SendAnswerResponse, error)
IceTrickle func(context.Context, *sfu_models.ICETrickle) (*sfu_signal_rpc.ICETrickleResponse, error)
UpdateSubscriptions func(context.Context, *sfu_signal_rpc.UpdateSubscriptionsRequest) (*sfu_signal_rpc.UpdateSubscriptionsResponse, error)
UpdateMuteStates func(context.Context, *sfu_signal_rpc.UpdateMuteStatesRequest) (*sfu_signal_rpc.UpdateMuteStatesResponse, error)
IceRestart func(context.Context, *sfu_signal_rpc.ICERestartRequest) (*sfu_signal_rpc.ICERestartResponse, error)
SendStats func(context.Context, *sfu_signal_rpc.SendStatsRequest) (*sfu_signal_rpc.SendStatsResponse, error)
SendMetrics func(context.Context, *sfu_signal_rpc.SendMetricsRequest) (*sfu_signal_rpc.SendMetricsResponse, error)
StartNoiseCancellation func(context.Context, *sfu_signal_rpc.StartNoiseCancellationRequest) (*sfu_signal_rpc.StartNoiseCancellationResponse, error)
StopNoiseCancellation func(context.Context, *sfu_signal_rpc.StopNoiseCancellationRequest) (*sfu_signal_rpc.StopNoiseCancellationResponse, error)
}
SignalRPC answers the twirp signalling RPCs. A nil field answers with an empty successful response, which is what the SFU sends when it simply accepts a request.
type TokenDetails ¶
type TokenDetails struct {
UserID string `json:"userId"`
APIKey string `json:"apiKey"`
Token string `json:"token"`
}
TokenDetails is everything a client needs to authenticate as one user.
func GenerateToken ¶
func GenerateToken(apiKey, apiSecret, userID string, exp time.Duration) (*TokenDetails, error)
GenerateToken signs a Stream user token with the app secret. Unlike the upstream helper it replaces, it does not call out to the Stream demo token service, so tests stay hermetic.