mirror of
				https://github.com/pion/webrtc.git
				synced 2025-10-31 18:52:55 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			178 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +build !js
 | |
| 
 | |
| package webrtc
 | |
| 
 | |
| import (
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/pion/transport/test"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| )
 | |
| 
 | |
| func TestPeerConnection_Close(t *testing.T) {
 | |
| 	// Limit runtime in case of deadlocks
 | |
| 	lim := test.TimeOut(time.Second * 20)
 | |
| 	defer lim.Stop()
 | |
| 
 | |
| 	report := test.CheckRoutines(t)
 | |
| 	defer report()
 | |
| 
 | |
| 	pcOffer, pcAnswer, err := newPair()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	awaitSetup := make(chan struct{})
 | |
| 	pcAnswer.OnDataChannel(func(d *DataChannel) {
 | |
| 		// Make sure this is the data channel we were looking for. (Not the one
 | |
| 		// created in signalPair).
 | |
| 		if d.Label() != "data" {
 | |
| 			return
 | |
| 		}
 | |
| 		close(awaitSetup)
 | |
| 	})
 | |
| 
 | |
| 	awaitICEClosed := make(chan struct{})
 | |
| 	pcAnswer.OnICEConnectionStateChange(func(i ICEConnectionState) {
 | |
| 		if i == ICEConnectionStateClosed {
 | |
| 			close(awaitICEClosed)
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	_, err = pcOffer.CreateDataChannel("data", nil)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	err = signalPair(pcOffer, pcAnswer)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	<-awaitSetup
 | |
| 
 | |
| 	closePairNow(t, pcOffer, pcAnswer)
 | |
| 
 | |
| 	<-awaitICEClosed
 | |
| }
 | |
| 
 | |
| // Assert that a PeerConnection that is shutdown before ICE starts doesn't leak
 | |
| func TestPeerConnection_Close_PreICE(t *testing.T) {
 | |
| 	// Limit runtime in case of deadlocks
 | |
| 	lim := test.TimeOut(time.Second * 30)
 | |
| 	defer lim.Stop()
 | |
| 
 | |
| 	report := test.CheckRoutines(t)
 | |
| 	defer report()
 | |
| 
 | |
| 	pcOffer, pcAnswer, err := newPair()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	_, err = pcOffer.CreateDataChannel("test-channel", nil)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	answer, err := pcOffer.CreateOffer(nil)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	assert.NoError(t, pcOffer.Close())
 | |
| 
 | |
| 	if err = pcAnswer.SetRemoteDescription(answer); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	for {
 | |
| 		if pcAnswer.iceTransport.State() == ICETransportStateChecking {
 | |
| 			break
 | |
| 		}
 | |
| 		time.Sleep(time.Second / 4)
 | |
| 	}
 | |
| 
 | |
| 	assert.NoError(t, pcAnswer.Close())
 | |
| 
 | |
| 	// Assert that ICETransport is shutdown, test timeout will prevent deadlock
 | |
| 	for {
 | |
| 		if pcAnswer.iceTransport.State() == ICETransportStateClosed {
 | |
| 			return
 | |
| 		}
 | |
| 		time.Sleep(time.Second / 4)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPeerConnection_Close_DuringICE(t *testing.T) {
 | |
| 	// Limit runtime in case of deadlocks
 | |
| 	lim := test.TimeOut(time.Second * 30)
 | |
| 	defer lim.Stop()
 | |
| 
 | |
| 	report := test.CheckRoutines(t)
 | |
| 	defer report()
 | |
| 
 | |
| 	pcOffer, pcAnswer, err := newPair()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	closedOffer := make(chan struct{})
 | |
| 	closedAnswer := make(chan struct{})
 | |
| 	pcAnswer.OnICEConnectionStateChange(func(iceState ICEConnectionState) {
 | |
| 		if iceState == ICEConnectionStateConnected {
 | |
| 			go func() {
 | |
| 				assert.NoError(t, pcAnswer.Close())
 | |
| 				close(closedAnswer)
 | |
| 
 | |
| 				assert.NoError(t, pcOffer.Close())
 | |
| 				close(closedOffer)
 | |
| 			}()
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	_, err = pcOffer.CreateDataChannel("test-channel", nil)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	offer, err := pcOffer.CreateOffer(nil)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	offerGatheringComplete := GatheringCompletePromise(pcOffer)
 | |
| 	if err = pcOffer.SetLocalDescription(offer); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	<-offerGatheringComplete
 | |
| 
 | |
| 	if err = pcAnswer.SetRemoteDescription(*pcOffer.LocalDescription()); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	answer, err := pcAnswer.CreateAnswer(nil)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	answerGatheringComplete := GatheringCompletePromise(pcAnswer)
 | |
| 	if err = pcAnswer.SetLocalDescription(answer); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	<-answerGatheringComplete
 | |
| 	if err = pcOffer.SetRemoteDescription(*pcAnswer.LocalDescription()); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	select {
 | |
| 	case <-closedAnswer:
 | |
| 	case <-time.After(5 * time.Second):
 | |
| 		t.Error("pcAnswer.Close() Timeout")
 | |
| 	}
 | |
| 	select {
 | |
| 	case <-closedOffer:
 | |
| 	case <-time.After(5 * time.Second):
 | |
| 		t.Error("pcOffer.Close() Timeout")
 | |
| 	}
 | |
| }
 | 
