Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ionorg/ion-sfu
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.41
Choose a base ref
...
head repository: ionorg/ion-sfu
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.42
Choose a head ref
  • 1 commit
  • 3 files changed
  • 1 contributor

Commits on Oct 30, 2020

  1. feat: more test (#276)

    tarrencev authored Oct 30, 2020
    Copy the full SHA
    6d98cb2 View commit details
Showing with 186 additions and 95 deletions.
  1. +1 −1 go.mod
  2. +2 −0 go.sum
  3. +183 −94 pkg/sfu_test.go
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ require (
github.com/pion/rtp v1.6.1
github.com/pion/sdp/v3 v3.0.2
github.com/pion/turn/v2 v2.0.5 // indirect
github.com/pion/webrtc/v3 v3.0.0-beta.10.0.20201027193323-3e64df35adfa
github.com/pion/webrtc/v3 v3.0.0-beta.10.0.20201030205602-60db5090fc93
github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.6.1
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -258,6 +258,8 @@ github.com/pion/udp v0.1.0 h1:uGxQsNyrqG3GLINv36Ff60covYmfrLoxzwnCsIYspXI=
github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths=
github.com/pion/webrtc/v3 v3.0.0-beta.10.0.20201027193323-3e64df35adfa h1:eyg97N6pAKZr48UFQoc58ldXFUUZ674shu9syBcJ7YI=
github.com/pion/webrtc/v3 v3.0.0-beta.10.0.20201027193323-3e64df35adfa/go.mod h1:GlriYYHJ5KkNsCunm3oFDPql4TDTrrNoI9iSWWSnafA=
github.com/pion/webrtc/v3 v3.0.0-beta.10.0.20201030205602-60db5090fc93 h1:h6kVKATdkUm7sFZQ//Q5t/2VKd7BZpO0Ozc9q94D4RI=
github.com/pion/webrtc/v3 v3.0.0-beta.10.0.20201030205602-60db5090fc93/go.mod h1:GlriYYHJ5KkNsCunm3oFDPql4TDTrrNoI9iSWWSnafA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
277 changes: 183 additions & 94 deletions pkg/sfu_test.go
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@ import (
"testing"
"time"

"github.com/lucsky/cuid"
log "github.com/pion/ion-log"
"github.com/pion/webrtc/v3"
"github.com/stretchr/testify/assert"
@@ -86,10 +85,11 @@ type media struct {
tid string
}

type remote struct {
id string
action string
media []media
type action struct {
id string
kind string
sleep time.Duration
media []media
}

type peer struct {
@@ -98,14 +98,15 @@ type peer struct {
local *Peer
remote *webrtc.PeerConnection
subs sync.WaitGroup
pubs []media
pubs []*webrtc.RTPSender
}

type step struct {
remotes []*remote
actions []*action
}

func addMedia(done <-chan struct{}, t *testing.T, pc *webrtc.PeerConnection, media []media) {
func addMedia(done <-chan struct{}, t *testing.T, pc *webrtc.PeerConnection, media []media) []*webrtc.RTPSender {
var senders []*webrtc.RTPSender
for _, media := range media {
var track *webrtc.Track
var err error
@@ -114,17 +115,20 @@ func addMedia(done <-chan struct{}, t *testing.T, pc *webrtc.PeerConnection, med
case "audio":
track, err = pc.NewTrack(webrtc.DefaultPayloadTypeOpus, rand.Uint32(), media.tid, media.id)
assert.NoError(t, err)
_, err = pc.AddTrack(track)
sender, err := pc.AddTrack(track)
assert.NoError(t, err)
senders = append(senders, sender)
case "video":
track, err = pc.NewTrack(webrtc.DefaultPayloadTypeVP8, rand.Uint32(), media.tid, media.id)
assert.NoError(t, err)
_, err = pc.AddTrack(track)
sender, err := pc.AddTrack(track)
assert.NoError(t, err)
senders = append(senders, sender)
}

go sendRTPUntilDone(done, t, track)
}
return senders
}

func TestSFU_SessionScenarios(t *testing.T) {
@@ -141,34 +145,116 @@ func TestSFU_SessionScenarios(t *testing.T) {
name: "Sequential join",
steps: []step{
{
remotes: []*remote{{
id: "remote1",
action: "join",
actions: []*action{{
id: "remote1",
kind: "join",
}},
},
{
actions: []*action{{
id: "remote1",
kind: "publish",
media: []media{
{kind: "audio", id: "stream1", tid: "audio"},
{kind: "video", id: "stream1", tid: "video"},
},
}},
},
{
actions: []*action{{
id: "remote2",
kind: "join",
}},
},
{
actions: []*action{{
id: "remote2",
kind: "publish",
media: []media{
{kind: "audio", id: "stream2", tid: "audio"},
{kind: "video", id: "stream2", tid: "video"},
},
}},
},
},
},
{
name: "Concurrent join + publish",
steps: []step{
{
actions: []*action{{
id: "remote1",
kind: "join",
}, {
id: "remote2",
kind: "join",
}, {
id: "remote3",
kind: "join",
}},
},
{
remotes: []*remote{{
id: "remote1",
action: "publish",
actions: []*action{{
id: "remote1",
kind: "publish",
media: []media{
{kind: "audio", id: "stream1", tid: "audio"},
{kind: "video", id: "stream1", tid: "video"},
},
}, {
id: "remote2",
kind: "publish",
media: []media{
{kind: "audio", id: "stream1", tid: cuid.New()},
{kind: "video", id: "stream1", tid: cuid.New()},
{kind: "audio", id: "stream2", tid: "audio"},
{kind: "video", id: "stream2", tid: "video"},
},
}, {
id: "remote3",
kind: "publish",
media: []media{
{kind: "audio", id: "stream3", tid: "audio"},
{kind: "video", id: "stream3", tid: "video"},
},
}},
},
},
},
{
name: "Multiple stream publish",
steps: []step{
{
actions: []*action{{
id: "remote1",
kind: "join",
}, {
id: "remote2",
kind: "join",
}},
},
{
remotes: []*remote{{
id: "remote2",
action: "join",
actions: []*action{{
id: "remote1",
kind: "publish",
media: []media{
{kind: "audio", id: "stream1", tid: "audio"},
{kind: "video", id: "stream1", tid: "video"},
},
}, {
id: "remote2",
kind: "publish",
media: []media{
{kind: "audio", id: "stream2", tid: "audio"},
{kind: "video", id: "stream2", tid: "video"},
},
}},
},
{
remotes: []*remote{{
id: "remote2",
action: "publish",
actions: []*action{{
id: "remote1",
kind: "publish",
media: []media{
{kind: "audio", id: "stream2", tid: cuid.New()},
{kind: "video", id: "stream2", tid: cuid.New()},
{kind: "audio", id: "stream3", tid: "audio"},
{kind: "video", id: "stream3", tid: "video"},
},
}},
},
@@ -183,95 +269,98 @@ func TestSFU_SessionScenarios(t *testing.T) {

peers := make(map[string]*peer)
for _, step := range tt.steps {
for _, remote := range step.remotes {
p := peers[remote.id]

switch remote.action {
case "join":
assert.Nil(t, p)

me := webrtc.MediaEngine{}
me.RegisterDefaultCodecs()
api := webrtc.NewAPI(webrtc.WithMediaEngine(me))
r, err := api.NewPeerConnection(webrtc.Configuration{})
r.OnTrack(func(*webrtc.Track, *webrtc.RTPReceiver) {
p.subs.Done()
})
assert.NoError(t, err)
_, err = r.CreateDataChannel("ion-sfu", nil)
assert.NoError(t, err)
local := NewPeer(sfu)
p = &peer{id: remote.id, remote: r, local: &local}

for id, existing := range peers {
if id != remote.id {
p.subs.Add(len(existing.pubs))
}
}
for _, action := range step.actions {
func() {
p := peers[action.id]

switch action.kind {
case "join":
assert.Nil(t, p)

me := webrtc.MediaEngine{}
me.RegisterDefaultCodecs()
api := webrtc.NewAPI(webrtc.WithMediaEngine(me))
r, err := api.NewPeerConnection(webrtc.Configuration{})
r.OnTrack(func(*webrtc.Track, *webrtc.RTPReceiver) {
p.subs.Done()
})
assert.NoError(t, err)
_, err = r.CreateDataChannel("ion-sfu", nil)
assert.NoError(t, err)
local := NewPeer(sfu)
p = &peer{id: action.id, remote: r, local: &local}

peers[remote.id] = p
for id, existing := range peers {
if id != action.id {
p.subs.Add(len(existing.pubs))
}
}

p.mu.Lock()
peers[action.id] = p

p.remote.OnNegotiationNeeded(func() {
p.mu.Lock()
defer p.mu.Unlock()
o, err := p.remote.CreateOffer(nil)
assert.NoError(t, err)
err = p.remote.SetLocalDescription(o)
assert.NoError(t, err)
a, err := p.local.Answer(o)
assert.NoError(t, err)
p.remote.SetRemoteDescription(*a)
})
p.remote.OnNegotiationNeeded(func() {
p.mu.Lock()
defer p.mu.Unlock()
o, err := p.remote.CreateOffer(nil)
assert.NoError(t, err)
err = p.remote.SetLocalDescription(o)
assert.NoError(t, err)
a, err := p.local.Answer(o)
assert.NoError(t, err)
log.Infof("%v", a)
p.remote.SetRemoteDescription(*a)
})

p.local.OnOffer = func(o *webrtc.SessionDescription) {
p.mu.Lock()
defer p.mu.Unlock()
err := p.remote.SetRemoteDescription(*o)
assert.NoError(t, err)
a, err := p.remote.CreateAnswer(nil)
assert.NoError(t, err)
err = p.remote.SetLocalDescription(a)
assert.NoError(t, err)
err = p.local.SetRemoteDescription(a)
assert.NoError(t, err)
}

p.local.OnOffer = func(o *webrtc.SessionDescription) {
p.mu.Lock()
defer p.mu.Unlock()
err := p.remote.SetRemoteDescription(*o)
offer, err := p.remote.CreateOffer(nil)
assert.NoError(t, err)
a, err := p.remote.CreateAnswer(nil)
gatherComplete := webrtc.GatheringCompletePromise(p.remote)
err = p.remote.SetLocalDescription(offer)
assert.NoError(t, err)
err = p.remote.SetLocalDescription(a)
<-gatherComplete
answer, err := p.local.Join("test", *p.remote.LocalDescription())
assert.NoError(t, err)
err = p.local.SetRemoteDescription(a)
assert.NoError(t, err)
}
p.remote.SetRemoteDescription(*answer)

p.mu.Unlock()

offer, err := p.remote.CreateOffer(nil)
assert.NoError(t, err)
gatherComplete := webrtc.GatheringCompletePromise(p.remote)
err = p.remote.SetLocalDescription(offer)
assert.NoError(t, err)
<-gatherComplete
answer, err := p.local.Join("test", *p.remote.LocalDescription())
assert.NoError(t, err)
p.remote.SetRemoteDescription(*answer)

p.mu.Unlock()

case "publish":
p.pubs = append(p.pubs, remote.media...)

// all other peers should get sub'd
for id, p := range peers {
if id != p.id {
p.subs.Add(len(remote.media))
case "publish":
// all other peers should get sub'd
for id, p := range peers {
if id != p.id {
p.subs.Add(len(action.media))
}
}
}

addMedia(done, t, p.remote, remote.media)
}
p.pubs = append(p.pubs, addMedia(done, t, p.remote, action.media)...)
}
}()
}
}

for _, p := range peers {
p.subs.Wait()
}
close(done)

for _, p := range peers {
p.mu.Lock()
p.remote.Close()
p.local.Close()
p.mu.Unlock()
}
})
}