github.com/pion/webrtc/v3@v3.2.24/peerconnection_close_test.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 //go:build !js 5 // +build !js 6 7 package webrtc 8 9 import ( 10 "testing" 11 "time" 12 13 "github.com/pion/transport/v2/test" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func TestPeerConnection_Close(t *testing.T) { 18 // Limit runtime in case of deadlocks 19 lim := test.TimeOut(time.Second * 20) 20 defer lim.Stop() 21 22 report := test.CheckRoutines(t) 23 defer report() 24 25 pcOffer, pcAnswer, err := newPair() 26 if err != nil { 27 t.Fatal(err) 28 } 29 30 awaitSetup := make(chan struct{}) 31 pcAnswer.OnDataChannel(func(d *DataChannel) { 32 // Make sure this is the data channel we were looking for. (Not the one 33 // created in signalPair). 34 if d.Label() != "data" { 35 return 36 } 37 close(awaitSetup) 38 }) 39 40 awaitICEClosed := make(chan struct{}) 41 pcAnswer.OnICEConnectionStateChange(func(i ICEConnectionState) { 42 if i == ICEConnectionStateClosed { 43 close(awaitICEClosed) 44 } 45 }) 46 47 _, err = pcOffer.CreateDataChannel("data", nil) 48 if err != nil { 49 t.Fatal(err) 50 } 51 52 err = signalPair(pcOffer, pcAnswer) 53 if err != nil { 54 t.Fatal(err) 55 } 56 57 <-awaitSetup 58 59 closePairNow(t, pcOffer, pcAnswer) 60 61 <-awaitICEClosed 62 } 63 64 // Assert that a PeerConnection that is shutdown before ICE starts doesn't leak 65 func TestPeerConnection_Close_PreICE(t *testing.T) { 66 // Limit runtime in case of deadlocks 67 lim := test.TimeOut(time.Second * 30) 68 defer lim.Stop() 69 70 report := test.CheckRoutines(t) 71 defer report() 72 73 pcOffer, pcAnswer, err := newPair() 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 _, err = pcOffer.CreateDataChannel("test-channel", nil) 79 if err != nil { 80 t.Fatal(err) 81 } 82 83 answer, err := pcOffer.CreateOffer(nil) 84 if err != nil { 85 t.Fatal(err) 86 } 87 88 assert.NoError(t, pcOffer.Close()) 89 90 if err = pcAnswer.SetRemoteDescription(answer); err != nil { 91 t.Fatal(err) 92 } 93 94 for { 95 if pcAnswer.iceTransport.State() == ICETransportStateChecking { 96 break 97 } 98 time.Sleep(time.Second / 4) 99 } 100 101 assert.NoError(t, pcAnswer.Close()) 102 103 // Assert that ICETransport is shutdown, test timeout will prevent deadlock 104 for { 105 if pcAnswer.iceTransport.State() == ICETransportStateClosed { 106 return 107 } 108 time.Sleep(time.Second / 4) 109 } 110 } 111 112 func TestPeerConnection_Close_DuringICE(t *testing.T) { 113 // Limit runtime in case of deadlocks 114 lim := test.TimeOut(time.Second * 30) 115 defer lim.Stop() 116 117 report := test.CheckRoutines(t) 118 defer report() 119 120 pcOffer, pcAnswer, err := newPair() 121 if err != nil { 122 t.Fatal(err) 123 } 124 closedOffer := make(chan struct{}) 125 closedAnswer := make(chan struct{}) 126 pcAnswer.OnICEConnectionStateChange(func(iceState ICEConnectionState) { 127 if iceState == ICEConnectionStateConnected { 128 go func() { 129 assert.NoError(t, pcAnswer.Close()) 130 close(closedAnswer) 131 132 assert.NoError(t, pcOffer.Close()) 133 close(closedOffer) 134 }() 135 } 136 }) 137 138 _, err = pcOffer.CreateDataChannel("test-channel", nil) 139 if err != nil { 140 t.Fatal(err) 141 } 142 143 offer, err := pcOffer.CreateOffer(nil) 144 if err != nil { 145 t.Fatal(err) 146 } 147 148 offerGatheringComplete := GatheringCompletePromise(pcOffer) 149 if err = pcOffer.SetLocalDescription(offer); err != nil { 150 t.Fatal(err) 151 } 152 <-offerGatheringComplete 153 154 if err = pcAnswer.SetRemoteDescription(*pcOffer.LocalDescription()); err != nil { 155 t.Fatal(err) 156 } 157 158 answer, err := pcAnswer.CreateAnswer(nil) 159 if err != nil { 160 t.Fatal(err) 161 } 162 answerGatheringComplete := GatheringCompletePromise(pcAnswer) 163 if err = pcAnswer.SetLocalDescription(answer); err != nil { 164 t.Fatal(err) 165 } 166 <-answerGatheringComplete 167 if err = pcOffer.SetRemoteDescription(*pcAnswer.LocalDescription()); err != nil { 168 t.Fatal(err) 169 } 170 171 select { 172 case <-closedAnswer: 173 case <-time.After(5 * time.Second): 174 t.Error("pcAnswer.Close() Timeout") 175 } 176 select { 177 case <-closedOffer: 178 case <-time.After(5 * time.Second): 179 t.Error("pcOffer.Close() Timeout") 180 } 181 }