package webrtc import ( "context" "testing" "time" "github.com/pion/webrtc/v4" ) // minimalOfferSDP returns an SDP offer that advertises H.264 (video) and // Opus (audio) as recvonly — the minimum a WHEP client sends. func minimalOfferSDP(t *testing.T) webrtc.SessionDescription { t.Helper() // Create a throwaway PC to generate a valid offer. me := &webrtc.MediaEngine{} if err := me.RegisterDefaultCodecs(); err != nil { t.Fatalf("RegisterDefaultCodecs: %v", err) } api := webrtc.NewAPI(webrtc.WithMediaEngine(me)) pc, err := api.NewPeerConnection(webrtc.Configuration{}) if err != nil { t.Fatalf("NewPeerConnection: %v", err) } defer pc.Close() if _, err := pc.AddTransceiverFromKind(webrtc.RTPCodecTypeVideo, webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionRecvonly}); err != nil { t.Fatalf("AddTransceiver video: %v", err) } if _, err := pc.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio, webrtc.RTPTransceiverInit{Direction: webrtc.RTPTransceiverDirectionRecvonly}); err != nil { t.Fatalf("AddTransceiver audio: %v", err) } offer, err := pc.CreateOffer(nil) if err != nil { t.Fatalf("CreateOffer: %v", err) } return offer } func TestPeerFactory_CreateAnswer(t *testing.T) { src, err := NewSource("streamA", 0) if err != nil { t.Fatalf("NewSource: %v", err) } defer src.Close() src.Start() cfg := DefaultConfig() factory, err := NewPeerFactory(cfg) if err != nil { t.Fatalf("NewPeerFactory: %v", err) } offer := minimalOfferSDP(t) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() peer, err := factory.CreatePeer(ctx, src, offer) if err != nil { t.Fatalf("CreatePeer: %v", err) } defer peer.Close() if peer.Answer().Type != webrtc.SDPTypeAnswer { t.Errorf("Answer().Type = %v, want answer", peer.Answer().Type) } if peer.ResourceID() == "" { t.Error("ResourceID should be non-empty") } } func TestPeerFactory_ClosesCleanly(t *testing.T) { src, _ := NewSource("streamA", 0) defer src.Close() src.Start() factory, _ := NewPeerFactory(DefaultConfig()) offer := minimalOfferSDP(t) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() peer, err := factory.CreatePeer(ctx, src, offer) if err != nil { t.Fatalf("CreatePeer: %v", err) } if err := peer.Close(); err != nil { t.Errorf("Close: %v", err) } // Second close should be a no-op, not panic. if err := peer.Close(); err != nil { t.Errorf("second Close: %v", err) } }