mirror of
https://github.com/pion/webrtc.git
synced 2025-09-27 03:25:58 +08:00

This change adapts pion/ice to use a new interface for most network related operations. The interface was formerly a simple struct vnet.Net which was originally intended to facilicate testing. By replacing it with an interface we have greater flexibility and allow users to hook into the networking stack by providing their own implementation of the interface.
252 lines
7.0 KiB
Go
252 lines
7.0 KiB
Go
//go:build !js
|
|
// +build !js
|
|
|
|
package webrtc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/pion/rtp"
|
|
"github.com/pion/transport/v2/test"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// If a remote doesn't support a Codec used by a `TrackLocalStatic`
|
|
// an error should be returned to the user
|
|
func Test_TrackLocalStatic_NoCodecIntersection(t *testing.T) {
|
|
lim := test.TimeOut(time.Second * 30)
|
|
defer lim.Stop()
|
|
|
|
report := test.CheckRoutines(t)
|
|
defer report()
|
|
|
|
track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
|
|
assert.NoError(t, err)
|
|
|
|
t.Run("Offerer", func(t *testing.T) {
|
|
pc, err := NewPeerConnection(Configuration{})
|
|
assert.NoError(t, err)
|
|
|
|
noCodecPC, err := NewAPI().NewPeerConnection(Configuration{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pc.AddTrack(track)
|
|
assert.NoError(t, err)
|
|
|
|
assert.ErrorIs(t, signalPair(pc, noCodecPC), ErrUnsupportedCodec)
|
|
|
|
closePairNow(t, noCodecPC, pc)
|
|
})
|
|
|
|
t.Run("Answerer", func(t *testing.T) {
|
|
pc, err := NewPeerConnection(Configuration{})
|
|
assert.NoError(t, err)
|
|
|
|
m := &MediaEngine{}
|
|
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
|
|
RTPCodecCapability: RTPCodecCapability{MimeType: "video/VP9", ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
|
|
PayloadType: 96,
|
|
}, RTPCodecTypeVideo))
|
|
|
|
vp9OnlyPC, err := NewAPI(WithMediaEngine(m)).NewPeerConnection(Configuration{})
|
|
assert.NoError(t, err)
|
|
|
|
_, err = vp9OnlyPC.AddTransceiverFromKind(RTPCodecTypeVideo)
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pc.AddTrack(track)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, errors.Is(signalPair(vp9OnlyPC, pc), ErrUnsupportedCodec))
|
|
|
|
closePairNow(t, vp9OnlyPC, pc)
|
|
})
|
|
|
|
t.Run("Local", func(t *testing.T) {
|
|
offerer, answerer, err := newPair()
|
|
assert.NoError(t, err)
|
|
|
|
invalidCodecTrack, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: "video/invalid-codec"}, "video", "pion")
|
|
assert.NoError(t, err)
|
|
|
|
_, err = offerer.AddTrack(invalidCodecTrack)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, errors.Is(signalPair(offerer, answerer), ErrUnsupportedCodec))
|
|
closePairNow(t, offerer, answerer)
|
|
})
|
|
}
|
|
|
|
// Assert that Bind/Unbind happens when expected
|
|
func Test_TrackLocalStatic_Closed(t *testing.T) {
|
|
lim := test.TimeOut(time.Second * 30)
|
|
defer lim.Stop()
|
|
|
|
report := test.CheckRoutines(t)
|
|
defer report()
|
|
|
|
pcOffer, pcAnswer, err := newPair()
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pcAnswer.AddTransceiverFromKind(RTPCodecTypeVideo)
|
|
assert.NoError(t, err)
|
|
|
|
vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pcOffer.AddTrack(vp8Writer)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(vp8Writer.bindings), 0, "No binding should exist before signaling")
|
|
|
|
assert.NoError(t, signalPair(pcOffer, pcAnswer))
|
|
|
|
assert.Equal(t, len(vp8Writer.bindings), 1, "binding should exist after signaling")
|
|
|
|
closePairNow(t, pcOffer, pcAnswer)
|
|
|
|
assert.Equal(t, len(vp8Writer.bindings), 0, "No binding should exist after close")
|
|
}
|
|
|
|
func Test_TrackLocalStatic_PayloadType(t *testing.T) {
|
|
lim := test.TimeOut(time.Second * 30)
|
|
defer lim.Stop()
|
|
|
|
report := test.CheckRoutines(t)
|
|
defer report()
|
|
|
|
mediaEngineOne := &MediaEngine{}
|
|
assert.NoError(t, mediaEngineOne.RegisterCodec(RTPCodecParameters{
|
|
RTPCodecCapability: RTPCodecCapability{MimeType: "video/VP8", ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
|
|
PayloadType: 100,
|
|
}, RTPCodecTypeVideo))
|
|
|
|
mediaEngineTwo := &MediaEngine{}
|
|
assert.NoError(t, mediaEngineTwo.RegisterCodec(RTPCodecParameters{
|
|
RTPCodecCapability: RTPCodecCapability{MimeType: "video/VP8", ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
|
|
PayloadType: 200,
|
|
}, RTPCodecTypeVideo))
|
|
|
|
offerer, err := NewAPI(WithMediaEngine(mediaEngineOne)).NewPeerConnection(Configuration{})
|
|
assert.NoError(t, err)
|
|
|
|
answerer, err := NewAPI(WithMediaEngine(mediaEngineTwo)).NewPeerConnection(Configuration{})
|
|
assert.NoError(t, err)
|
|
|
|
track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
|
|
assert.NoError(t, err)
|
|
|
|
_, err = offerer.AddTransceiverFromKind(RTPCodecTypeVideo)
|
|
assert.NoError(t, err)
|
|
|
|
_, err = answerer.AddTrack(track)
|
|
assert.NoError(t, err)
|
|
|
|
onTrackFired, onTrackFiredFunc := context.WithCancel(context.Background())
|
|
offerer.OnTrack(func(track *TrackRemote, r *RTPReceiver) {
|
|
assert.Equal(t, track.PayloadType(), PayloadType(100))
|
|
assert.Equal(t, track.Codec().RTPCodecCapability.MimeType, "video/VP8")
|
|
|
|
onTrackFiredFunc()
|
|
})
|
|
|
|
assert.NoError(t, signalPair(offerer, answerer))
|
|
|
|
sendVideoUntilDone(onTrackFired.Done(), t, []*TrackLocalStaticSample{track})
|
|
|
|
closePairNow(t, offerer, answerer)
|
|
}
|
|
|
|
// Assert that writing to a Track doesn't modify the input
|
|
// Even though we can pass a pointer we shouldn't modify the incoming value
|
|
func Test_TrackLocalStatic_Mutate_Input(t *testing.T) {
|
|
lim := test.TimeOut(time.Second * 30)
|
|
defer lim.Stop()
|
|
|
|
report := test.CheckRoutines(t)
|
|
defer report()
|
|
|
|
pcOffer, pcAnswer, err := newPair()
|
|
assert.NoError(t, err)
|
|
|
|
vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pcOffer.AddTrack(vp8Writer)
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, signalPair(pcOffer, pcAnswer))
|
|
|
|
pkt := &rtp.Packet{Header: rtp.Header{SSRC: 1, PayloadType: 1}}
|
|
assert.NoError(t, vp8Writer.WriteRTP(pkt))
|
|
|
|
assert.Equal(t, pkt.Header.SSRC, uint32(1))
|
|
assert.Equal(t, pkt.Header.PayloadType, uint8(1))
|
|
|
|
closePairNow(t, pcOffer, pcAnswer)
|
|
}
|
|
|
|
// Assert that writing to a Track that has Binded (but not connected)
|
|
// does not block
|
|
func Test_TrackLocalStatic_Binding_NonBlocking(t *testing.T) {
|
|
lim := test.TimeOut(time.Second * 5)
|
|
defer lim.Stop()
|
|
|
|
report := test.CheckRoutines(t)
|
|
defer report()
|
|
|
|
pcOffer, pcAnswer, err := newPair()
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pcOffer.AddTransceiverFromKind(RTPCodecTypeVideo)
|
|
assert.NoError(t, err)
|
|
|
|
vp8Writer, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
|
|
assert.NoError(t, err)
|
|
|
|
_, err = pcAnswer.AddTrack(vp8Writer)
|
|
assert.NoError(t, err)
|
|
|
|
offer, err := pcOffer.CreateOffer(nil)
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, pcAnswer.SetRemoteDescription(offer))
|
|
|
|
answer, err := pcAnswer.CreateAnswer(nil)
|
|
assert.NoError(t, err)
|
|
assert.NoError(t, pcAnswer.SetLocalDescription(answer))
|
|
|
|
_, err = vp8Writer.Write(make([]byte, 20))
|
|
assert.NoError(t, err)
|
|
|
|
closePairNow(t, pcOffer, pcAnswer)
|
|
}
|
|
|
|
func BenchmarkTrackLocalWrite(b *testing.B) {
|
|
offerPC, answerPC, err := newPair()
|
|
defer closePairNow(b, offerPC, answerPC)
|
|
if err != nil {
|
|
b.Fatalf("Failed to create a PC pair for testing")
|
|
}
|
|
|
|
track, err := NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
|
|
assert.NoError(b, err)
|
|
|
|
_, err = offerPC.AddTrack(track)
|
|
assert.NoError(b, err)
|
|
|
|
_, err = answerPC.AddTransceiverFromKind(RTPCodecTypeVideo)
|
|
assert.NoError(b, err)
|
|
|
|
b.SetBytes(1024)
|
|
|
|
buf := make([]byte, 1024)
|
|
for i := 0; i < b.N; i++ {
|
|
_, err := track.Write(buf)
|
|
assert.NoError(b, err)
|
|
}
|
|
}
|