Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #include <iostream> |
michael@0 | 6 | #include <map> |
michael@0 | 7 | #include <algorithm> |
michael@0 | 8 | #include <string> |
michael@0 | 9 | #include <unistd.h> |
michael@0 | 10 | |
michael@0 | 11 | #include "base/basictypes.h" |
michael@0 | 12 | #include "logging.h" |
michael@0 | 13 | |
michael@0 | 14 | #define GTEST_HAS_RTTI 0 |
michael@0 | 15 | #include "gtest/gtest.h" |
michael@0 | 16 | #include "gtest_utils.h" |
michael@0 | 17 | |
michael@0 | 18 | #include "nspr.h" |
michael@0 | 19 | #include "nss.h" |
michael@0 | 20 | #include "ssl.h" |
michael@0 | 21 | #include "prthread.h" |
michael@0 | 22 | |
michael@0 | 23 | #include "cpr_stdlib.h" |
michael@0 | 24 | #include "FakePCObserver.h" |
michael@0 | 25 | #include "FakeMediaStreams.h" |
michael@0 | 26 | #include "FakeMediaStreamsImpl.h" |
michael@0 | 27 | #include "PeerConnectionImpl.h" |
michael@0 | 28 | #include "PeerConnectionCtx.h" |
michael@0 | 29 | #include "PeerConnectionMedia.h" |
michael@0 | 30 | #include "MediaPipeline.h" |
michael@0 | 31 | #include "runnable_utils.h" |
michael@0 | 32 | #include "nsServiceManagerUtils.h" |
michael@0 | 33 | #include "mozilla/Services.h" |
michael@0 | 34 | #include "nsIPrefService.h" |
michael@0 | 35 | #include "nsIPrefBranch.h" |
michael@0 | 36 | #include "nsNetUtil.h" |
michael@0 | 37 | #include "nsIIOService.h" |
michael@0 | 38 | #include "nsIDNSService.h" |
michael@0 | 39 | #include "nsWeakReference.h" |
michael@0 | 40 | #include "nricectx.h" |
michael@0 | 41 | #include "rlogringbuffer.h" |
michael@0 | 42 | #include "mozilla/SyncRunnable.h" |
michael@0 | 43 | #include "logging.h" |
michael@0 | 44 | #include "stunserver.h" |
michael@0 | 45 | #include "stunserver.cpp" |
michael@0 | 46 | #include "PeerConnectionImplEnumsBinding.cpp" |
michael@0 | 47 | |
michael@0 | 48 | #include "mtransport_test_utils.h" |
michael@0 | 49 | #include "gtest_ringbuffer_dumper.h" |
michael@0 | 50 | MtransportTestUtils *test_utils; |
michael@0 | 51 | nsCOMPtr<nsIThread> gMainThread; |
michael@0 | 52 | nsCOMPtr<nsIThread> gGtestThread; |
michael@0 | 53 | bool gTestsComplete = false; |
michael@0 | 54 | |
michael@0 | 55 | #ifndef USE_FAKE_MEDIA_STREAMS |
michael@0 | 56 | #error USE_FAKE_MEDIA_STREAMS undefined |
michael@0 | 57 | #endif |
michael@0 | 58 | #ifndef USE_FAKE_PCOBSERVER |
michael@0 | 59 | #error USE_FAKE_PCOBSERVER undefined |
michael@0 | 60 | #endif |
michael@0 | 61 | |
michael@0 | 62 | static int kDefaultTimeout = 7000; |
michael@0 | 63 | static bool fRtcpMux = true; |
michael@0 | 64 | |
michael@0 | 65 | static std::string callerName = "caller"; |
michael@0 | 66 | static std::string calleeName = "callee"; |
michael@0 | 67 | |
michael@0 | 68 | #define ARRAY_TO_STL(container, type, array) \ |
michael@0 | 69 | (container<type>((array), (array) + PR_ARRAY_SIZE(array))) |
michael@0 | 70 | |
michael@0 | 71 | #define ARRAY_TO_SET(type, array) ARRAY_TO_STL(std::set, type, array) |
michael@0 | 72 | |
michael@0 | 73 | std::string g_stun_server_address((char *)"23.21.150.121"); |
michael@0 | 74 | uint16_t g_stun_server_port(3478); |
michael@0 | 75 | std::string kBogusSrflxAddress((char *)"192.0.2.1"); |
michael@0 | 76 | uint16_t kBogusSrflxPort(1001); |
michael@0 | 77 | |
michael@0 | 78 | namespace sipcc { |
michael@0 | 79 | |
michael@0 | 80 | // We can't use mozilla/dom/MediaConstraintsBinding.h here because it uses |
michael@0 | 81 | // nsString, so we pass constraints in using MediaConstraintsExternal instead |
michael@0 | 82 | |
michael@0 | 83 | class MediaConstraints : public MediaConstraintsExternal { |
michael@0 | 84 | public: |
michael@0 | 85 | void setBooleanConstraint(const char *namePtr, bool value, bool mandatory) { |
michael@0 | 86 | cc_boolean_constraint_t &member (getMember(namePtr)); |
michael@0 | 87 | member.was_passed = true; |
michael@0 | 88 | member.value = value; |
michael@0 | 89 | member.mandatory = mandatory; |
michael@0 | 90 | } |
michael@0 | 91 | private: |
michael@0 | 92 | cc_boolean_constraint_t &getMember(const char *namePtr) { |
michael@0 | 93 | if (strcmp(namePtr, "OfferToReceiveAudio") == 0) { |
michael@0 | 94 | return mConstraints.offer_to_receive_audio; |
michael@0 | 95 | } |
michael@0 | 96 | if (strcmp(namePtr, "OfferToReceiveVideo") == 0) { |
michael@0 | 97 | return mConstraints.offer_to_receive_video; |
michael@0 | 98 | } |
michael@0 | 99 | MOZ_ASSERT(false); |
michael@0 | 100 | return mConstraints.moz_dont_offer_datachannel; |
michael@0 | 101 | } |
michael@0 | 102 | }; |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | using namespace mozilla; |
michael@0 | 106 | using namespace mozilla::dom; |
michael@0 | 107 | |
michael@0 | 108 | namespace test { |
michael@0 | 109 | std::string indent(const std::string &s, int width = 4) { |
michael@0 | 110 | std::string prefix; |
michael@0 | 111 | std::string out; |
michael@0 | 112 | char previous = '\n'; |
michael@0 | 113 | prefix.assign(width, ' '); |
michael@0 | 114 | for (std::string::const_iterator i = s.begin(); i != s.end(); i++) { |
michael@0 | 115 | if (previous == '\n') { |
michael@0 | 116 | out += prefix; |
michael@0 | 117 | } |
michael@0 | 118 | out += *i; |
michael@0 | 119 | previous = *i; |
michael@0 | 120 | } |
michael@0 | 121 | return out; |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | static const std::string strSampleSdpAudioVideoNoIce = |
michael@0 | 125 | "v=0\r\n" |
michael@0 | 126 | "o=Mozilla-SIPUA 4949 0 IN IP4 10.86.255.143\r\n" |
michael@0 | 127 | "s=SIP Call\r\n" |
michael@0 | 128 | "t=0 0\r\n" |
michael@0 | 129 | "a=ice-ufrag:qkEP\r\n" |
michael@0 | 130 | "a=ice-pwd:ed6f9GuHjLcoCN6sC/Eh7fVl\r\n" |
michael@0 | 131 | "m=audio 16384 RTP/AVP 0 8 9 101\r\n" |
michael@0 | 132 | "c=IN IP4 10.86.255.143\r\n" |
michael@0 | 133 | "a=rtpmap:0 PCMU/8000\r\n" |
michael@0 | 134 | "a=rtpmap:8 PCMA/8000\r\n" |
michael@0 | 135 | "a=rtpmap:9 G722/8000\r\n" |
michael@0 | 136 | "a=rtpmap:101 telephone-event/8000\r\n" |
michael@0 | 137 | "a=fmtp:101 0-15\r\n" |
michael@0 | 138 | "a=sendrecv\r\n" |
michael@0 | 139 | "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n" |
michael@0 | 140 | "a=candidate:2 2 UDP 2130706431 192.168.2.2 50006 typ host\r\n" |
michael@0 | 141 | "m=video 1024 RTP/AVP 97\r\n" |
michael@0 | 142 | "c=IN IP4 10.86.255.143\r\n" |
michael@0 | 143 | "a=rtpmap:120 VP8/90000\r\n" |
michael@0 | 144 | "a=fmtp:97 profile-level-id=42E00C\r\n" |
michael@0 | 145 | "a=sendrecv\r\n" |
michael@0 | 146 | "a=candidate:1 1 UDP 2130706431 192.168.2.3 50007 typ host\r\n" |
michael@0 | 147 | "a=candidate:2 2 UDP 2130706431 192.168.2.4 50008 typ host\r\n"; |
michael@0 | 148 | |
michael@0 | 149 | static const std::string strSampleCandidate = |
michael@0 | 150 | "a=candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host\r\n"; |
michael@0 | 151 | |
michael@0 | 152 | static const std::string strSampleMid = ""; |
michael@0 | 153 | |
michael@0 | 154 | static const unsigned short nSamplelevel = 2; |
michael@0 | 155 | |
michael@0 | 156 | static const std::string strG711SdpOffer = |
michael@0 | 157 | "v=0\r\n" |
michael@0 | 158 | "o=- 1 1 IN IP4 148.147.200.251\r\n" |
michael@0 | 159 | "s=-\r\n" |
michael@0 | 160 | "b=AS:64\r\n" |
michael@0 | 161 | "t=0 0\r\n" |
michael@0 | 162 | "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" |
michael@0 | 163 | "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" |
michael@0 | 164 | "m=audio 9000 RTP/AVP 0 8 126\r\n" |
michael@0 | 165 | "c=IN IP4 148.147.200.251\r\n" |
michael@0 | 166 | "b=TIAS:64000\r\n" |
michael@0 | 167 | "a=rtpmap:0 PCMU/8000\r\n" |
michael@0 | 168 | "a=rtpmap:8 PCMA/8000\r\n" |
michael@0 | 169 | "a=rtpmap:126 telephone-event/8000\r\n" |
michael@0 | 170 | "a=candidate:0 1 udp 2130706432 148.147.200.251 9000 typ host\r\n" |
michael@0 | 171 | "a=candidate:0 2 udp 2130706432 148.147.200.251 9005 typ host\r\n" |
michael@0 | 172 | "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" |
michael@0 | 173 | "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" |
michael@0 | 174 | "a=sendrecv\r\n"; |
michael@0 | 175 | |
michael@0 | 176 | |
michael@0 | 177 | enum sdpTestFlags |
michael@0 | 178 | { |
michael@0 | 179 | SHOULD_SEND_AUDIO = (1<<0), |
michael@0 | 180 | SHOULD_RECV_AUDIO = (1<<1), |
michael@0 | 181 | SHOULD_INACTIVE_AUDIO = (1<<2), |
michael@0 | 182 | SHOULD_REJECT_AUDIO = (1<<3), |
michael@0 | 183 | SHOULD_OMIT_AUDIO = (1<<4), |
michael@0 | 184 | DONT_CHECK_AUDIO = (1<<5), |
michael@0 | 185 | SHOULD_CHECK_AUDIO = (1<<6), |
michael@0 | 186 | |
michael@0 | 187 | SHOULD_SEND_VIDEO = (1<<8), |
michael@0 | 188 | SHOULD_RECV_VIDEO = (1<<9), |
michael@0 | 189 | SHOULD_INACTIVE_VIDEO = (1<<10), |
michael@0 | 190 | SHOULD_REJECT_VIDEO = (1<<11), |
michael@0 | 191 | SHOULD_OMIT_VIDEO = (1<<12), |
michael@0 | 192 | DONT_CHECK_VIDEO = (1<<13), |
michael@0 | 193 | SHOULD_CHECK_VIDEO = (1<<14), |
michael@0 | 194 | |
michael@0 | 195 | SHOULD_INCLUDE_DATA = (1 << 16), |
michael@0 | 196 | DONT_CHECK_DATA = (1 << 17), |
michael@0 | 197 | |
michael@0 | 198 | SHOULD_SENDRECV_AUDIO = SHOULD_SEND_AUDIO | SHOULD_RECV_AUDIO, |
michael@0 | 199 | SHOULD_SENDRECV_VIDEO = SHOULD_SEND_VIDEO | SHOULD_RECV_VIDEO, |
michael@0 | 200 | SHOULD_SENDRECV_AV = SHOULD_SENDRECV_AUDIO | SHOULD_SENDRECV_VIDEO, |
michael@0 | 201 | SHOULD_CHECK_AV = SHOULD_CHECK_AUDIO | SHOULD_CHECK_VIDEO, |
michael@0 | 202 | |
michael@0 | 203 | AUDIO_FLAGS = SHOULD_SEND_AUDIO | SHOULD_RECV_AUDIO |
michael@0 | 204 | | SHOULD_INACTIVE_AUDIO | SHOULD_REJECT_AUDIO |
michael@0 | 205 | | DONT_CHECK_AUDIO | SHOULD_OMIT_AUDIO |
michael@0 | 206 | | SHOULD_CHECK_AUDIO, |
michael@0 | 207 | |
michael@0 | 208 | VIDEO_FLAGS = SHOULD_SEND_VIDEO | SHOULD_RECV_VIDEO |
michael@0 | 209 | | SHOULD_INACTIVE_VIDEO | SHOULD_REJECT_VIDEO |
michael@0 | 210 | | DONT_CHECK_VIDEO | SHOULD_OMIT_VIDEO |
michael@0 | 211 | | SHOULD_CHECK_VIDEO |
michael@0 | 212 | }; |
michael@0 | 213 | |
michael@0 | 214 | enum offerAnswerFlags |
michael@0 | 215 | { |
michael@0 | 216 | OFFER_NONE = 0, // Sugar to make function calls clearer. |
michael@0 | 217 | OFFER_AUDIO = (1<<0), |
michael@0 | 218 | OFFER_VIDEO = (1<<1), |
michael@0 | 219 | // Leaving some room here for other media types |
michael@0 | 220 | ANSWER_NONE = 0, // Sugar to make function calls clearer. |
michael@0 | 221 | ANSWER_AUDIO = (1<<8), |
michael@0 | 222 | ANSWER_VIDEO = (1<<9), |
michael@0 | 223 | |
michael@0 | 224 | OFFER_AV = OFFER_AUDIO | OFFER_VIDEO, |
michael@0 | 225 | ANSWER_AV = ANSWER_AUDIO | ANSWER_VIDEO |
michael@0 | 226 | }; |
michael@0 | 227 | |
michael@0 | 228 | enum mediaPipelineFlags |
michael@0 | 229 | { |
michael@0 | 230 | PIPELINE_LOCAL = (1<<0), |
michael@0 | 231 | PIPELINE_RTCP_MUX = (1<<1), |
michael@0 | 232 | PIPELINE_SEND = (1<<2), |
michael@0 | 233 | PIPELINE_VIDEO = (1<<3), |
michael@0 | 234 | PIPELINE_RTCP_NACK = (1<<4) |
michael@0 | 235 | }; |
michael@0 | 236 | |
michael@0 | 237 | |
michael@0 | 238 | class TestObserver : public AFakePCObserver |
michael@0 | 239 | { |
michael@0 | 240 | public: |
michael@0 | 241 | TestObserver(sipcc::PeerConnectionImpl *peerConnection, |
michael@0 | 242 | const std::string &aName) : |
michael@0 | 243 | AFakePCObserver(peerConnection, aName) {} |
michael@0 | 244 | |
michael@0 | 245 | size_t MatchingCandidates(const std::string& cand) { |
michael@0 | 246 | size_t count = 0; |
michael@0 | 247 | |
michael@0 | 248 | for (size_t i=0; i<candidates.size(); ++i) { |
michael@0 | 249 | if (candidates[i].find(cand) != std::string::npos) |
michael@0 | 250 | ++count; |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | return count; |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | NS_DECL_THREADSAFE_ISUPPORTS |
michael@0 | 257 | NS_IMETHODIMP OnCreateOfferSuccess(const char* offer, ER&); |
michael@0 | 258 | NS_IMETHODIMP OnCreateOfferError(uint32_t code, const char *msg, ER&); |
michael@0 | 259 | NS_IMETHODIMP OnCreateAnswerSuccess(const char* answer, ER&); |
michael@0 | 260 | NS_IMETHODIMP OnCreateAnswerError(uint32_t code, const char *msg, ER&); |
michael@0 | 261 | NS_IMETHODIMP OnSetLocalDescriptionSuccess(ER&); |
michael@0 | 262 | NS_IMETHODIMP OnSetRemoteDescriptionSuccess(ER&); |
michael@0 | 263 | NS_IMETHODIMP OnSetLocalDescriptionError(uint32_t code, const char *msg, ER&); |
michael@0 | 264 | NS_IMETHODIMP OnSetRemoteDescriptionError(uint32_t code, const char *msg, ER&); |
michael@0 | 265 | NS_IMETHODIMP NotifyConnection(ER&); |
michael@0 | 266 | NS_IMETHODIMP NotifyClosedConnection(ER&); |
michael@0 | 267 | NS_IMETHODIMP NotifyDataChannel(nsIDOMDataChannel *channel, ER&); |
michael@0 | 268 | NS_IMETHODIMP OnStateChange(PCObserverStateType state_type, ER&, void*); |
michael@0 | 269 | NS_IMETHODIMP OnAddStream(nsIDOMMediaStream *stream, ER&); |
michael@0 | 270 | NS_IMETHODIMP OnRemoveStream(ER&); |
michael@0 | 271 | NS_IMETHODIMP OnAddTrack(ER&); |
michael@0 | 272 | NS_IMETHODIMP OnRemoveTrack(ER&); |
michael@0 | 273 | NS_IMETHODIMP OnAddIceCandidateSuccess(ER&); |
michael@0 | 274 | NS_IMETHODIMP OnAddIceCandidateError(uint32_t code, const char *msg, ER&); |
michael@0 | 275 | NS_IMETHODIMP OnIceCandidate(uint16_t level, const char *mid, const char *cand, ER&); |
michael@0 | 276 | }; |
michael@0 | 277 | |
michael@0 | 278 | NS_IMPL_ISUPPORTS(TestObserver, nsISupportsWeakReference) |
michael@0 | 279 | |
michael@0 | 280 | NS_IMETHODIMP |
michael@0 | 281 | TestObserver::OnCreateOfferSuccess(const char* offer, ER&) |
michael@0 | 282 | { |
michael@0 | 283 | lastString = strdup(offer); |
michael@0 | 284 | state = stateSuccess; |
michael@0 | 285 | std::cout << name << ": onCreateOfferSuccess = " << std::endl << indent(offer) |
michael@0 | 286 | << std::endl; |
michael@0 | 287 | return NS_OK; |
michael@0 | 288 | } |
michael@0 | 289 | |
michael@0 | 290 | NS_IMETHODIMP |
michael@0 | 291 | TestObserver::OnCreateOfferError(uint32_t code, const char *message, ER&) |
michael@0 | 292 | { |
michael@0 | 293 | lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); |
michael@0 | 294 | state = stateError; |
michael@0 | 295 | std::cout << name << ": onCreateOfferError = " << code |
michael@0 | 296 | << " (" << message << ")" << std::endl; |
michael@0 | 297 | return NS_OK; |
michael@0 | 298 | } |
michael@0 | 299 | |
michael@0 | 300 | NS_IMETHODIMP |
michael@0 | 301 | TestObserver::OnCreateAnswerSuccess(const char* answer, ER&) |
michael@0 | 302 | { |
michael@0 | 303 | lastString = strdup(answer); |
michael@0 | 304 | state = stateSuccess; |
michael@0 | 305 | std::cout << name << ": onCreateAnswerSuccess =" << std::endl |
michael@0 | 306 | << indent(answer) << std::endl; |
michael@0 | 307 | return NS_OK; |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | NS_IMETHODIMP |
michael@0 | 311 | TestObserver::OnCreateAnswerError(uint32_t code, const char *message, ER&) |
michael@0 | 312 | { |
michael@0 | 313 | lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); |
michael@0 | 314 | std::cout << name << ": onCreateAnswerError = " << code |
michael@0 | 315 | << " (" << message << ")" << std::endl; |
michael@0 | 316 | state = stateError; |
michael@0 | 317 | return NS_OK; |
michael@0 | 318 | } |
michael@0 | 319 | |
michael@0 | 320 | NS_IMETHODIMP |
michael@0 | 321 | TestObserver::OnSetLocalDescriptionSuccess(ER&) |
michael@0 | 322 | { |
michael@0 | 323 | lastStatusCode = sipcc::PeerConnectionImpl::kNoError; |
michael@0 | 324 | state = stateSuccess; |
michael@0 | 325 | std::cout << name << ": onSetLocalDescriptionSuccess" << std::endl; |
michael@0 | 326 | return NS_OK; |
michael@0 | 327 | } |
michael@0 | 328 | |
michael@0 | 329 | NS_IMETHODIMP |
michael@0 | 330 | TestObserver::OnSetRemoteDescriptionSuccess(ER&) |
michael@0 | 331 | { |
michael@0 | 332 | lastStatusCode = sipcc::PeerConnectionImpl::kNoError; |
michael@0 | 333 | state = stateSuccess; |
michael@0 | 334 | std::cout << name << ": onSetRemoteDescriptionSuccess" << std::endl; |
michael@0 | 335 | return NS_OK; |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | NS_IMETHODIMP |
michael@0 | 339 | TestObserver::OnSetLocalDescriptionError(uint32_t code, const char *message, ER&) |
michael@0 | 340 | { |
michael@0 | 341 | lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); |
michael@0 | 342 | state = stateError; |
michael@0 | 343 | std::cout << name << ": onSetLocalDescriptionError = " << code |
michael@0 | 344 | << " (" << message << ")" << std::endl; |
michael@0 | 345 | return NS_OK; |
michael@0 | 346 | } |
michael@0 | 347 | |
michael@0 | 348 | NS_IMETHODIMP |
michael@0 | 349 | TestObserver::OnSetRemoteDescriptionError(uint32_t code, const char *message, ER&) |
michael@0 | 350 | { |
michael@0 | 351 | lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); |
michael@0 | 352 | state = stateError; |
michael@0 | 353 | std::cout << name << ": onSetRemoteDescriptionError = " << code |
michael@0 | 354 | << " (" << message << ")" << std::endl; |
michael@0 | 355 | return NS_OK; |
michael@0 | 356 | } |
michael@0 | 357 | |
michael@0 | 358 | NS_IMETHODIMP |
michael@0 | 359 | TestObserver::NotifyConnection(ER&) |
michael@0 | 360 | { |
michael@0 | 361 | std::cout << name << ": NotifyConnection" << std::endl; |
michael@0 | 362 | return NS_OK; |
michael@0 | 363 | } |
michael@0 | 364 | |
michael@0 | 365 | NS_IMETHODIMP |
michael@0 | 366 | TestObserver::NotifyClosedConnection(ER&) |
michael@0 | 367 | { |
michael@0 | 368 | std::cout << name << ": NotifyClosedConnection" << std::endl; |
michael@0 | 369 | return NS_OK; |
michael@0 | 370 | } |
michael@0 | 371 | |
michael@0 | 372 | NS_IMETHODIMP |
michael@0 | 373 | TestObserver::NotifyDataChannel(nsIDOMDataChannel *channel, ER&) |
michael@0 | 374 | { |
michael@0 | 375 | std::cout << name << ": NotifyDataChannel" << std::endl; |
michael@0 | 376 | return NS_OK; |
michael@0 | 377 | } |
michael@0 | 378 | |
michael@0 | 379 | NS_IMETHODIMP |
michael@0 | 380 | TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*) |
michael@0 | 381 | { |
michael@0 | 382 | nsresult rv; |
michael@0 | 383 | PCImplReadyState gotready; |
michael@0 | 384 | PCImplIceConnectionState gotice; |
michael@0 | 385 | PCImplIceGatheringState goticegathering; |
michael@0 | 386 | PCImplSipccState gotsipcc; |
michael@0 | 387 | PCImplSignalingState gotsignaling; |
michael@0 | 388 | |
michael@0 | 389 | std::cout << name << ": "; |
michael@0 | 390 | |
michael@0 | 391 | switch (state_type) |
michael@0 | 392 | { |
michael@0 | 393 | case PCObserverStateType::ReadyState: |
michael@0 | 394 | rv = pc->ReadyState(&gotready); |
michael@0 | 395 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 396 | std::cout << "Ready State: " |
michael@0 | 397 | << PCImplReadyStateValues::strings[int(gotready)].value |
michael@0 | 398 | << std::endl; |
michael@0 | 399 | break; |
michael@0 | 400 | case PCObserverStateType::IceConnectionState: |
michael@0 | 401 | rv = pc->IceConnectionState(&gotice); |
michael@0 | 402 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 403 | std::cout << "ICE Connection State: " |
michael@0 | 404 | << PCImplIceConnectionStateValues::strings[int(gotice)].value |
michael@0 | 405 | << std::endl; |
michael@0 | 406 | break; |
michael@0 | 407 | case PCObserverStateType::IceGatheringState: |
michael@0 | 408 | rv = pc->IceGatheringState(&goticegathering); |
michael@0 | 409 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 410 | std::cout |
michael@0 | 411 | << "ICE Gathering State: " |
michael@0 | 412 | << PCImplIceGatheringStateValues::strings[int(goticegathering)].value |
michael@0 | 413 | << std::endl; |
michael@0 | 414 | break; |
michael@0 | 415 | case PCObserverStateType::SdpState: |
michael@0 | 416 | std::cout << "SDP State: " << std::endl; |
michael@0 | 417 | // NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 418 | break; |
michael@0 | 419 | case PCObserverStateType::SipccState: |
michael@0 | 420 | rv = pc->SipccState(&gotsipcc); |
michael@0 | 421 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 422 | std::cout << "SIPCC State: " |
michael@0 | 423 | << PCImplSipccStateValues::strings[int(gotsipcc)].value |
michael@0 | 424 | << std::endl; |
michael@0 | 425 | break; |
michael@0 | 426 | case PCObserverStateType::SignalingState: |
michael@0 | 427 | rv = pc->SignalingState(&gotsignaling); |
michael@0 | 428 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 429 | std::cout << "Signaling State: " |
michael@0 | 430 | << PCImplSignalingStateValues::strings[int(gotsignaling)].value |
michael@0 | 431 | << std::endl; |
michael@0 | 432 | break; |
michael@0 | 433 | default: |
michael@0 | 434 | // Unknown State |
michael@0 | 435 | MOZ_CRASH("Unknown state change type."); |
michael@0 | 436 | break; |
michael@0 | 437 | } |
michael@0 | 438 | |
michael@0 | 439 | lastStateType = state_type; |
michael@0 | 440 | return NS_OK; |
michael@0 | 441 | } |
michael@0 | 442 | |
michael@0 | 443 | |
michael@0 | 444 | NS_IMETHODIMP |
michael@0 | 445 | TestObserver::OnAddStream(nsIDOMMediaStream *stream, ER&) |
michael@0 | 446 | { |
michael@0 | 447 | PR_ASSERT(stream); |
michael@0 | 448 | |
michael@0 | 449 | DOMMediaStream *ms = static_cast<DOMMediaStream *>(stream); |
michael@0 | 450 | |
michael@0 | 451 | std::cout << name << ": OnAddStream called hints=" << ms->GetHintContents() |
michael@0 | 452 | << " thread=" << PR_GetCurrentThread() << std::endl ; |
michael@0 | 453 | |
michael@0 | 454 | onAddStreamCalled = true; |
michael@0 | 455 | |
michael@0 | 456 | streams.push_back(ms); |
michael@0 | 457 | |
michael@0 | 458 | // We know that the media stream is secretly a Fake_SourceMediaStream, |
michael@0 | 459 | // so now we can start it pulling from us |
michael@0 | 460 | Fake_SourceMediaStream *fs = static_cast<Fake_SourceMediaStream *>(ms->GetStream()); |
michael@0 | 461 | |
michael@0 | 462 | test_utils->sts_target()->Dispatch( |
michael@0 | 463 | WrapRunnable(fs, &Fake_SourceMediaStream::Start), |
michael@0 | 464 | NS_DISPATCH_NORMAL); |
michael@0 | 465 | |
michael@0 | 466 | return NS_OK; |
michael@0 | 467 | } |
michael@0 | 468 | |
michael@0 | 469 | NS_IMETHODIMP |
michael@0 | 470 | TestObserver::OnRemoveStream(ER&) |
michael@0 | 471 | { |
michael@0 | 472 | state = stateSuccess; |
michael@0 | 473 | return NS_OK; |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | NS_IMETHODIMP |
michael@0 | 477 | TestObserver::OnAddTrack(ER&) |
michael@0 | 478 | { |
michael@0 | 479 | state = stateSuccess; |
michael@0 | 480 | return NS_OK; |
michael@0 | 481 | } |
michael@0 | 482 | |
michael@0 | 483 | NS_IMETHODIMP |
michael@0 | 484 | TestObserver::OnRemoveTrack(ER&) |
michael@0 | 485 | { |
michael@0 | 486 | state = stateSuccess; |
michael@0 | 487 | return NS_OK; |
michael@0 | 488 | } |
michael@0 | 489 | |
michael@0 | 490 | NS_IMETHODIMP |
michael@0 | 491 | TestObserver::OnIceCandidate(uint16_t level, |
michael@0 | 492 | const char * mid, |
michael@0 | 493 | const char * candidate, ER&) |
michael@0 | 494 | { |
michael@0 | 495 | std::cout << name << ": onIceCandidate [" << level << "/" |
michael@0 | 496 | << mid << "] " << candidate << std::endl; |
michael@0 | 497 | candidates.push_back(candidate); |
michael@0 | 498 | return NS_OK; |
michael@0 | 499 | } |
michael@0 | 500 | |
michael@0 | 501 | NS_IMETHODIMP |
michael@0 | 502 | TestObserver::OnAddIceCandidateSuccess(ER&) |
michael@0 | 503 | { |
michael@0 | 504 | lastStatusCode = sipcc::PeerConnectionImpl::kNoError; |
michael@0 | 505 | state = stateSuccess; |
michael@0 | 506 | std::cout << name << ": onAddIceCandidateSuccess" << std::endl; |
michael@0 | 507 | addIceSuccessCount++; |
michael@0 | 508 | return NS_OK; |
michael@0 | 509 | } |
michael@0 | 510 | |
michael@0 | 511 | NS_IMETHODIMP |
michael@0 | 512 | TestObserver::OnAddIceCandidateError(uint32_t code, const char *message, ER&) |
michael@0 | 513 | { |
michael@0 | 514 | lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code); |
michael@0 | 515 | state = stateError; |
michael@0 | 516 | std::cout << name << ": onAddIceCandidateError = " << code |
michael@0 | 517 | << " (" << message << ")" << std::endl; |
michael@0 | 518 | return NS_OK; |
michael@0 | 519 | } |
michael@0 | 520 | |
michael@0 | 521 | class ParsedSDP { |
michael@0 | 522 | public: |
michael@0 | 523 | //Line number with the corresponding SDP line. |
michael@0 | 524 | typedef std::pair<int, std::string> SdpLine; |
michael@0 | 525 | |
michael@0 | 526 | ParsedSDP(std::string sdp): |
michael@0 | 527 | sdp_(), |
michael@0 | 528 | sdp_without_ice_(), |
michael@0 | 529 | ice_candidates_(), |
michael@0 | 530 | levels_(0), |
michael@0 | 531 | num_lines(0) |
michael@0 | 532 | { |
michael@0 | 533 | sdp_ = sdp; |
michael@0 | 534 | Parse(); |
michael@0 | 535 | } |
michael@0 | 536 | |
michael@0 | 537 | void DeleteAllLines(std::string objType) |
michael@0 | 538 | { |
michael@0 | 539 | int count = sdp_map_.count(objType); |
michael@0 | 540 | std::cout << "Removing " << count << " lines from SDP (" << objType |
michael@0 | 541 | << ")" << std::endl; |
michael@0 | 542 | |
michael@0 | 543 | for (int i = 0; i < count; i++) { |
michael@0 | 544 | DeleteLine(objType); |
michael@0 | 545 | } |
michael@0 | 546 | } |
michael@0 | 547 | |
michael@0 | 548 | void DeleteLine(std::string objType) |
michael@0 | 549 | { |
michael@0 | 550 | ReplaceLine(objType, ""); |
michael@0 | 551 | } |
michael@0 | 552 | |
michael@0 | 553 | // Replaces the first instance of objType in the SDP with |
michael@0 | 554 | // a new string. |
michael@0 | 555 | // If content is an empty string then the line will be removed |
michael@0 | 556 | void ReplaceLine(std::string objType, std::string content) |
michael@0 | 557 | { |
michael@0 | 558 | std::multimap<std::string, SdpLine>::iterator it; |
michael@0 | 559 | it = sdp_map_.find(objType); |
michael@0 | 560 | if(it != sdp_map_.end()) { |
michael@0 | 561 | SdpLine sdp_line_pair = (*it).second; |
michael@0 | 562 | int line_no = sdp_line_pair.first; |
michael@0 | 563 | sdp_map_.erase(it); |
michael@0 | 564 | if(content.empty()) { |
michael@0 | 565 | return; |
michael@0 | 566 | } |
michael@0 | 567 | std::string value = content.substr(objType.length() + 1); |
michael@0 | 568 | sdp_map_.insert(std::pair<std::string, SdpLine>(objType, |
michael@0 | 569 | std::make_pair(line_no,value))); |
michael@0 | 570 | } |
michael@0 | 571 | } |
michael@0 | 572 | |
michael@0 | 573 | void AddLine(std::string content) |
michael@0 | 574 | { |
michael@0 | 575 | size_t whiteSpace = content.find(' '); |
michael@0 | 576 | std::string key; |
michael@0 | 577 | std::string value; |
michael@0 | 578 | if(whiteSpace == std::string::npos) { |
michael@0 | 579 | key = content.substr(0, content.size() - 2); |
michael@0 | 580 | value = ""; |
michael@0 | 581 | } else { |
michael@0 | 582 | key = content.substr(0, whiteSpace); |
michael@0 | 583 | value = content.substr(whiteSpace+1); |
michael@0 | 584 | } |
michael@0 | 585 | sdp_map_.insert(std::pair<std::string, SdpLine>(key, |
michael@0 | 586 | std::make_pair(num_lines,value))); |
michael@0 | 587 | num_lines++; |
michael@0 | 588 | } |
michael@0 | 589 | |
michael@0 | 590 | // Returns the values for all lines of the indicated type |
michael@0 | 591 | // Removes trailing "\r\n" from values. |
michael@0 | 592 | std::vector<std::string> GetLines(std::string objType) const |
michael@0 | 593 | { |
michael@0 | 594 | std::multimap<std::string, SdpLine>::const_iterator it, end; |
michael@0 | 595 | std::vector<std::string> values; |
michael@0 | 596 | it = sdp_map_.lower_bound(objType); |
michael@0 | 597 | end = sdp_map_.upper_bound(objType); |
michael@0 | 598 | while (it != end) { |
michael@0 | 599 | std::string value = it->second.second; |
michael@0 | 600 | if (value.find("\r") != std::string::npos) { |
michael@0 | 601 | value = value.substr(0, value.find("\r")); |
michael@0 | 602 | } else { |
michael@0 | 603 | ADD_FAILURE(); |
michael@0 | 604 | } |
michael@0 | 605 | values.push_back(value); |
michael@0 | 606 | ++it; |
michael@0 | 607 | } |
michael@0 | 608 | return values; |
michael@0 | 609 | } |
michael@0 | 610 | |
michael@0 | 611 | //Parse SDP as std::string into map that looks like: |
michael@0 | 612 | // key: sdp content till first space |
michael@0 | 613 | // value : <line_number, sdp content after the first space> |
michael@0 | 614 | void Parse() |
michael@0 | 615 | { |
michael@0 | 616 | size_t prev = 0; |
michael@0 | 617 | size_t found = 0; |
michael@0 | 618 | num_lines = 0; |
michael@0 | 619 | for(;;) { |
michael@0 | 620 | found = sdp_.find('\n', found + 1); |
michael@0 | 621 | if (found == std::string::npos) |
michael@0 | 622 | break; |
michael@0 | 623 | std::string line = sdp_.substr(prev, (found - prev) + 1); |
michael@0 | 624 | size_t whiteSpace = line.find(' '); |
michael@0 | 625 | std::string key; |
michael@0 | 626 | std::string value; |
michael@0 | 627 | if(whiteSpace == std::string::npos) { |
michael@0 | 628 | //this is the line with no extra contents |
michael@0 | 629 | //example, v=0, a=sendrecv |
michael@0 | 630 | key = line.substr(0, line.size() - 2); |
michael@0 | 631 | //<line_no>:<valeu> |
michael@0 | 632 | value = ""; |
michael@0 | 633 | } else { |
michael@0 | 634 | key = line.substr(0, whiteSpace); |
michael@0 | 635 | //<line_no>:<value> |
michael@0 | 636 | value = line.substr(whiteSpace+1); |
michael@0 | 637 | } |
michael@0 | 638 | SdpLine sdp_line_pair = std::make_pair(num_lines,value); |
michael@0 | 639 | sdp_map_.insert(std::pair<std::string, SdpLine>(key, sdp_line_pair)); |
michael@0 | 640 | num_lines++; |
michael@0 | 641 | //storing ice candidates separately for quick acesss as needed |
michael@0 | 642 | //for the trickle unit tests |
michael@0 | 643 | if (line.find("a=candidate") == 0) { |
michael@0 | 644 | // This is a candidate, strip of a= and \r\n |
michael@0 | 645 | std::string cand = line.substr(2, line.size() - 4); |
michael@0 | 646 | ice_candidates_.insert(std::pair<int, std::string>(levels_, cand)); |
michael@0 | 647 | } else { |
michael@0 | 648 | sdp_without_ice_ += line; |
michael@0 | 649 | } |
michael@0 | 650 | if (line.find("m=") == 0) { |
michael@0 | 651 | // This is an m-line |
michael@0 | 652 | ++levels_; |
michael@0 | 653 | } |
michael@0 | 654 | prev = found + 1; |
michael@0 | 655 | } |
michael@0 | 656 | } |
michael@0 | 657 | |
michael@0 | 658 | //Convert Internal SDP representation into String representation |
michael@0 | 659 | std::string getSdp() |
michael@0 | 660 | { |
michael@0 | 661 | std::vector<std::string> sdp_lines(num_lines); |
michael@0 | 662 | for (std::multimap<std::string, SdpLine>::iterator it = sdp_map_.begin(); |
michael@0 | 663 | it != sdp_map_.end(); ++it) { |
michael@0 | 664 | |
michael@0 | 665 | SdpLine sdp_line_pair = (*it).second; |
michael@0 | 666 | std::string value; |
michael@0 | 667 | if(sdp_line_pair.second.length() == 0) { |
michael@0 | 668 | value = (*it).first + "\r\n"; |
michael@0 | 669 | sdp_lines[sdp_line_pair.first] = value; |
michael@0 | 670 | } else { |
michael@0 | 671 | value = (*it).first + ' ' + sdp_line_pair.second; |
michael@0 | 672 | sdp_lines[sdp_line_pair.first] = value; |
michael@0 | 673 | } |
michael@0 | 674 | } |
michael@0 | 675 | |
michael@0 | 676 | //generate our final sdp in std::string format |
michael@0 | 677 | std::string sdp; |
michael@0 | 678 | for (size_t i = 0; i < sdp_lines.size(); i++) |
michael@0 | 679 | { |
michael@0 | 680 | sdp += sdp_lines[i]; |
michael@0 | 681 | } |
michael@0 | 682 | |
michael@0 | 683 | return sdp; |
michael@0 | 684 | } |
michael@0 | 685 | |
michael@0 | 686 | |
michael@0 | 687 | |
michael@0 | 688 | std::string sdp_; |
michael@0 | 689 | std::string sdp_without_ice_; |
michael@0 | 690 | std::multimap<int, std::string> ice_candidates_; |
michael@0 | 691 | std::multimap<std::string, SdpLine> sdp_map_; |
michael@0 | 692 | int levels_; |
michael@0 | 693 | int num_lines; |
michael@0 | 694 | }; |
michael@0 | 695 | |
michael@0 | 696 | class SignalingAgent { |
michael@0 | 697 | public: |
michael@0 | 698 | SignalingAgent(const std::string &aName) : pc(nullptr), name(aName) { |
michael@0 | 699 | cfg_.addStunServer(g_stun_server_address, g_stun_server_port); |
michael@0 | 700 | |
michael@0 | 701 | pc = sipcc::PeerConnectionImpl::CreatePeerConnection(); |
michael@0 | 702 | EXPECT_TRUE(pc); |
michael@0 | 703 | } |
michael@0 | 704 | |
michael@0 | 705 | SignalingAgent(const std::string &aName, const std::string stun_addr, |
michael@0 | 706 | uint16_t stun_port) : pc(nullptr), name(aName) { |
michael@0 | 707 | cfg_.addStunServer(stun_addr, stun_port); |
michael@0 | 708 | |
michael@0 | 709 | pc = sipcc::PeerConnectionImpl::CreatePeerConnection(); |
michael@0 | 710 | EXPECT_TRUE(pc); |
michael@0 | 711 | } |
michael@0 | 712 | |
michael@0 | 713 | |
michael@0 | 714 | ~SignalingAgent() { |
michael@0 | 715 | mozilla::SyncRunnable::DispatchToThread(gMainThread, |
michael@0 | 716 | WrapRunnable(this, &SignalingAgent::Close)); |
michael@0 | 717 | } |
michael@0 | 718 | |
michael@0 | 719 | void Init_m(nsCOMPtr<nsIThread> thread) |
michael@0 | 720 | { |
michael@0 | 721 | pObserver = new TestObserver(pc, name); |
michael@0 | 722 | ASSERT_TRUE(pObserver); |
michael@0 | 723 | |
michael@0 | 724 | ASSERT_EQ(pc->Initialize(*pObserver, nullptr, cfg_, thread), NS_OK); |
michael@0 | 725 | } |
michael@0 | 726 | |
michael@0 | 727 | void Init(nsCOMPtr<nsIThread> thread) |
michael@0 | 728 | { |
michael@0 | 729 | mozilla::SyncRunnable::DispatchToThread(thread, |
michael@0 | 730 | WrapRunnable(this, &SignalingAgent::Init_m, thread)); |
michael@0 | 731 | |
michael@0 | 732 | ASSERT_TRUE_WAIT(sipcc_state() == PCImplSipccState::Started, |
michael@0 | 733 | kDefaultTimeout); |
michael@0 | 734 | } |
michael@0 | 735 | |
michael@0 | 736 | void WaitForGather() { |
michael@0 | 737 | ASSERT_TRUE_WAIT(ice_gathering_state() == PCImplIceGatheringState::Complete, |
michael@0 | 738 | kDefaultTimeout); |
michael@0 | 739 | |
michael@0 | 740 | std::cout << name << ": Init Complete" << std::endl; |
michael@0 | 741 | } |
michael@0 | 742 | |
michael@0 | 743 | bool WaitForGatherAllowFail() { |
michael@0 | 744 | EXPECT_TRUE_WAIT( |
michael@0 | 745 | ice_gathering_state() == PCImplIceGatheringState::Complete || |
michael@0 | 746 | ice_connection_state() == PCImplIceConnectionState::Failed, |
michael@0 | 747 | kDefaultTimeout); |
michael@0 | 748 | |
michael@0 | 749 | if (ice_connection_state() == PCImplIceConnectionState::Failed) { |
michael@0 | 750 | std::cout << name << ": Init Failed" << std::endl; |
michael@0 | 751 | return false; |
michael@0 | 752 | } |
michael@0 | 753 | |
michael@0 | 754 | std::cout << name << "Init Complete" << std::endl; |
michael@0 | 755 | return true; |
michael@0 | 756 | } |
michael@0 | 757 | |
michael@0 | 758 | PCImplSipccState sipcc_state() |
michael@0 | 759 | { |
michael@0 | 760 | return pc->SipccState(); |
michael@0 | 761 | } |
michael@0 | 762 | |
michael@0 | 763 | PCImplIceConnectionState ice_connection_state() |
michael@0 | 764 | { |
michael@0 | 765 | return pc->IceConnectionState(); |
michael@0 | 766 | } |
michael@0 | 767 | |
michael@0 | 768 | PCImplIceGatheringState ice_gathering_state() |
michael@0 | 769 | { |
michael@0 | 770 | return pc->IceGatheringState(); |
michael@0 | 771 | } |
michael@0 | 772 | |
michael@0 | 773 | PCImplSignalingState signaling_state() |
michael@0 | 774 | { |
michael@0 | 775 | return pc->SignalingState(); |
michael@0 | 776 | } |
michael@0 | 777 | |
michael@0 | 778 | void Close() |
michael@0 | 779 | { |
michael@0 | 780 | if (pc) { |
michael@0 | 781 | std::cout << name << ": Close" << std::endl; |
michael@0 | 782 | |
michael@0 | 783 | pc->Close(); |
michael@0 | 784 | pc = nullptr; |
michael@0 | 785 | } |
michael@0 | 786 | |
michael@0 | 787 | // Shutdown is synchronous evidently. |
michael@0 | 788 | // ASSERT_TRUE(pObserver->WaitForObserverCall()); |
michael@0 | 789 | // ASSERT_EQ(pc->sipcc_state(), sipcc::PeerConnectionInterface::kIdle); |
michael@0 | 790 | } |
michael@0 | 791 | |
michael@0 | 792 | bool OfferContains(const std::string& str) { |
michael@0 | 793 | std::string o(offer()); |
michael@0 | 794 | |
michael@0 | 795 | return o.find(str) != std::string::npos; |
michael@0 | 796 | } |
michael@0 | 797 | |
michael@0 | 798 | bool AnswerContains(const std::string& str) { |
michael@0 | 799 | std::string o(answer()); |
michael@0 | 800 | |
michael@0 | 801 | return o.find(str) != std::string::npos; |
michael@0 | 802 | } |
michael@0 | 803 | |
michael@0 | 804 | size_t MatchingCandidates(const std::string& cand) { |
michael@0 | 805 | return pObserver->MatchingCandidates(cand); |
michael@0 | 806 | } |
michael@0 | 807 | |
michael@0 | 808 | char* offer() const { return offer_; } |
michael@0 | 809 | char* answer() const { return answer_; } |
michael@0 | 810 | |
michael@0 | 811 | std::string getLocalDescription() const { |
michael@0 | 812 | char *sdp = nullptr; |
michael@0 | 813 | pc->GetLocalDescription(&sdp); |
michael@0 | 814 | if (!sdp) { |
michael@0 | 815 | return ""; |
michael@0 | 816 | } |
michael@0 | 817 | return sdp; |
michael@0 | 818 | } |
michael@0 | 819 | |
michael@0 | 820 | std::string getRemoteDescription() const { |
michael@0 | 821 | char *sdp = 0; |
michael@0 | 822 | pc->GetRemoteDescription(&sdp); |
michael@0 | 823 | if (!sdp) { |
michael@0 | 824 | return ""; |
michael@0 | 825 | } |
michael@0 | 826 | return sdp; |
michael@0 | 827 | } |
michael@0 | 828 | |
michael@0 | 829 | // Adds a stream to the PeerConnection. |
michael@0 | 830 | void AddStream(uint32_t hint = |
michael@0 | 831 | DOMMediaStream::HINT_CONTENTS_AUDIO | |
michael@0 | 832 | DOMMediaStream::HINT_CONTENTS_VIDEO, |
michael@0 | 833 | MediaStream *stream = nullptr, |
michael@0 | 834 | sipcc::MediaConstraints *constraints = nullptr |
michael@0 | 835 | ) { |
michael@0 | 836 | |
michael@0 | 837 | sipcc::MediaConstraints noConstraints; |
michael@0 | 838 | if (!constraints) { |
michael@0 | 839 | constraints = &noConstraints; |
michael@0 | 840 | } |
michael@0 | 841 | |
michael@0 | 842 | nsRefPtr<DOMMediaStream> domMediaStream; |
michael@0 | 843 | if (stream) { |
michael@0 | 844 | domMediaStream = new DOMMediaStream(stream); |
michael@0 | 845 | } else { |
michael@0 | 846 | domMediaStream = new DOMMediaStream(); |
michael@0 | 847 | } |
michael@0 | 848 | |
michael@0 | 849 | domMediaStream->SetHintContents(hint); |
michael@0 | 850 | ASSERT_EQ(pc->AddStream(*domMediaStream, *constraints), NS_OK); |
michael@0 | 851 | domMediaStream_ = domMediaStream; |
michael@0 | 852 | } |
michael@0 | 853 | |
michael@0 | 854 | |
michael@0 | 855 | // Removes a stream from the PeerConnection. If the stream |
michael@0 | 856 | // parameter is absent, removes the stream that was most |
michael@0 | 857 | // recently added to the PeerConnection. |
michael@0 | 858 | void RemoveLastStreamAdded() { |
michael@0 | 859 | ASSERT_EQ(pc->RemoveStream(*domMediaStream_), NS_OK); |
michael@0 | 860 | } |
michael@0 | 861 | |
michael@0 | 862 | void CreateOffer(sipcc::MediaConstraints& constraints, |
michael@0 | 863 | uint32_t offerFlags, uint32_t sdpCheck, |
michael@0 | 864 | PCImplSignalingState endState = |
michael@0 | 865 | PCImplSignalingState::SignalingStable) { |
michael@0 | 866 | |
michael@0 | 867 | // Create a media stream as if it came from GUM |
michael@0 | 868 | Fake_AudioStreamSource *audio_stream = |
michael@0 | 869 | new Fake_AudioStreamSource(); |
michael@0 | 870 | |
michael@0 | 871 | nsresult ret; |
michael@0 | 872 | mozilla::SyncRunnable::DispatchToThread( |
michael@0 | 873 | test_utils->sts_target(), |
michael@0 | 874 | WrapRunnableRet(audio_stream, &Fake_MediaStream::Start, &ret)); |
michael@0 | 875 | |
michael@0 | 876 | ASSERT_TRUE(NS_SUCCEEDED(ret)); |
michael@0 | 877 | |
michael@0 | 878 | uint32_t aHintContents = 0; |
michael@0 | 879 | if (offerFlags & OFFER_AUDIO) { |
michael@0 | 880 | aHintContents |= DOMMediaStream::HINT_CONTENTS_AUDIO; |
michael@0 | 881 | } |
michael@0 | 882 | if (offerFlags & OFFER_VIDEO) { |
michael@0 | 883 | aHintContents |= DOMMediaStream::HINT_CONTENTS_VIDEO; |
michael@0 | 884 | } |
michael@0 | 885 | AddStream(aHintContents, audio_stream); |
michael@0 | 886 | |
michael@0 | 887 | // Now call CreateOffer as JS would |
michael@0 | 888 | pObserver->state = TestObserver::stateNoResponse; |
michael@0 | 889 | ASSERT_EQ(pc->CreateOffer(constraints), NS_OK); |
michael@0 | 890 | ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, |
michael@0 | 891 | kDefaultTimeout); |
michael@0 | 892 | ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); |
michael@0 | 893 | SDPSanityCheck(pObserver->lastString, sdpCheck, true); |
michael@0 | 894 | ASSERT_EQ(signaling_state(), endState); |
michael@0 | 895 | offer_ = pObserver->lastString; |
michael@0 | 896 | } |
michael@0 | 897 | |
michael@0 | 898 | void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer, |
michael@0 | 899 | uint32_t offerAnswerFlags, |
michael@0 | 900 | uint32_t sdpCheck = DONT_CHECK_AUDIO| |
michael@0 | 901 | DONT_CHECK_VIDEO| |
michael@0 | 902 | DONT_CHECK_DATA, |
michael@0 | 903 | PCImplSignalingState endState = |
michael@0 | 904 | PCImplSignalingState::SignalingHaveRemoteOffer) { |
michael@0 | 905 | |
michael@0 | 906 | uint32_t aHintContents = 0; |
michael@0 | 907 | if (offerAnswerFlags & ANSWER_AUDIO) { |
michael@0 | 908 | aHintContents |= DOMMediaStream::HINT_CONTENTS_AUDIO; |
michael@0 | 909 | } |
michael@0 | 910 | if (offerAnswerFlags & ANSWER_VIDEO) { |
michael@0 | 911 | aHintContents |= DOMMediaStream::HINT_CONTENTS_VIDEO; |
michael@0 | 912 | } |
michael@0 | 913 | AddStream(aHintContents); |
michael@0 | 914 | |
michael@0 | 915 | // Decide if streams are disabled for offer or answer |
michael@0 | 916 | // then perform SDP checking based on which stream disabled |
michael@0 | 917 | pObserver->state = TestObserver::stateNoResponse; |
michael@0 | 918 | ASSERT_EQ(pc->CreateAnswer(constraints), NS_OK); |
michael@0 | 919 | ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, |
michael@0 | 920 | kDefaultTimeout); |
michael@0 | 921 | ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); |
michael@0 | 922 | SDPSanityCheck(pObserver->lastString, sdpCheck, false); |
michael@0 | 923 | ASSERT_EQ(signaling_state(), endState); |
michael@0 | 924 | |
michael@0 | 925 | answer_ = pObserver->lastString; |
michael@0 | 926 | } |
michael@0 | 927 | |
michael@0 | 928 | // At present, we use the hints field in a stream to find and |
michael@0 | 929 | // remove it. This only works if the specified hints flags are |
michael@0 | 930 | // unique among all streams in the PeerConnection. This is not |
michael@0 | 931 | // generally true, and will need significant revision once |
michael@0 | 932 | // multiple streams are supported. |
michael@0 | 933 | void CreateOfferRemoveStream(sipcc::MediaConstraints& constraints, |
michael@0 | 934 | uint32_t hints, uint32_t sdpCheck) { |
michael@0 | 935 | |
michael@0 | 936 | domMediaStream_->SetHintContents(hints); |
michael@0 | 937 | |
michael@0 | 938 | // This currently "removes" a stream that has the same audio/video |
michael@0 | 939 | // hints as were passed in. |
michael@0 | 940 | // When complete RemoveStream will remove and entire stream and its tracks |
michael@0 | 941 | // not just disable a track as this is currently doing |
michael@0 | 942 | ASSERT_EQ(pc->RemoveStream(*domMediaStream_), NS_OK); |
michael@0 | 943 | |
michael@0 | 944 | // Now call CreateOffer as JS would |
michael@0 | 945 | pObserver->state = TestObserver::stateNoResponse; |
michael@0 | 946 | ASSERT_EQ(pc->CreateOffer(constraints), NS_OK); |
michael@0 | 947 | ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, |
michael@0 | 948 | kDefaultTimeout); |
michael@0 | 949 | ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess); |
michael@0 | 950 | SDPSanityCheck(pObserver->lastString, sdpCheck, true); |
michael@0 | 951 | offer_ = pObserver->lastString; |
michael@0 | 952 | } |
michael@0 | 953 | |
michael@0 | 954 | void SetRemote(TestObserver::Action action, std::string remote, |
michael@0 | 955 | bool ignoreError = false, |
michael@0 | 956 | PCImplSignalingState endState = |
michael@0 | 957 | PCImplSignalingState::SignalingInvalid) { |
michael@0 | 958 | |
michael@0 | 959 | if (endState == PCImplSignalingState::SignalingInvalid) { |
michael@0 | 960 | endState = (action == TestObserver::OFFER ? |
michael@0 | 961 | PCImplSignalingState::SignalingHaveRemoteOffer : |
michael@0 | 962 | PCImplSignalingState::SignalingStable); |
michael@0 | 963 | } |
michael@0 | 964 | |
michael@0 | 965 | pObserver->state = TestObserver::stateNoResponse; |
michael@0 | 966 | ASSERT_EQ(pc->SetRemoteDescription(action, remote.c_str()), NS_OK); |
michael@0 | 967 | ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, |
michael@0 | 968 | kDefaultTimeout); |
michael@0 | 969 | ASSERT_EQ(signaling_state(), endState); |
michael@0 | 970 | if (!ignoreError) { |
michael@0 | 971 | ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); |
michael@0 | 972 | } |
michael@0 | 973 | } |
michael@0 | 974 | |
michael@0 | 975 | void SetLocal(TestObserver::Action action, std::string local, |
michael@0 | 976 | bool ignoreError = false, |
michael@0 | 977 | PCImplSignalingState endState = |
michael@0 | 978 | PCImplSignalingState::SignalingInvalid) { |
michael@0 | 979 | |
michael@0 | 980 | if (endState == PCImplSignalingState::SignalingInvalid) { |
michael@0 | 981 | endState = (action == TestObserver::OFFER ? |
michael@0 | 982 | PCImplSignalingState::SignalingHaveLocalOffer : |
michael@0 | 983 | PCImplSignalingState::SignalingStable); |
michael@0 | 984 | } |
michael@0 | 985 | |
michael@0 | 986 | pObserver->state = TestObserver::stateNoResponse; |
michael@0 | 987 | ASSERT_EQ(pc->SetLocalDescription(action, local.c_str()), NS_OK); |
michael@0 | 988 | ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, |
michael@0 | 989 | kDefaultTimeout); |
michael@0 | 990 | ASSERT_EQ(signaling_state(), endState); |
michael@0 | 991 | if (!ignoreError) { |
michael@0 | 992 | ASSERT_EQ(pObserver->state, TestObserver::stateSuccess); |
michael@0 | 993 | } |
michael@0 | 994 | } |
michael@0 | 995 | |
michael@0 | 996 | void DoTrickleIce(ParsedSDP &sdp) { |
michael@0 | 997 | int expectAddIce = 0; |
michael@0 | 998 | pObserver->addIceSuccessCount = 0; |
michael@0 | 999 | for (std::multimap<int, std::string>::iterator it = |
michael@0 | 1000 | sdp.ice_candidates_.begin(); |
michael@0 | 1001 | it != sdp.ice_candidates_.end(); ++it) { |
michael@0 | 1002 | if ((*it).first != 0) { |
michael@0 | 1003 | std::cerr << "Adding trickle ICE candidate " << (*it).second |
michael@0 | 1004 | << std::endl; |
michael@0 | 1005 | ASSERT_TRUE(NS_SUCCEEDED(pc->AddIceCandidate((*it).second.c_str(), "", (*it).first))); |
michael@0 | 1006 | expectAddIce++; |
michael@0 | 1007 | } |
michael@0 | 1008 | } |
michael@0 | 1009 | ASSERT_TRUE_WAIT(pObserver->addIceSuccessCount == expectAddIce, |
michael@0 | 1010 | kDefaultTimeout); |
michael@0 | 1011 | } |
michael@0 | 1012 | |
michael@0 | 1013 | |
michael@0 | 1014 | void DoTrickleIceChrome(ParsedSDP &sdp) { |
michael@0 | 1015 | int expectAddIce = 0; |
michael@0 | 1016 | pObserver->addIceSuccessCount = 0; |
michael@0 | 1017 | for (std::multimap<int, std::string>::iterator it = |
michael@0 | 1018 | sdp.ice_candidates_.begin(); |
michael@0 | 1019 | it != sdp.ice_candidates_.end(); ++it) { |
michael@0 | 1020 | if ((*it).first != 0) { |
michael@0 | 1021 | std::string candidate = "a=" + (*it).second + "\r\n"; |
michael@0 | 1022 | std::cerr << "Adding trickle ICE candidate " << candidate << std::endl; |
michael@0 | 1023 | |
michael@0 | 1024 | ASSERT_TRUE(NS_SUCCEEDED(pc->AddIceCandidate(candidate.c_str(), "", (*it).first))); |
michael@0 | 1025 | expectAddIce++; |
michael@0 | 1026 | } |
michael@0 | 1027 | } |
michael@0 | 1028 | ASSERT_TRUE_WAIT(pObserver->addIceSuccessCount == expectAddIce, |
michael@0 | 1029 | kDefaultTimeout); |
michael@0 | 1030 | } |
michael@0 | 1031 | |
michael@0 | 1032 | |
michael@0 | 1033 | bool IceCompleted() { |
michael@0 | 1034 | return pc->IceConnectionState() == PCImplIceConnectionState::Connected; |
michael@0 | 1035 | } |
michael@0 | 1036 | |
michael@0 | 1037 | void AddIceCandidate(const char* candidate, const char* mid, unsigned short level, |
michael@0 | 1038 | bool expectSuccess) { |
michael@0 | 1039 | PCImplSignalingState endState = signaling_state(); |
michael@0 | 1040 | pObserver->state = TestObserver::stateNoResponse; |
michael@0 | 1041 | pc->AddIceCandidate(candidate, mid, level); |
michael@0 | 1042 | ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse, |
michael@0 | 1043 | kDefaultTimeout); |
michael@0 | 1044 | ASSERT_TRUE(pObserver->state == |
michael@0 | 1045 | expectSuccess ? TestObserver::stateSuccess : |
michael@0 | 1046 | TestObserver::stateError |
michael@0 | 1047 | ); |
michael@0 | 1048 | |
michael@0 | 1049 | // Verify that adding ICE candidates does not change the signaling state |
michael@0 | 1050 | ASSERT_EQ(signaling_state(), endState); |
michael@0 | 1051 | } |
michael@0 | 1052 | |
michael@0 | 1053 | int GetPacketsReceived(int stream) { |
michael@0 | 1054 | std::vector<DOMMediaStream *> streams = pObserver->GetStreams(); |
michael@0 | 1055 | |
michael@0 | 1056 | if ((int) streams.size() <= stream) { |
michael@0 | 1057 | return 0; |
michael@0 | 1058 | } |
michael@0 | 1059 | |
michael@0 | 1060 | return streams[stream]->GetStream()->AsSourceStream()->GetSegmentsAdded(); |
michael@0 | 1061 | } |
michael@0 | 1062 | |
michael@0 | 1063 | int GetPacketsSent(int stream) { |
michael@0 | 1064 | return static_cast<Fake_MediaStreamBase *>( |
michael@0 | 1065 | domMediaStream_->GetStream())->GetSegmentsAdded(); |
michael@0 | 1066 | } |
michael@0 | 1067 | |
michael@0 | 1068 | //Stops generating new audio data for transmission. |
michael@0 | 1069 | //Should be called before Cleanup of the peer connection. |
michael@0 | 1070 | void CloseSendStreams() { |
michael@0 | 1071 | static_cast<Fake_MediaStream*>( |
michael@0 | 1072 | domMediaStream_->GetStream())->StopStream(); |
michael@0 | 1073 | } |
michael@0 | 1074 | |
michael@0 | 1075 | //Stops pulling audio data off the receivers. |
michael@0 | 1076 | //Should be called before Cleanup of the peer connection. |
michael@0 | 1077 | void CloseReceiveStreams() { |
michael@0 | 1078 | std::vector<DOMMediaStream *> streams = |
michael@0 | 1079 | pObserver->GetStreams(); |
michael@0 | 1080 | for (size_t i = 0; i < streams.size(); i++) { |
michael@0 | 1081 | streams[i]->GetStream()->AsSourceStream()->StopStream(); |
michael@0 | 1082 | } |
michael@0 | 1083 | } |
michael@0 | 1084 | |
michael@0 | 1085 | mozilla::RefPtr<mozilla::MediaPipeline> GetMediaPipeline( |
michael@0 | 1086 | bool local, int stream, int track) { |
michael@0 | 1087 | sipcc::SourceStreamInfo *streamInfo; |
michael@0 | 1088 | |
michael@0 | 1089 | if (local) { |
michael@0 | 1090 | streamInfo = pc->media()->GetLocalStream(stream); |
michael@0 | 1091 | } else { |
michael@0 | 1092 | streamInfo = pc->media()->GetRemoteStream(stream); |
michael@0 | 1093 | } |
michael@0 | 1094 | |
michael@0 | 1095 | if (!streamInfo) { |
michael@0 | 1096 | return nullptr; |
michael@0 | 1097 | } |
michael@0 | 1098 | |
michael@0 | 1099 | const auto &pipelines = streamInfo->GetPipelines(); |
michael@0 | 1100 | auto it = pipelines.find(track); |
michael@0 | 1101 | return (it == pipelines.end())? nullptr : it->second; |
michael@0 | 1102 | } |
michael@0 | 1103 | |
michael@0 | 1104 | void CheckMediaPipeline(int stream, int track, uint32_t flags, |
michael@0 | 1105 | VideoSessionConduit::FrameRequestType frameRequestMethod = |
michael@0 | 1106 | VideoSessionConduit::FrameRequestNone) { |
michael@0 | 1107 | |
michael@0 | 1108 | std::cout << name << ": Checking media pipeline settings for " |
michael@0 | 1109 | << ((flags & PIPELINE_LOCAL) ? "local " : "remote ") |
michael@0 | 1110 | << ((flags & PIPELINE_SEND) ? "sending " : "receiving ") |
michael@0 | 1111 | << ((flags & PIPELINE_VIDEO) ? "video" : "audio") |
michael@0 | 1112 | << " pipeline (stream " << stream |
michael@0 | 1113 | << ", track " << track << "); expect " |
michael@0 | 1114 | << ((flags & PIPELINE_RTCP_MUX) ? "MUX, " : "no MUX, ") |
michael@0 | 1115 | << ((flags & PIPELINE_RTCP_NACK) ? "NACK." : "no NACK.") |
michael@0 | 1116 | << std::endl; |
michael@0 | 1117 | |
michael@0 | 1118 | mozilla::RefPtr<mozilla::MediaPipeline> pipeline = |
michael@0 | 1119 | GetMediaPipeline((flags & PIPELINE_LOCAL), stream, track); |
michael@0 | 1120 | ASSERT_TRUE(pipeline); |
michael@0 | 1121 | ASSERT_EQ(pipeline->IsDoingRtcpMux(), !!(flags & PIPELINE_RTCP_MUX)); |
michael@0 | 1122 | // We cannot yet test send/recv with video. |
michael@0 | 1123 | if (!(flags & PIPELINE_VIDEO)) { |
michael@0 | 1124 | if (flags & PIPELINE_SEND) { |
michael@0 | 1125 | ASSERT_TRUE_WAIT(pipeline->rtp_packets_sent() >= 40 && |
michael@0 | 1126 | pipeline->rtcp_packets_received() >= 1, |
michael@0 | 1127 | kDefaultTimeout); |
michael@0 | 1128 | ASSERT_GE(pipeline->rtp_packets_sent(), 40); |
michael@0 | 1129 | ASSERT_GE(pipeline->rtcp_packets_received(), 1); |
michael@0 | 1130 | } else { |
michael@0 | 1131 | ASSERT_TRUE_WAIT(pipeline->rtp_packets_received() >= 40 && |
michael@0 | 1132 | pipeline->rtcp_packets_sent() >= 1, |
michael@0 | 1133 | kDefaultTimeout); |
michael@0 | 1134 | ASSERT_GE(pipeline->rtp_packets_received(), 40); |
michael@0 | 1135 | ASSERT_GE(pipeline->rtcp_packets_sent(), 1); |
michael@0 | 1136 | } |
michael@0 | 1137 | } |
michael@0 | 1138 | |
michael@0 | 1139 | |
michael@0 | 1140 | // Check feedback method for video |
michael@0 | 1141 | if (flags & PIPELINE_VIDEO) { |
michael@0 | 1142 | mozilla::MediaSessionConduit *conduit = pipeline->Conduit(); |
michael@0 | 1143 | ASSERT_TRUE(conduit); |
michael@0 | 1144 | ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO); |
michael@0 | 1145 | mozilla::VideoSessionConduit *video_conduit = |
michael@0 | 1146 | static_cast<mozilla::VideoSessionConduit*>(conduit); |
michael@0 | 1147 | ASSERT_EQ(!!(flags & PIPELINE_RTCP_NACK), |
michael@0 | 1148 | video_conduit->UsingNackBasic()); |
michael@0 | 1149 | ASSERT_EQ(frameRequestMethod, video_conduit->FrameRequestMethod()); |
michael@0 | 1150 | } |
michael@0 | 1151 | } |
michael@0 | 1152 | |
michael@0 | 1153 | public: |
michael@0 | 1154 | mozilla::RefPtr<sipcc::PeerConnectionImpl> pc; |
michael@0 | 1155 | nsRefPtr<TestObserver> pObserver; |
michael@0 | 1156 | char* offer_; |
michael@0 | 1157 | char* answer_; |
michael@0 | 1158 | nsRefPtr<DOMMediaStream> domMediaStream_; |
michael@0 | 1159 | sipcc::IceConfiguration cfg_; |
michael@0 | 1160 | const std::string name; |
michael@0 | 1161 | |
michael@0 | 1162 | private: |
michael@0 | 1163 | void SDPSanityCheck(std::string sdp, uint32_t flags, bool offer) |
michael@0 | 1164 | { |
michael@0 | 1165 | ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess); |
michael@0 | 1166 | ASSERT_NE(sdp.find("v=0"), std::string::npos); |
michael@0 | 1167 | ASSERT_NE(sdp.find("c=IN IP4"), std::string::npos); |
michael@0 | 1168 | ASSERT_NE(sdp.find("a=fingerprint:sha-256"), std::string::npos); |
michael@0 | 1169 | |
michael@0 | 1170 | std::cout << name << ": SDPSanityCheck flags for " |
michael@0 | 1171 | << (offer ? "offer" : "answer") |
michael@0 | 1172 | << " = " << std::hex << std::showbase |
michael@0 | 1173 | << flags << std::dec |
michael@0 | 1174 | |
michael@0 | 1175 | << ((flags & SHOULD_SEND_AUDIO)?" SHOULD_SEND_AUDIO":"") |
michael@0 | 1176 | << ((flags & SHOULD_RECV_AUDIO)?" SHOULD_RECV_AUDIO":"") |
michael@0 | 1177 | << ((flags & SHOULD_INACTIVE_AUDIO)?" SHOULD_INACTIVE_AUDIO":"") |
michael@0 | 1178 | << ((flags & SHOULD_REJECT_AUDIO)?" SHOULD_REJECT_AUDIO":"") |
michael@0 | 1179 | << ((flags & SHOULD_OMIT_AUDIO)?" SHOULD_OMIT_AUDIO":"") |
michael@0 | 1180 | << ((flags & DONT_CHECK_AUDIO)?" DONT_CHECK_AUDIO":"") |
michael@0 | 1181 | |
michael@0 | 1182 | << ((flags & SHOULD_SEND_VIDEO)?" SHOULD_SEND_VIDEO":"") |
michael@0 | 1183 | << ((flags & SHOULD_RECV_VIDEO)?" SHOULD_RECV_VIDEO":"") |
michael@0 | 1184 | << ((flags & SHOULD_INACTIVE_VIDEO)?" SHOULD_INACTIVE_VIDEO":"") |
michael@0 | 1185 | << ((flags & SHOULD_REJECT_VIDEO)?" SHOULD_REJECT_VIDEO":"") |
michael@0 | 1186 | << ((flags & SHOULD_OMIT_VIDEO)?" SHOULD_OMIT_VIDEO":"") |
michael@0 | 1187 | << ((flags & DONT_CHECK_VIDEO)?" DONT_CHECK_VIDEO":"") |
michael@0 | 1188 | |
michael@0 | 1189 | << ((flags & SHOULD_INCLUDE_DATA)?" SHOULD_INCLUDE_DATA":"") |
michael@0 | 1190 | << ((flags & DONT_CHECK_DATA)?" DONT_CHECK_DATA":"") |
michael@0 | 1191 | << std::endl; |
michael@0 | 1192 | |
michael@0 | 1193 | switch(flags & AUDIO_FLAGS) { |
michael@0 | 1194 | case 0: |
michael@0 | 1195 | ASSERT_EQ(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1196 | break; |
michael@0 | 1197 | case SHOULD_CHECK_AUDIO: |
michael@0 | 1198 | ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1199 | if (offer) { |
michael@0 | 1200 | ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); |
michael@0 | 1201 | } |
michael@0 | 1202 | break; |
michael@0 | 1203 | case SHOULD_SEND_AUDIO: |
michael@0 | 1204 | ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1205 | ASSERT_NE(sdp.find(" 0-15\r\na=sendonly"), std::string::npos); |
michael@0 | 1206 | if (offer) { |
michael@0 | 1207 | ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); |
michael@0 | 1208 | } |
michael@0 | 1209 | break; |
michael@0 | 1210 | case SHOULD_RECV_AUDIO: |
michael@0 | 1211 | ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1212 | ASSERT_NE(sdp.find(" 0-15\r\na=recvonly"), std::string::npos); |
michael@0 | 1213 | if (offer) { |
michael@0 | 1214 | ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); |
michael@0 | 1215 | } |
michael@0 | 1216 | break; |
michael@0 | 1217 | case SHOULD_SENDRECV_AUDIO: |
michael@0 | 1218 | ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1219 | ASSERT_NE(sdp.find(" 0-15\r\na=sendrecv"), std::string::npos); |
michael@0 | 1220 | if (offer) { |
michael@0 | 1221 | ASSERT_NE(sdp.find("a=rtpmap:0 PCMU/8000"), std::string::npos); |
michael@0 | 1222 | } |
michael@0 | 1223 | break; |
michael@0 | 1224 | case SHOULD_INACTIVE_AUDIO: |
michael@0 | 1225 | ASSERT_NE(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1226 | ASSERT_NE(sdp.find(" 0-15\r\na=inactive"), std::string::npos); |
michael@0 | 1227 | break; |
michael@0 | 1228 | case SHOULD_REJECT_AUDIO: |
michael@0 | 1229 | ASSERT_EQ(sdp.find("a=rtpmap:109 opus/48000"), std::string::npos); |
michael@0 | 1230 | ASSERT_NE(sdp.find("m=audio 0 "), std::string::npos); |
michael@0 | 1231 | break; |
michael@0 | 1232 | case SHOULD_OMIT_AUDIO: |
michael@0 | 1233 | ASSERT_EQ(sdp.find("m=audio"), std::string::npos); |
michael@0 | 1234 | break; |
michael@0 | 1235 | case DONT_CHECK_AUDIO: |
michael@0 | 1236 | break; |
michael@0 | 1237 | default: |
michael@0 | 1238 | ASSERT_FALSE("Missing case in switch statement"); |
michael@0 | 1239 | } |
michael@0 | 1240 | |
michael@0 | 1241 | switch(flags & VIDEO_FLAGS) { |
michael@0 | 1242 | case 0: |
michael@0 | 1243 | ASSERT_EQ(sdp.find("a=rtpmap:120 VP8/90000"), std::string::npos); |
michael@0 | 1244 | break; |
michael@0 | 1245 | case SHOULD_CHECK_VIDEO: |
michael@0 | 1246 | ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000"), std::string::npos); |
michael@0 | 1247 | break; |
michael@0 | 1248 | case SHOULD_SEND_VIDEO: |
michael@0 | 1249 | ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=sendonly"), |
michael@0 | 1250 | std::string::npos); |
michael@0 | 1251 | break; |
michael@0 | 1252 | case SHOULD_RECV_VIDEO: |
michael@0 | 1253 | ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=recvonly"), |
michael@0 | 1254 | std::string::npos); |
michael@0 | 1255 | break; |
michael@0 | 1256 | case SHOULD_SENDRECV_VIDEO: |
michael@0 | 1257 | ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=sendrecv"), |
michael@0 | 1258 | std::string::npos); |
michael@0 | 1259 | break; |
michael@0 | 1260 | case SHOULD_INACTIVE_VIDEO: |
michael@0 | 1261 | ASSERT_NE(sdp.find("a=rtpmap:120 VP8/90000\r\na=inactive"), |
michael@0 | 1262 | std::string::npos); |
michael@0 | 1263 | break; |
michael@0 | 1264 | case SHOULD_REJECT_VIDEO: |
michael@0 | 1265 | ASSERT_NE(sdp.find("m=video 0 "), std::string::npos); |
michael@0 | 1266 | break; |
michael@0 | 1267 | case SHOULD_OMIT_VIDEO: |
michael@0 | 1268 | ASSERT_EQ(sdp.find("m=video"), std::string::npos); |
michael@0 | 1269 | break; |
michael@0 | 1270 | case DONT_CHECK_VIDEO: |
michael@0 | 1271 | break; |
michael@0 | 1272 | default: |
michael@0 | 1273 | ASSERT_FALSE("Missing case in switch statement"); |
michael@0 | 1274 | } |
michael@0 | 1275 | |
michael@0 | 1276 | if (flags & SHOULD_INCLUDE_DATA) { |
michael@0 | 1277 | ASSERT_NE(sdp.find("m=application"), std::string::npos); |
michael@0 | 1278 | } else if (!(flags & DONT_CHECK_DATA)) { |
michael@0 | 1279 | ASSERT_EQ(sdp.find("m=application"), std::string::npos); |
michael@0 | 1280 | } |
michael@0 | 1281 | } |
michael@0 | 1282 | }; |
michael@0 | 1283 | |
michael@0 | 1284 | class SignalingEnvironment : public ::testing::Environment { |
michael@0 | 1285 | public: |
michael@0 | 1286 | void TearDown() { |
michael@0 | 1287 | // Signaling is shut down in XPCOM shutdown |
michael@0 | 1288 | } |
michael@0 | 1289 | }; |
michael@0 | 1290 | |
michael@0 | 1291 | class SignalingAgentTest : public ::testing::Test { |
michael@0 | 1292 | public: |
michael@0 | 1293 | static void SetUpTestCase() { |
michael@0 | 1294 | } |
michael@0 | 1295 | |
michael@0 | 1296 | void TearDown() { |
michael@0 | 1297 | // Delete all the agents. |
michael@0 | 1298 | for (size_t i=0; i < agents_.size(); i++) { |
michael@0 | 1299 | delete agents_[i]; |
michael@0 | 1300 | } |
michael@0 | 1301 | } |
michael@0 | 1302 | |
michael@0 | 1303 | bool CreateAgent() { |
michael@0 | 1304 | return CreateAgent(g_stun_server_address, g_stun_server_port); |
michael@0 | 1305 | } |
michael@0 | 1306 | |
michael@0 | 1307 | bool CreateAgent(const std::string stun_addr, uint16_t stun_port, |
michael@0 | 1308 | bool wait_for_gather = true) { |
michael@0 | 1309 | ScopedDeletePtr<SignalingAgent> agent( |
michael@0 | 1310 | new SignalingAgent("agent", stun_addr, stun_port)); |
michael@0 | 1311 | |
michael@0 | 1312 | agent->Init(gMainThread); |
michael@0 | 1313 | |
michael@0 | 1314 | if (wait_for_gather) { |
michael@0 | 1315 | if (!agent->WaitForGatherAllowFail()) |
michael@0 | 1316 | return false; |
michael@0 | 1317 | } |
michael@0 | 1318 | |
michael@0 | 1319 | agents_.push_back(agent.forget()); |
michael@0 | 1320 | |
michael@0 | 1321 | return true; |
michael@0 | 1322 | } |
michael@0 | 1323 | |
michael@0 | 1324 | void CreateAgentNoInit() { |
michael@0 | 1325 | ScopedDeletePtr<SignalingAgent> agent(new SignalingAgent("agent")); |
michael@0 | 1326 | agents_.push_back(agent.forget()); |
michael@0 | 1327 | } |
michael@0 | 1328 | |
michael@0 | 1329 | SignalingAgent *agent(size_t i) { |
michael@0 | 1330 | return agents_[i]; |
michael@0 | 1331 | } |
michael@0 | 1332 | |
michael@0 | 1333 | private: |
michael@0 | 1334 | std::vector<SignalingAgent *> agents_; |
michael@0 | 1335 | }; |
michael@0 | 1336 | |
michael@0 | 1337 | |
michael@0 | 1338 | class SignalingTest : public ::testing::Test { |
michael@0 | 1339 | public: |
michael@0 | 1340 | SignalingTest() |
michael@0 | 1341 | : init_(false), |
michael@0 | 1342 | a1_(nullptr), |
michael@0 | 1343 | a2_(nullptr), |
michael@0 | 1344 | wait_for_gather_(true), |
michael@0 | 1345 | stun_addr_(g_stun_server_address), |
michael@0 | 1346 | stun_port_(g_stun_server_port) {} |
michael@0 | 1347 | |
michael@0 | 1348 | SignalingTest(const std::string& stun_addr, uint16_t stun_port) |
michael@0 | 1349 | : a1_(nullptr), |
michael@0 | 1350 | a2_(nullptr), |
michael@0 | 1351 | wait_for_gather_(true), |
michael@0 | 1352 | stun_addr_(stun_addr), |
michael@0 | 1353 | stun_port_(stun_port) {} |
michael@0 | 1354 | |
michael@0 | 1355 | static void SetUpTestCase() { |
michael@0 | 1356 | } |
michael@0 | 1357 | |
michael@0 | 1358 | void EnsureInit() { |
michael@0 | 1359 | |
michael@0 | 1360 | if (init_) |
michael@0 | 1361 | return; |
michael@0 | 1362 | |
michael@0 | 1363 | a1_ = new SignalingAgent(callerName, stun_addr_, stun_port_); |
michael@0 | 1364 | a2_ = new SignalingAgent(calleeName, stun_addr_, stun_port_); |
michael@0 | 1365 | |
michael@0 | 1366 | a1_->Init(gMainThread); |
michael@0 | 1367 | a2_->Init(gMainThread); |
michael@0 | 1368 | |
michael@0 | 1369 | if (wait_for_gather_) { |
michael@0 | 1370 | WaitForGather(); |
michael@0 | 1371 | } |
michael@0 | 1372 | } |
michael@0 | 1373 | |
michael@0 | 1374 | void WaitForGather() { |
michael@0 | 1375 | a1_->WaitForGather(); |
michael@0 | 1376 | a2_->WaitForGather(); |
michael@0 | 1377 | } |
michael@0 | 1378 | |
michael@0 | 1379 | static void TearDownTestCase() { |
michael@0 | 1380 | } |
michael@0 | 1381 | |
michael@0 | 1382 | void CreateOffer(sipcc::MediaConstraints& constraints, |
michael@0 | 1383 | uint32_t offerFlags, uint32_t sdpCheck) { |
michael@0 | 1384 | EnsureInit(); |
michael@0 | 1385 | a1_->CreateOffer(constraints, offerFlags, sdpCheck); |
michael@0 | 1386 | } |
michael@0 | 1387 | |
michael@0 | 1388 | void CreateSetOffer(sipcc::MediaConstraints& constraints, uint32_t sdpCheck) { |
michael@0 | 1389 | EnsureInit(); |
michael@0 | 1390 | a1_->CreateOffer(constraints, OFFER_AV, sdpCheck); |
michael@0 | 1391 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1392 | } |
michael@0 | 1393 | |
michael@0 | 1394 | void OfferAnswer(sipcc::MediaConstraints& aconstraints, |
michael@0 | 1395 | sipcc::MediaConstraints& bconstraints, |
michael@0 | 1396 | uint32_t offerAnswerFlags, |
michael@0 | 1397 | bool finishAfterAnswer, uint32_t offerSdpCheck, |
michael@0 | 1398 | uint32_t answerSdpCheck) { |
michael@0 | 1399 | EnsureInit(); |
michael@0 | 1400 | a1_->CreateOffer(aconstraints, offerAnswerFlags, offerSdpCheck); |
michael@0 | 1401 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1402 | a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1403 | a2_->CreateAnswer(bconstraints, a1_->offer(), |
michael@0 | 1404 | offerAnswerFlags, answerSdpCheck); |
michael@0 | 1405 | if(true == finishAfterAnswer) { |
michael@0 | 1406 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1407 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1408 | |
michael@0 | 1409 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1410 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1411 | } |
michael@0 | 1412 | } |
michael@0 | 1413 | |
michael@0 | 1414 | void OfferModifiedAnswer(sipcc::MediaConstraints& aconstraints, |
michael@0 | 1415 | sipcc::MediaConstraints& bconstraints, |
michael@0 | 1416 | uint32_t offerSdpCheck, uint32_t answerSdpCheck) { |
michael@0 | 1417 | EnsureInit(); |
michael@0 | 1418 | a1_->CreateOffer(aconstraints, OFFER_AUDIO, offerSdpCheck); |
michael@0 | 1419 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1420 | a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1421 | a2_->CreateAnswer(bconstraints, a1_->offer(), OFFER_AUDIO | ANSWER_AUDIO, |
michael@0 | 1422 | answerSdpCheck); |
michael@0 | 1423 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1424 | ParsedSDP sdpWrapper(a2_->answer()); |
michael@0 | 1425 | sdpWrapper.ReplaceLine("m=audio", "m=audio 65375 RTP/SAVPF 109 8 101\r\n"); |
michael@0 | 1426 | sdpWrapper.AddLine("a=rtpmap:8 PCMA/8000\r\n"); |
michael@0 | 1427 | std::cout << "Modified SDP " << std::endl |
michael@0 | 1428 | << indent(sdpWrapper.getSdp()) << std::endl; |
michael@0 | 1429 | a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp()); |
michael@0 | 1430 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1431 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1432 | } |
michael@0 | 1433 | |
michael@0 | 1434 | void OfferAnswerTrickle(sipcc::MediaConstraints& aconstraints, |
michael@0 | 1435 | sipcc::MediaConstraints& bconstraints, |
michael@0 | 1436 | uint32_t offerSdpCheck, uint32_t answerSdpCheck) { |
michael@0 | 1437 | EnsureInit(); |
michael@0 | 1438 | a1_->CreateOffer(aconstraints, OFFER_AV, offerSdpCheck); |
michael@0 | 1439 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1440 | ParsedSDP a1_offer(a1_->offer()); |
michael@0 | 1441 | a2_->SetRemote(TestObserver::OFFER, a1_offer.sdp_without_ice_); |
michael@0 | 1442 | a2_->CreateAnswer(bconstraints, a1_offer.sdp_without_ice_, |
michael@0 | 1443 | OFFER_AV|ANSWER_AV, answerSdpCheck); |
michael@0 | 1444 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1445 | ParsedSDP a2_answer(a2_->answer()); |
michael@0 | 1446 | a1_->SetRemote(TestObserver::ANSWER, a2_answer.sdp_without_ice_); |
michael@0 | 1447 | // Now set the trickle ICE candidates |
michael@0 | 1448 | a1_->DoTrickleIce(a2_answer); |
michael@0 | 1449 | a2_->DoTrickleIce(a1_offer); |
michael@0 | 1450 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1451 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1452 | } |
michael@0 | 1453 | |
michael@0 | 1454 | |
michael@0 | 1455 | void OfferAnswerTrickleChrome(sipcc::MediaConstraints& aconstraints, |
michael@0 | 1456 | sipcc::MediaConstraints& bconstraints, |
michael@0 | 1457 | uint32_t offerSdpCheck, uint32_t answerSdpCheck) { |
michael@0 | 1458 | EnsureInit(); |
michael@0 | 1459 | a1_->CreateOffer(aconstraints, OFFER_AV, offerSdpCheck); |
michael@0 | 1460 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1461 | ParsedSDP a1_offer(a1_->offer()); |
michael@0 | 1462 | a2_->SetRemote(TestObserver::OFFER, a1_offer.sdp_without_ice_); |
michael@0 | 1463 | a2_->CreateAnswer(bconstraints, a1_offer.sdp_without_ice_, |
michael@0 | 1464 | OFFER_AV|ANSWER_AV, answerSdpCheck); |
michael@0 | 1465 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1466 | ParsedSDP a2_answer(a2_->answer()); |
michael@0 | 1467 | a1_->SetRemote(TestObserver::ANSWER, a2_answer.sdp_without_ice_); |
michael@0 | 1468 | // Now set the trickle ICE candidates |
michael@0 | 1469 | a1_->DoTrickleIceChrome(a2_answer); |
michael@0 | 1470 | a2_->DoTrickleIceChrome(a1_offer); |
michael@0 | 1471 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1472 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1473 | } |
michael@0 | 1474 | |
michael@0 | 1475 | void CreateOfferRemoveStream(sipcc::MediaConstraints& constraints, |
michael@0 | 1476 | uint32_t hints, uint32_t sdpCheck) { |
michael@0 | 1477 | EnsureInit(); |
michael@0 | 1478 | sipcc::MediaConstraints aconstraints; |
michael@0 | 1479 | aconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1480 | aconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1481 | a1_->CreateOffer(aconstraints, OFFER_AV, SHOULD_SENDRECV_AV ); |
michael@0 | 1482 | a1_->CreateOfferRemoveStream(constraints, hints, sdpCheck); |
michael@0 | 1483 | } |
michael@0 | 1484 | |
michael@0 | 1485 | void CreateOfferAudioOnly(sipcc::MediaConstraints& constraints, |
michael@0 | 1486 | uint32_t sdpCheck) { |
michael@0 | 1487 | EnsureInit(); |
michael@0 | 1488 | a1_->CreateOffer(constraints, OFFER_AUDIO, sdpCheck); |
michael@0 | 1489 | } |
michael@0 | 1490 | |
michael@0 | 1491 | void CreateOfferAddCandidate(sipcc::MediaConstraints& constraints, |
michael@0 | 1492 | const char * candidate, const char * mid, |
michael@0 | 1493 | unsigned short level, uint32_t sdpCheck) { |
michael@0 | 1494 | EnsureInit(); |
michael@0 | 1495 | a1_->CreateOffer(constraints, OFFER_AV, sdpCheck); |
michael@0 | 1496 | a1_->AddIceCandidate(candidate, mid, level, true); |
michael@0 | 1497 | } |
michael@0 | 1498 | |
michael@0 | 1499 | void AddIceCandidateEarly(const char * candidate, const char * mid, |
michael@0 | 1500 | unsigned short level) { |
michael@0 | 1501 | EnsureInit(); |
michael@0 | 1502 | a1_->AddIceCandidate(candidate, mid, level, false); |
michael@0 | 1503 | } |
michael@0 | 1504 | |
michael@0 | 1505 | void CheckRtcpFbSdp(const std::string &sdp, |
michael@0 | 1506 | const std::set<std::string>& expected) { |
michael@0 | 1507 | |
michael@0 | 1508 | std::set<std::string>::const_iterator it; |
michael@0 | 1509 | |
michael@0 | 1510 | // Iterate through the list of expected feedback types and ensure |
michael@0 | 1511 | // that none of them are missing. |
michael@0 | 1512 | for (it = expected.begin(); it != expected.end(); ++it) { |
michael@0 | 1513 | std::string attr = std::string("\r\na=rtcp-fb:120 ") + (*it) + "\r\n"; |
michael@0 | 1514 | std::cout << " - Checking for a=rtcp-fb: '" << *it << "'" << std::endl; |
michael@0 | 1515 | ASSERT_NE(sdp.find(attr), std::string::npos); |
michael@0 | 1516 | } |
michael@0 | 1517 | |
michael@0 | 1518 | // Iterate through all of the rtcp-fb lines in the SDP and ensure |
michael@0 | 1519 | // that all of them are expected. |
michael@0 | 1520 | ParsedSDP sdpWrapper(sdp); |
michael@0 | 1521 | std::vector<std::string> values = sdpWrapper.GetLines("a=rtcp-fb:120"); |
michael@0 | 1522 | std::vector<std::string>::iterator it2; |
michael@0 | 1523 | for (it2 = values.begin(); it2 != values.end(); ++it2) { |
michael@0 | 1524 | std::cout << " - Verifying that rtcp-fb is okay: '" << *it2 |
michael@0 | 1525 | << "'" << std::endl; |
michael@0 | 1526 | ASSERT_NE(0U, expected.count(*it2)); |
michael@0 | 1527 | } |
michael@0 | 1528 | } |
michael@0 | 1529 | |
michael@0 | 1530 | void TestRtcpFb(const std::set<std::string>& feedback, |
michael@0 | 1531 | uint32_t rtcpFbFlags, |
michael@0 | 1532 | VideoSessionConduit::FrameRequestType frameRequestMethod) { |
michael@0 | 1533 | EnsureInit(); |
michael@0 | 1534 | sipcc::MediaConstraints constraints; |
michael@0 | 1535 | |
michael@0 | 1536 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
michael@0 | 1537 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 1538 | |
michael@0 | 1539 | ParsedSDP sdpWrapper(a1_->offer()); |
michael@0 | 1540 | |
michael@0 | 1541 | // Strip out any existing rtcp-fb lines |
michael@0 | 1542 | sdpWrapper.DeleteAllLines("a=rtcp-fb:120"); |
michael@0 | 1543 | |
michael@0 | 1544 | // Add rtcp-fb lines for the desired feedback types |
michael@0 | 1545 | // We know that the video section is generated second (last), |
michael@0 | 1546 | // so appending these to the end of the SDP has the desired effect. |
michael@0 | 1547 | std::set<std::string>::const_iterator it; |
michael@0 | 1548 | for (it = feedback.begin(); it != feedback.end(); ++it) { |
michael@0 | 1549 | sdpWrapper.AddLine(std::string("a=rtcp-fb:120 ") + (*it) + "\r\n"); |
michael@0 | 1550 | } |
michael@0 | 1551 | |
michael@0 | 1552 | std::cout << "Modified SDP " << std::endl |
michael@0 | 1553 | << indent(sdpWrapper.getSdp()) << std::endl; |
michael@0 | 1554 | |
michael@0 | 1555 | // Double-check that the offered SDP matches what we expect |
michael@0 | 1556 | CheckRtcpFbSdp(sdpWrapper.getSdp(), feedback); |
michael@0 | 1557 | |
michael@0 | 1558 | a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp()); |
michael@0 | 1559 | a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); |
michael@0 | 1560 | |
michael@0 | 1561 | CheckRtcpFbSdp(a2_->answer(), feedback); |
michael@0 | 1562 | |
michael@0 | 1563 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1564 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 1565 | |
michael@0 | 1566 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1567 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 1568 | |
michael@0 | 1569 | a1_->CloseSendStreams(); |
michael@0 | 1570 | a1_->CloseReceiveStreams(); |
michael@0 | 1571 | a2_->CloseSendStreams(); |
michael@0 | 1572 | a2_->CloseReceiveStreams(); |
michael@0 | 1573 | |
michael@0 | 1574 | // Check caller video settings for remote pipeline |
michael@0 | 1575 | a1_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | |
michael@0 | 1576 | PIPELINE_SEND | PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod); |
michael@0 | 1577 | |
michael@0 | 1578 | // Check callee video settings for remote pipeline |
michael@0 | 1579 | a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | |
michael@0 | 1580 | PIPELINE_VIDEO | rtcpFbFlags, frameRequestMethod); |
michael@0 | 1581 | } |
michael@0 | 1582 | |
michael@0 | 1583 | void SetTestStunServer() { |
michael@0 | 1584 | stun_addr_ = TestStunServer::GetInstance()->addr(); |
michael@0 | 1585 | stun_port_ = TestStunServer::GetInstance()->port(); |
michael@0 | 1586 | |
michael@0 | 1587 | TestStunServer::GetInstance()->SetActive(false); |
michael@0 | 1588 | TestStunServer::GetInstance()->SetResponseAddr( |
michael@0 | 1589 | kBogusSrflxAddress, kBogusSrflxPort); |
michael@0 | 1590 | } |
michael@0 | 1591 | |
michael@0 | 1592 | // Check max-fs and max-fr in SDP |
michael@0 | 1593 | void CheckMaxFsFrSdp(const std::string sdp, |
michael@0 | 1594 | int format, |
michael@0 | 1595 | int max_fs, |
michael@0 | 1596 | int max_fr) { |
michael@0 | 1597 | ParsedSDP sdpWrapper(sdp); |
michael@0 | 1598 | std::stringstream ss; |
michael@0 | 1599 | ss << "a=fmtp:" << format; |
michael@0 | 1600 | std::vector<std::string> lines = sdpWrapper.GetLines(ss.str()); |
michael@0 | 1601 | |
michael@0 | 1602 | // Both max-fs and max-fr not exist |
michael@0 | 1603 | if (lines.empty()) { |
michael@0 | 1604 | ASSERT_EQ(max_fs, 0); |
michael@0 | 1605 | ASSERT_EQ(max_fr, 0); |
michael@0 | 1606 | return; |
michael@0 | 1607 | } |
michael@0 | 1608 | |
michael@0 | 1609 | // At most one instance allowed for each format |
michael@0 | 1610 | ASSERT_EQ(lines.size(), 1U); |
michael@0 | 1611 | |
michael@0 | 1612 | std::string line = lines.front(); |
michael@0 | 1613 | |
michael@0 | 1614 | // Make sure that max-fs doesn't exist |
michael@0 | 1615 | if (max_fs == 0) { |
michael@0 | 1616 | ASSERT_EQ(line.find("max-fs="), std::string::npos); |
michael@0 | 1617 | } |
michael@0 | 1618 | // Check max-fs value |
michael@0 | 1619 | if (max_fs > 0) { |
michael@0 | 1620 | std::stringstream ss; |
michael@0 | 1621 | ss << "max-fs=" << max_fs; |
michael@0 | 1622 | ASSERT_NE(line.find(ss.str()), std::string::npos); |
michael@0 | 1623 | } |
michael@0 | 1624 | // Make sure that max-fr doesn't exist |
michael@0 | 1625 | if (max_fr == 0) { |
michael@0 | 1626 | ASSERT_EQ(line.find("max-fr="), std::string::npos); |
michael@0 | 1627 | } |
michael@0 | 1628 | // Check max-fr value |
michael@0 | 1629 | if (max_fr > 0) { |
michael@0 | 1630 | std::stringstream ss; |
michael@0 | 1631 | ss << "max-fr=" << max_fr; |
michael@0 | 1632 | ASSERT_NE(line.find(ss.str()), std::string::npos); |
michael@0 | 1633 | } |
michael@0 | 1634 | } |
michael@0 | 1635 | |
michael@0 | 1636 | protected: |
michael@0 | 1637 | bool init_; |
michael@0 | 1638 | ScopedDeletePtr<SignalingAgent> a1_; // Canonically "caller" |
michael@0 | 1639 | ScopedDeletePtr<SignalingAgent> a2_; // Canonically "callee" |
michael@0 | 1640 | bool wait_for_gather_; |
michael@0 | 1641 | std::string stun_addr_; |
michael@0 | 1642 | uint16_t stun_port_; |
michael@0 | 1643 | }; |
michael@0 | 1644 | |
michael@0 | 1645 | static void SetIntPrefOnMainThread(nsCOMPtr<nsIPrefBranch> prefs, |
michael@0 | 1646 | const char *pref_name, |
michael@0 | 1647 | int new_value) { |
michael@0 | 1648 | MOZ_ASSERT(NS_IsMainThread()); |
michael@0 | 1649 | prefs->SetIntPref(pref_name, new_value); |
michael@0 | 1650 | } |
michael@0 | 1651 | |
michael@0 | 1652 | static void SetMaxFsFr(nsCOMPtr<nsIPrefBranch> prefs, |
michael@0 | 1653 | int max_fs, |
michael@0 | 1654 | int max_fr) { |
michael@0 | 1655 | gMainThread->Dispatch( |
michael@0 | 1656 | WrapRunnableNM(SetIntPrefOnMainThread, |
michael@0 | 1657 | prefs, |
michael@0 | 1658 | "media.navigator.video.max_fs", |
michael@0 | 1659 | max_fs), |
michael@0 | 1660 | NS_DISPATCH_SYNC); |
michael@0 | 1661 | |
michael@0 | 1662 | gMainThread->Dispatch( |
michael@0 | 1663 | WrapRunnableNM(SetIntPrefOnMainThread, |
michael@0 | 1664 | prefs, |
michael@0 | 1665 | "media.navigator.video.max_fr", |
michael@0 | 1666 | max_fr), |
michael@0 | 1667 | NS_DISPATCH_SYNC); |
michael@0 | 1668 | } |
michael@0 | 1669 | |
michael@0 | 1670 | class FsFrPrefClearer { |
michael@0 | 1671 | public: |
michael@0 | 1672 | FsFrPrefClearer(nsCOMPtr<nsIPrefBranch> prefs): mPrefs(prefs) {} |
michael@0 | 1673 | ~FsFrPrefClearer() { |
michael@0 | 1674 | gMainThread->Dispatch( |
michael@0 | 1675 | WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread, |
michael@0 | 1676 | mPrefs, |
michael@0 | 1677 | "media.navigator.video.max_fs"), |
michael@0 | 1678 | NS_DISPATCH_SYNC); |
michael@0 | 1679 | gMainThread->Dispatch( |
michael@0 | 1680 | WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread, |
michael@0 | 1681 | mPrefs, |
michael@0 | 1682 | "media.navigator.video.max_fr"), |
michael@0 | 1683 | NS_DISPATCH_SYNC); |
michael@0 | 1684 | } |
michael@0 | 1685 | |
michael@0 | 1686 | static void ClearUserPrefOnMainThread(nsCOMPtr<nsIPrefBranch> prefs, |
michael@0 | 1687 | const char *pref_name) { |
michael@0 | 1688 | MOZ_ASSERT(NS_IsMainThread()); |
michael@0 | 1689 | prefs->ClearUserPref(pref_name); |
michael@0 | 1690 | } |
michael@0 | 1691 | private: |
michael@0 | 1692 | nsCOMPtr<nsIPrefBranch> mPrefs; |
michael@0 | 1693 | }; |
michael@0 | 1694 | |
michael@0 | 1695 | TEST_F(SignalingTest, JustInit) |
michael@0 | 1696 | { |
michael@0 | 1697 | } |
michael@0 | 1698 | |
michael@0 | 1699 | TEST_F(SignalingTest, CreateSetOffer) |
michael@0 | 1700 | { |
michael@0 | 1701 | sipcc::MediaConstraints constraints; |
michael@0 | 1702 | CreateSetOffer(constraints, SHOULD_SENDRECV_AV); |
michael@0 | 1703 | } |
michael@0 | 1704 | |
michael@0 | 1705 | TEST_F(SignalingTest, CreateOfferAudioVideoConstraintUndefined) |
michael@0 | 1706 | { |
michael@0 | 1707 | sipcc::MediaConstraints constraints; |
michael@0 | 1708 | CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
michael@0 | 1709 | } |
michael@0 | 1710 | |
michael@0 | 1711 | TEST_F(SignalingTest, CreateOfferNoVideoStreamRecvVideo) |
michael@0 | 1712 | { |
michael@0 | 1713 | sipcc::MediaConstraints constraints; |
michael@0 | 1714 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1715 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1716 | CreateOffer(constraints, OFFER_AUDIO, |
michael@0 | 1717 | SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); |
michael@0 | 1718 | } |
michael@0 | 1719 | |
michael@0 | 1720 | TEST_F(SignalingTest, CreateOfferNoAudioStreamRecvAudio) |
michael@0 | 1721 | { |
michael@0 | 1722 | sipcc::MediaConstraints constraints; |
michael@0 | 1723 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1724 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1725 | CreateOffer(constraints, OFFER_VIDEO, |
michael@0 | 1726 | SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1727 | } |
michael@0 | 1728 | |
michael@0 | 1729 | TEST_F(SignalingTest, CreateOfferNoVideoStream) |
michael@0 | 1730 | { |
michael@0 | 1731 | sipcc::MediaConstraints constraints; |
michael@0 | 1732 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1733 | constraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1734 | CreateOffer(constraints, OFFER_AUDIO, |
michael@0 | 1735 | SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO); |
michael@0 | 1736 | } |
michael@0 | 1737 | |
michael@0 | 1738 | TEST_F(SignalingTest, CreateOfferNoAudioStream) |
michael@0 | 1739 | { |
michael@0 | 1740 | sipcc::MediaConstraints constraints; |
michael@0 | 1741 | constraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1742 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1743 | CreateOffer(constraints, OFFER_VIDEO, |
michael@0 | 1744 | SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1745 | } |
michael@0 | 1746 | |
michael@0 | 1747 | TEST_F(SignalingTest, CreateOfferDontReceiveAudio) |
michael@0 | 1748 | { |
michael@0 | 1749 | sipcc::MediaConstraints constraints; |
michael@0 | 1750 | constraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1751 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1752 | CreateOffer(constraints, OFFER_AV, |
michael@0 | 1753 | SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1754 | } |
michael@0 | 1755 | |
michael@0 | 1756 | TEST_F(SignalingTest, CreateOfferDontReceiveVideo) |
michael@0 | 1757 | { |
michael@0 | 1758 | sipcc::MediaConstraints constraints; |
michael@0 | 1759 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1760 | constraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1761 | CreateOffer(constraints, OFFER_AV, |
michael@0 | 1762 | SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO); |
michael@0 | 1763 | } |
michael@0 | 1764 | |
michael@0 | 1765 | // XXX Disabled pending resolution of Bug 840728 |
michael@0 | 1766 | TEST_F(SignalingTest, DISABLED_CreateOfferRemoveAudioStream) |
michael@0 | 1767 | { |
michael@0 | 1768 | sipcc::MediaConstraints constraints; |
michael@0 | 1769 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1770 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1771 | CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_AUDIO, |
michael@0 | 1772 | SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1773 | } |
michael@0 | 1774 | |
michael@0 | 1775 | // XXX Disabled pending resolution of Bug 840728 |
michael@0 | 1776 | TEST_F(SignalingTest, DISABLED_CreateOfferDontReceiveAudioRemoveAudioStream) |
michael@0 | 1777 | { |
michael@0 | 1778 | sipcc::MediaConstraints constraints; |
michael@0 | 1779 | constraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1780 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1781 | CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_AUDIO, |
michael@0 | 1782 | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1783 | } |
michael@0 | 1784 | |
michael@0 | 1785 | // XXX Disabled pending resolution of Bug 840728 |
michael@0 | 1786 | TEST_F(SignalingTest, DISABLED_CreateOfferDontReceiveVideoRemoveVideoStream) |
michael@0 | 1787 | { |
michael@0 | 1788 | sipcc::MediaConstraints constraints; |
michael@0 | 1789 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1790 | constraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1791 | CreateOfferRemoveStream(constraints, DOMMediaStream::HINT_CONTENTS_VIDEO, |
michael@0 | 1792 | SHOULD_SENDRECV_AUDIO); |
michael@0 | 1793 | } |
michael@0 | 1794 | |
michael@0 | 1795 | TEST_F(SignalingTest, OfferAnswerNothingDisabled) |
michael@0 | 1796 | { |
michael@0 | 1797 | sipcc::MediaConstraints constraints; |
michael@0 | 1798 | OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, false, |
michael@0 | 1799 | SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 1800 | } |
michael@0 | 1801 | |
michael@0 | 1802 | TEST_F(SignalingTest, OfferAnswerDontReceiveAudioOnOffer) |
michael@0 | 1803 | { |
michael@0 | 1804 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1805 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1806 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1807 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1808 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1809 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1810 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, |
michael@0 | 1811 | false, SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO, |
michael@0 | 1812 | SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1813 | } |
michael@0 | 1814 | |
michael@0 | 1815 | TEST_F(SignalingTest, OfferAnswerDontReceiveVideoOnOffer) |
michael@0 | 1816 | { |
michael@0 | 1817 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1818 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1819 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1820 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1821 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1822 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1823 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, |
michael@0 | 1824 | false, SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO, |
michael@0 | 1825 | SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); |
michael@0 | 1826 | } |
michael@0 | 1827 | |
michael@0 | 1828 | TEST_F(SignalingTest, OfferAnswerDontReceiveAudioOnAnswer) |
michael@0 | 1829 | { |
michael@0 | 1830 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1831 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1832 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1833 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1834 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1835 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1836 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, |
michael@0 | 1837 | false, SHOULD_SENDRECV_AV, |
michael@0 | 1838 | SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1839 | } |
michael@0 | 1840 | |
michael@0 | 1841 | TEST_F(SignalingTest, OfferAnswerDontReceiveVideoOnAnswer) |
michael@0 | 1842 | { |
michael@0 | 1843 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1844 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1845 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1846 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1847 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1848 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1849 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AV, |
michael@0 | 1850 | false, SHOULD_SENDRECV_AV, |
michael@0 | 1851 | SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO); |
michael@0 | 1852 | } |
michael@0 | 1853 | |
michael@0 | 1854 | TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOfferRecvAudio) |
michael@0 | 1855 | { |
michael@0 | 1856 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1857 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1858 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1859 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1860 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1861 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1862 | OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, |
michael@0 | 1863 | false, SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO, |
michael@0 | 1864 | SHOULD_SEND_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1865 | } |
michael@0 | 1866 | |
michael@0 | 1867 | TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOffer) |
michael@0 | 1868 | { |
michael@0 | 1869 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1870 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1871 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1872 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1873 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1874 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1875 | OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, |
michael@0 | 1876 | false, SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO, |
michael@0 | 1877 | SHOULD_OMIT_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1878 | } |
michael@0 | 1879 | |
michael@0 | 1880 | TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOfferRecvVideo) |
michael@0 | 1881 | { |
michael@0 | 1882 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1883 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1884 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1885 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1886 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1887 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1888 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV, |
michael@0 | 1889 | false, SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO, |
michael@0 | 1890 | SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO); |
michael@0 | 1891 | } |
michael@0 | 1892 | |
michael@0 | 1893 | TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOffer) |
michael@0 | 1894 | { |
michael@0 | 1895 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1896 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1897 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1898 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1899 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1900 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1901 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV, |
michael@0 | 1902 | false, SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO, |
michael@0 | 1903 | SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO); |
michael@0 | 1904 | } |
michael@0 | 1905 | |
michael@0 | 1906 | TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswer) |
michael@0 | 1907 | { |
michael@0 | 1908 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1909 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1910 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1911 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1912 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1913 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1914 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO, |
michael@0 | 1915 | false, SHOULD_SENDRECV_AV, |
michael@0 | 1916 | SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1917 | } |
michael@0 | 1918 | |
michael@0 | 1919 | TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswer) |
michael@0 | 1920 | { |
michael@0 | 1921 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1922 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1923 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1924 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1925 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1926 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1927 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, |
michael@0 | 1928 | false, SHOULD_SENDRECV_AV, |
michael@0 | 1929 | SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); |
michael@0 | 1930 | } |
michael@0 | 1931 | |
michael@0 | 1932 | TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswerDontReceiveVideoOnAnswer) |
michael@0 | 1933 | { |
michael@0 | 1934 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1935 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1936 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1937 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1938 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1939 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1940 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, |
michael@0 | 1941 | false, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AUDIO ); |
michael@0 | 1942 | } |
michael@0 | 1943 | |
michael@0 | 1944 | TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswerDontReceiveAudioOnAnswer) |
michael@0 | 1945 | { |
michael@0 | 1946 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1947 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1948 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1949 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1950 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1951 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1952 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO, |
michael@0 | 1953 | false, SHOULD_SENDRECV_AV, |
michael@0 | 1954 | SHOULD_REJECT_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 1955 | } |
michael@0 | 1956 | |
michael@0 | 1957 | TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnOfferDontReceiveAudioOnOffer) |
michael@0 | 1958 | { |
michael@0 | 1959 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1960 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1961 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1962 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1963 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1964 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1965 | OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, |
michael@0 | 1966 | false, SHOULD_SENDRECV_VIDEO, SHOULD_SENDRECV_VIDEO); |
michael@0 | 1967 | } |
michael@0 | 1968 | |
michael@0 | 1969 | TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnOfferDontReceiveVideoOnOffer) |
michael@0 | 1970 | { |
michael@0 | 1971 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1972 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1973 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1974 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1975 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1976 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1977 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AUDIO | ANSWER_AV, |
michael@0 | 1978 | false, SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO, |
michael@0 | 1979 | SHOULD_SENDRECV_AUDIO | SHOULD_OMIT_VIDEO); |
michael@0 | 1980 | } |
michael@0 | 1981 | |
michael@0 | 1982 | TEST_F(SignalingTest, OfferAnswerDontReceiveAudioNoAudioStreamOnOfferDontReceiveVideoOnAnswer) |
michael@0 | 1983 | { |
michael@0 | 1984 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 1985 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", false, false); |
michael@0 | 1986 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 1987 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 1988 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 1989 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 1990 | OfferAnswer(offerconstraints, answerconstraints, OFFER_VIDEO | ANSWER_AV, |
michael@0 | 1991 | false, SHOULD_SENDRECV_VIDEO, SHOULD_SEND_VIDEO); |
michael@0 | 1992 | } |
michael@0 | 1993 | |
michael@0 | 1994 | TEST_F(SignalingTest, CreateOfferAddCandidate) |
michael@0 | 1995 | { |
michael@0 | 1996 | sipcc::MediaConstraints constraints; |
michael@0 | 1997 | CreateOfferAddCandidate(constraints, strSampleCandidate.c_str(), |
michael@0 | 1998 | strSampleMid.c_str(), nSamplelevel, |
michael@0 | 1999 | SHOULD_SENDRECV_AV); |
michael@0 | 2000 | } |
michael@0 | 2001 | |
michael@0 | 2002 | TEST_F(SignalingTest, AddIceCandidateEarly) |
michael@0 | 2003 | { |
michael@0 | 2004 | sipcc::MediaConstraints constraints; |
michael@0 | 2005 | AddIceCandidateEarly(strSampleCandidate.c_str(), |
michael@0 | 2006 | strSampleMid.c_str(), nSamplelevel); |
michael@0 | 2007 | } |
michael@0 | 2008 | |
michael@0 | 2009 | // XXX adam@nostrum.com -- This test seems questionable; we need to think |
michael@0 | 2010 | // through what actually needs to be tested here. |
michael@0 | 2011 | TEST_F(SignalingTest, DISABLED_OfferAnswerReNegotiateOfferAnswerDontReceiveVideoNoVideoStream) |
michael@0 | 2012 | { |
michael@0 | 2013 | sipcc::MediaConstraints aconstraints; |
michael@0 | 2014 | aconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2015 | aconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 2016 | |
michael@0 | 2017 | sipcc::MediaConstraints bconstraints; |
michael@0 | 2018 | bconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2019 | bconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 2020 | |
michael@0 | 2021 | OfferAnswer(aconstraints, aconstraints, OFFER_AV | ANSWER_AV, |
michael@0 | 2022 | false, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2023 | OfferAnswer(bconstraints, bconstraints, OFFER_AUDIO | ANSWER_AV, |
michael@0 | 2024 | false, SHOULD_SENDRECV_AUDIO | SHOULD_SEND_VIDEO, |
michael@0 | 2025 | SHOULD_SENDRECV_AUDIO | SHOULD_INACTIVE_VIDEO); |
michael@0 | 2026 | } |
michael@0 | 2027 | |
michael@0 | 2028 | TEST_F(SignalingTest, OfferAnswerDontAddAudioStreamOnAnswerNoConstraints) |
michael@0 | 2029 | { |
michael@0 | 2030 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 2031 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2032 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 2033 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 2034 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_VIDEO, |
michael@0 | 2035 | false, SHOULD_SENDRECV_AV, |
michael@0 | 2036 | SHOULD_RECV_AUDIO | SHOULD_SENDRECV_VIDEO); |
michael@0 | 2037 | } |
michael@0 | 2038 | |
michael@0 | 2039 | TEST_F(SignalingTest, OfferAnswerDontAddVideoStreamOnAnswerNoConstraints) |
michael@0 | 2040 | { |
michael@0 | 2041 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 2042 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2043 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 2044 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 2045 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, |
michael@0 | 2046 | false, SHOULD_SENDRECV_AV, |
michael@0 | 2047 | SHOULD_SENDRECV_AUDIO | SHOULD_RECV_VIDEO); |
michael@0 | 2048 | } |
michael@0 | 2049 | |
michael@0 | 2050 | TEST_F(SignalingTest, OfferAnswerDontAddAudioVideoStreamsOnAnswerNoConstraints) |
michael@0 | 2051 | { |
michael@0 | 2052 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 2053 | offerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2054 | offerconstraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 2055 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 2056 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_NONE, |
michael@0 | 2057 | false, SHOULD_SENDRECV_AV, |
michael@0 | 2058 | SHOULD_RECV_AUDIO | SHOULD_RECV_VIDEO); |
michael@0 | 2059 | } |
michael@0 | 2060 | |
michael@0 | 2061 | TEST_F(SignalingTest, FullCall) |
michael@0 | 2062 | { |
michael@0 | 2063 | sipcc::MediaConstraints constraints; |
michael@0 | 2064 | OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, |
michael@0 | 2065 | true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2066 | |
michael@0 | 2067 | // Wait for some data to get written |
michael@0 | 2068 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2069 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2070 | |
michael@0 | 2071 | a1_->CloseSendStreams(); |
michael@0 | 2072 | a2_->CloseReceiveStreams(); |
michael@0 | 2073 | // Check that we wrote a bunch of data |
michael@0 | 2074 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2075 | //ASSERT_GE(a2_->GetPacketsSent(0), 40); |
michael@0 | 2076 | //ASSERT_GE(a1_->GetPacketsReceived(0), 40); |
michael@0 | 2077 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2078 | |
michael@0 | 2079 | // Check the low-level media pipeline |
michael@0 | 2080 | // for RTP and RTCP flows |
michael@0 | 2081 | // The first Local pipeline gets stored at 0 |
michael@0 | 2082 | a1_->CheckMediaPipeline(0, 0, fRtcpMux ? |
michael@0 | 2083 | PIPELINE_LOCAL | PIPELINE_RTCP_MUX | PIPELINE_SEND : |
michael@0 | 2084 | PIPELINE_LOCAL | PIPELINE_SEND); |
michael@0 | 2085 | |
michael@0 | 2086 | // The first Remote pipeline gets stored at 1 |
michael@0 | 2087 | a2_->CheckMediaPipeline(0, 1, (fRtcpMux ? PIPELINE_RTCP_MUX : 0)); |
michael@0 | 2088 | } |
michael@0 | 2089 | |
michael@0 | 2090 | TEST_F(SignalingTest, FullCallAudioOnly) |
michael@0 | 2091 | { |
michael@0 | 2092 | sipcc::MediaConstraints constraints; |
michael@0 | 2093 | OfferAnswer(constraints, constraints, OFFER_AUDIO | ANSWER_AUDIO, |
michael@0 | 2094 | true, SHOULD_SENDRECV_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2095 | |
michael@0 | 2096 | // Wait for some data to get written |
michael@0 | 2097 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2098 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2099 | |
michael@0 | 2100 | a1_->CloseSendStreams(); |
michael@0 | 2101 | a2_->CloseReceiveStreams(); |
michael@0 | 2102 | // Check that we wrote a bunch of data |
michael@0 | 2103 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2104 | //ASSERT_GE(a2_->GetPacketsSent(0), 40); |
michael@0 | 2105 | //ASSERT_GE(a1_->GetPacketsReceived(0), 40); |
michael@0 | 2106 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2107 | } |
michael@0 | 2108 | |
michael@0 | 2109 | TEST_F(SignalingTest, FullCallAnswererRejectsVideo) |
michael@0 | 2110 | { |
michael@0 | 2111 | sipcc::MediaConstraints offerconstraints; |
michael@0 | 2112 | sipcc::MediaConstraints answerconstraints; |
michael@0 | 2113 | answerconstraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2114 | answerconstraints.setBooleanConstraint("OfferToReceiveVideo", false, false); |
michael@0 | 2115 | OfferAnswer(offerconstraints, answerconstraints, OFFER_AV | ANSWER_AUDIO, |
michael@0 | 2116 | true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2117 | |
michael@0 | 2118 | // Wait for some data to get written |
michael@0 | 2119 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2120 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2121 | |
michael@0 | 2122 | a1_->CloseSendStreams(); |
michael@0 | 2123 | a2_->CloseReceiveStreams(); |
michael@0 | 2124 | // Check that we wrote a bunch of data |
michael@0 | 2125 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2126 | //ASSERT_GE(a2_->GetPacketsSent(0), 40); |
michael@0 | 2127 | //ASSERT_GE(a1_->GetPacketsReceived(0), 40); |
michael@0 | 2128 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2129 | } |
michael@0 | 2130 | |
michael@0 | 2131 | TEST_F(SignalingTest, FullCallVideoOnly) |
michael@0 | 2132 | { |
michael@0 | 2133 | sipcc::MediaConstraints constraints; |
michael@0 | 2134 | OfferAnswer(constraints, constraints, OFFER_VIDEO | ANSWER_VIDEO, |
michael@0 | 2135 | true, SHOULD_SENDRECV_VIDEO, SHOULD_SENDRECV_VIDEO); |
michael@0 | 2136 | |
michael@0 | 2137 | // If we could check for video packets, we would wait for some to be written |
michael@0 | 2138 | // here. Since we can't, we don't. |
michael@0 | 2139 | // ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2140 | // a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2141 | |
michael@0 | 2142 | a1_->CloseSendStreams(); |
michael@0 | 2143 | a2_->CloseReceiveStreams(); |
michael@0 | 2144 | |
michael@0 | 2145 | // FIXME -- Ideally we would check that packets were sent |
michael@0 | 2146 | // and received; however, the test driver setup does not |
michael@0 | 2147 | // currently support sending/receiving with Fake_VideoStreamSource. |
michael@0 | 2148 | // |
michael@0 | 2149 | // Check that we wrote a bunch of data |
michael@0 | 2150 | // ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2151 | //ASSERT_GE(a2_->GetPacketsSent(0), 40); |
michael@0 | 2152 | //ASSERT_GE(a1_->GetPacketsReceived(0), 40); |
michael@0 | 2153 | // ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2154 | } |
michael@0 | 2155 | |
michael@0 | 2156 | TEST_F(SignalingTest, OfferModifiedAnswer) |
michael@0 | 2157 | { |
michael@0 | 2158 | sipcc::MediaConstraints constraints; |
michael@0 | 2159 | OfferModifiedAnswer(constraints, constraints, SHOULD_SENDRECV_AUDIO, |
michael@0 | 2160 | SHOULD_SENDRECV_AUDIO); |
michael@0 | 2161 | a1_->CloseSendStreams(); |
michael@0 | 2162 | a2_->CloseReceiveStreams(); |
michael@0 | 2163 | } |
michael@0 | 2164 | |
michael@0 | 2165 | TEST_F(SignalingTest, FullCallTrickle) |
michael@0 | 2166 | { |
michael@0 | 2167 | sipcc::MediaConstraints constraints; |
michael@0 | 2168 | OfferAnswerTrickle(constraints, constraints, |
michael@0 | 2169 | SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2170 | |
michael@0 | 2171 | std::cerr << "ICE handshake completed" << std::endl; |
michael@0 | 2172 | |
michael@0 | 2173 | // Wait for some data to get written |
michael@0 | 2174 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2175 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2176 | |
michael@0 | 2177 | a1_->CloseSendStreams(); |
michael@0 | 2178 | a2_->CloseReceiveStreams(); |
michael@0 | 2179 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2180 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2181 | } |
michael@0 | 2182 | |
michael@0 | 2183 | // Offer answer with trickle but with chrome-style candidates |
michael@0 | 2184 | TEST_F(SignalingTest, FullCallTrickleChrome) |
michael@0 | 2185 | { |
michael@0 | 2186 | sipcc::MediaConstraints constraints; |
michael@0 | 2187 | OfferAnswerTrickleChrome(constraints, constraints, |
michael@0 | 2188 | SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2189 | |
michael@0 | 2190 | std::cerr << "ICE handshake completed" << std::endl; |
michael@0 | 2191 | |
michael@0 | 2192 | // Wait for some data to get written |
michael@0 | 2193 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2194 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2195 | |
michael@0 | 2196 | a1_->CloseSendStreams(); |
michael@0 | 2197 | a2_->CloseReceiveStreams(); |
michael@0 | 2198 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2199 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2200 | } |
michael@0 | 2201 | |
michael@0 | 2202 | // This test comes from Bug 810220 |
michael@0 | 2203 | TEST_F(SignalingTest, AudioOnlyG711Call) |
michael@0 | 2204 | { |
michael@0 | 2205 | EnsureInit(); |
michael@0 | 2206 | |
michael@0 | 2207 | sipcc::MediaConstraints constraints; |
michael@0 | 2208 | const std::string& offer(strG711SdpOffer); |
michael@0 | 2209 | |
michael@0 | 2210 | std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; |
michael@0 | 2211 | a2_->SetRemote(TestObserver::OFFER, offer); |
michael@0 | 2212 | |
michael@0 | 2213 | std::cout << "Creating answer:" << std::endl; |
michael@0 | 2214 | a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO, |
michael@0 | 2215 | DONT_CHECK_AUDIO | DONT_CHECK_VIDEO | DONT_CHECK_DATA); |
michael@0 | 2216 | |
michael@0 | 2217 | std::string answer = a2_->answer(); |
michael@0 | 2218 | |
michael@0 | 2219 | // They didn't offer opus, so our answer shouldn't include it. |
michael@0 | 2220 | ASSERT_EQ(answer.find(" opus/"), std::string::npos); |
michael@0 | 2221 | |
michael@0 | 2222 | // They also didn't offer video or application |
michael@0 | 2223 | ASSERT_EQ(answer.find("video"), std::string::npos); |
michael@0 | 2224 | ASSERT_EQ(answer.find("application"), std::string::npos); |
michael@0 | 2225 | |
michael@0 | 2226 | // We should answer with PCMU and telephone-event |
michael@0 | 2227 | ASSERT_NE(answer.find(" PCMU/8000"), std::string::npos); |
michael@0 | 2228 | ASSERT_NE(answer.find(" telephone-event/8000"), std::string::npos); |
michael@0 | 2229 | |
michael@0 | 2230 | // Double-check the directionality |
michael@0 | 2231 | ASSERT_NE(answer.find("\r\na=sendrecv"), std::string::npos); |
michael@0 | 2232 | |
michael@0 | 2233 | } |
michael@0 | 2234 | |
michael@0 | 2235 | // This test comes from Bug814038 |
michael@0 | 2236 | TEST_F(SignalingTest, ChromeOfferAnswer) |
michael@0 | 2237 | { |
michael@0 | 2238 | EnsureInit(); |
michael@0 | 2239 | |
michael@0 | 2240 | sipcc::MediaConstraints constraints; |
michael@0 | 2241 | |
michael@0 | 2242 | // This is captured SDP from an early interop attempt with Chrome. |
michael@0 | 2243 | std::string offer = |
michael@0 | 2244 | "v=0\r\n" |
michael@0 | 2245 | "o=- 1713781661 2 IN IP4 127.0.0.1\r\n" |
michael@0 | 2246 | "s=-\r\n" |
michael@0 | 2247 | "t=0 0\r\n" |
michael@0 | 2248 | "a=group:BUNDLE audio video\r\n" |
michael@0 | 2249 | |
michael@0 | 2250 | "m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n" |
michael@0 | 2251 | "a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:" |
michael@0 | 2252 | "5D:49:6B:19:E5:7C:AB\r\n" |
michael@0 | 2253 | "c=IN IP4 0.0.0.0\r\n" |
michael@0 | 2254 | "a=rtcp:1 IN IP4 0.0.0.0\r\n" |
michael@0 | 2255 | "a=ice-ufrag:lBrbdDfrVBH1cldN\r\n" |
michael@0 | 2256 | "a=ice-pwd:rzh23jet4QpCaEoj9Sl75pL3\r\n" |
michael@0 | 2257 | "a=ice-options:google-ice\r\n" |
michael@0 | 2258 | "a=sendrecv\r\n" |
michael@0 | 2259 | "a=mid:audio\r\n" |
michael@0 | 2260 | "a=rtcp-mux\r\n" |
michael@0 | 2261 | "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:" |
michael@0 | 2262 | "RzrYlzpkTsvgYFD1hQqNCzQ7y4emNLKI1tODsjim\r\n" |
michael@0 | 2263 | "a=rtpmap:103 ISAC/16000\r\n" |
michael@0 | 2264 | "a=rtpmap:104 ISAC/32000\r\n" |
michael@0 | 2265 | // NOTE: the actual SDP that Chrome sends at the moment |
michael@0 | 2266 | // doesn't indicate two channels. I've amended their SDP |
michael@0 | 2267 | // here, under the assumption that the constraints |
michael@0 | 2268 | // described in draft-spittka-payload-rtp-opus will |
michael@0 | 2269 | // eventually be implemented by Google. |
michael@0 | 2270 | "a=rtpmap:111 opus/48000/2\r\n" |
michael@0 | 2271 | "a=rtpmap:0 PCMU/8000\r\n" |
michael@0 | 2272 | "a=rtpmap:8 PCMA/8000\r\n" |
michael@0 | 2273 | "a=rtpmap:107 CN/48000\r\n" |
michael@0 | 2274 | "a=rtpmap:106 CN/32000\r\n" |
michael@0 | 2275 | "a=rtpmap:105 CN/16000\r\n" |
michael@0 | 2276 | "a=rtpmap:13 CN/8000\r\n" |
michael@0 | 2277 | "a=rtpmap:126 telephone-event/8000\r\n" |
michael@0 | 2278 | "a=ssrc:661333377 cname:KIXaNxUlU5DP3fVS\r\n" |
michael@0 | 2279 | "a=ssrc:661333377 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 a0\r\n" |
michael@0 | 2280 | "a=ssrc:661333377 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n" |
michael@0 | 2281 | "a=ssrc:661333377 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5a0\r\n" |
michael@0 | 2282 | |
michael@0 | 2283 | "m=video 1 RTP/SAVPF 100 101 102\r\n" |
michael@0 | 2284 | "a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:" |
michael@0 | 2285 | "6B:19:E5:7C:AB\r\n" |
michael@0 | 2286 | "c=IN IP4 0.0.0.0\r\n" |
michael@0 | 2287 | "a=rtcp:1 IN IP4 0.0.0.0\r\n" |
michael@0 | 2288 | "a=ice-ufrag:lBrbdDfrVBH1cldN\r\n" |
michael@0 | 2289 | "a=ice-pwd:rzh23jet4QpCaEoj9Sl75pL3\r\n" |
michael@0 | 2290 | "a=ice-options:google-ice\r\n" |
michael@0 | 2291 | "a=sendrecv\r\n" |
michael@0 | 2292 | "a=mid:video\r\n" |
michael@0 | 2293 | "a=rtcp-mux\r\n" |
michael@0 | 2294 | "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:" |
michael@0 | 2295 | "RzrYlzpkTsvgYFD1hQqNCzQ7y4emNLKI1tODsjim\r\n" |
michael@0 | 2296 | "a=rtpmap:100 VP8/90000\r\n" |
michael@0 | 2297 | "a=rtpmap:101 red/90000\r\n" |
michael@0 | 2298 | "a=rtpmap:102 ulpfec/90000\r\n" |
michael@0 | 2299 | "a=rtcp-fb:100 nack\r\n" |
michael@0 | 2300 | "a=rtcp-fb:100 ccm fir\r\n" |
michael@0 | 2301 | "a=ssrc:3012607008 cname:KIXaNxUlU5DP3fVS\r\n" |
michael@0 | 2302 | "a=ssrc:3012607008 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 v0\r\n" |
michael@0 | 2303 | "a=ssrc:3012607008 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n" |
michael@0 | 2304 | "a=ssrc:3012607008 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5v0\r\n"; |
michael@0 | 2305 | |
michael@0 | 2306 | |
michael@0 | 2307 | std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; |
michael@0 | 2308 | a2_->SetRemote(TestObserver::OFFER, offer); |
michael@0 | 2309 | |
michael@0 | 2310 | std::cout << "Creating answer:" << std::endl; |
michael@0 | 2311 | a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 2312 | |
michael@0 | 2313 | std::string answer = a2_->answer(); |
michael@0 | 2314 | } |
michael@0 | 2315 | |
michael@0 | 2316 | |
michael@0 | 2317 | TEST_F(SignalingTest, FullChromeHandshake) |
michael@0 | 2318 | { |
michael@0 | 2319 | EnsureInit(); |
michael@0 | 2320 | |
michael@0 | 2321 | sipcc::MediaConstraints constraints; |
michael@0 | 2322 | constraints.setBooleanConstraint("OfferToReceiveAudio", true, false); |
michael@0 | 2323 | constraints.setBooleanConstraint("OfferToReceiveVideo", true, false); |
michael@0 | 2324 | |
michael@0 | 2325 | std::string offer = "v=0\r\n" |
michael@0 | 2326 | "o=- 3835809413 2 IN IP4 127.0.0.1\r\n" |
michael@0 | 2327 | "s=-\r\n" |
michael@0 | 2328 | "t=0 0\r\n" |
michael@0 | 2329 | "a=group:BUNDLE audio video\r\n" |
michael@0 | 2330 | "a=msid-semantic: WMS ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n" |
michael@0 | 2331 | "m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n" |
michael@0 | 2332 | "c=IN IP4 1.1.1.1\r\n" |
michael@0 | 2333 | "a=rtcp:1 IN IP4 1.1.1.1\r\n" |
michael@0 | 2334 | "a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n" |
michael@0 | 2335 | "a=ice-pwd:iscXxsdU+0gracg0g5D45orx\r\n" |
michael@0 | 2336 | "a=ice-options:google-ice\r\n" |
michael@0 | 2337 | "a=fingerprint:sha-256 A8:76:8C:4C:FA:2E:67:D7:F8:1D:28:4E:90:24:04:" |
michael@0 | 2338 | "12:EB:B4:A6:69:3D:05:92:E4:91:C3:EA:F9:B7:54:D3:09\r\n" |
michael@0 | 2339 | "a=sendrecv\r\n" |
michael@0 | 2340 | "a=mid:audio\r\n" |
michael@0 | 2341 | "a=rtcp-mux\r\n" |
michael@0 | 2342 | "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/he/v44FKu/QvEhex86zV0pdn2V" |
michael@0 | 2343 | "4Y7wB2xaZ8eUy\r\n" |
michael@0 | 2344 | "a=rtpmap:103 ISAC/16000\r\n" |
michael@0 | 2345 | "a=rtpmap:104 ISAC/32000\r\n" |
michael@0 | 2346 | "a=rtpmap:111 opus/48000/2\r\n" |
michael@0 | 2347 | "a=rtpmap:0 PCMU/8000\r\n" |
michael@0 | 2348 | "a=rtpmap:8 PCMA/8000\r\n" |
michael@0 | 2349 | "a=rtpmap:107 CN/48000\r\n" |
michael@0 | 2350 | "a=rtpmap:106 CN/32000\r\n" |
michael@0 | 2351 | "a=rtpmap:105 CN/16000\r\n" |
michael@0 | 2352 | "a=rtpmap:13 CN/8000\r\n" |
michael@0 | 2353 | "a=rtpmap:126 telephone-event/8000\r\n" |
michael@0 | 2354 | "a=ssrc:3389377748 cname:G5I+Jxz4rcaq8IIK\r\n" |
michael@0 | 2355 | "a=ssrc:3389377748 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH a0\r\n" |
michael@0 | 2356 | "a=ssrc:3389377748 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n" |
michael@0 | 2357 | "a=ssrc:3389377748 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHa0\r\n" |
michael@0 | 2358 | "m=video 1 RTP/SAVPF 100 116 117\r\n" |
michael@0 | 2359 | "c=IN IP4 1.1.1.1\r\n" |
michael@0 | 2360 | "a=rtcp:1 IN IP4 1.1.1.1\r\n" |
michael@0 | 2361 | "a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n" |
michael@0 | 2362 | "a=ice-pwd:iscXxsdU+0gracg0g5D45orx\r\n" |
michael@0 | 2363 | "a=ice-options:google-ice\r\n" |
michael@0 | 2364 | "a=fingerprint:sha-256 A8:76:8C:4C:FA:2E:67:D7:F8:1D:28:4E:90:24:04:" |
michael@0 | 2365 | "12:EB:B4:A6:69:3D:05:92:E4:91:C3:EA:F9:B7:54:D3:09\r\n" |
michael@0 | 2366 | "a=sendrecv\r\n" |
michael@0 | 2367 | "a=mid:video\r\n" |
michael@0 | 2368 | "a=rtcp-mux\r\n" |
michael@0 | 2369 | "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/he/v44FKu/QvEhex86zV0pdn2V" |
michael@0 | 2370 | "4Y7wB2xaZ8eUy\r\n" |
michael@0 | 2371 | "a=rtpmap:100 VP8/90000\r\n" |
michael@0 | 2372 | "a=rtpmap:116 red/90000\r\n" |
michael@0 | 2373 | "a=rtpmap:117 ulpfec/90000\r\n" |
michael@0 | 2374 | "a=ssrc:3613537198 cname:G5I+Jxz4rcaq8IIK\r\n" |
michael@0 | 2375 | "a=ssrc:3613537198 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH v0\r\n" |
michael@0 | 2376 | "a=ssrc:3613537198 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n" |
michael@0 | 2377 | "a=ssrc:3613537198 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHv0\r\n"; |
michael@0 | 2378 | |
michael@0 | 2379 | std::cout << "Setting offer to:" << std::endl << indent(offer) << std::endl; |
michael@0 | 2380 | a2_->SetRemote(TestObserver::OFFER, offer); |
michael@0 | 2381 | |
michael@0 | 2382 | std::cout << "Creating answer:" << std::endl; |
michael@0 | 2383 | a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 2384 | |
michael@0 | 2385 | std::cout << "Setting answer" << std::endl; |
michael@0 | 2386 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 2387 | |
michael@0 | 2388 | std::string answer = a2_->answer(); |
michael@0 | 2389 | ASSERT_NE(answer.find("111 opus/"), std::string::npos); |
michael@0 | 2390 | } |
michael@0 | 2391 | |
michael@0 | 2392 | // Disabled pending resolution of bug 818640. |
michael@0 | 2393 | TEST_F(SignalingTest, DISABLED_OfferAllDynamicTypes) |
michael@0 | 2394 | { |
michael@0 | 2395 | EnsureInit(); |
michael@0 | 2396 | |
michael@0 | 2397 | sipcc::MediaConstraints constraints; |
michael@0 | 2398 | std::string offer; |
michael@0 | 2399 | for (int i = 96; i < 128; i++) |
michael@0 | 2400 | { |
michael@0 | 2401 | std::stringstream ss; |
michael@0 | 2402 | ss << i; |
michael@0 | 2403 | std::cout << "Trying dynamic pt = " << i << std::endl; |
michael@0 | 2404 | offer = |
michael@0 | 2405 | "v=0\r\n" |
michael@0 | 2406 | "o=- 1 1 IN IP4 148.147.200.251\r\n" |
michael@0 | 2407 | "s=-\r\n" |
michael@0 | 2408 | "b=AS:64\r\n" |
michael@0 | 2409 | "t=0 0\r\n" |
michael@0 | 2410 | "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" |
michael@0 | 2411 | "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" |
michael@0 | 2412 | "m=audio 9000 RTP/AVP " + ss.str() + "\r\n" |
michael@0 | 2413 | "c=IN IP4 148.147.200.251\r\n" |
michael@0 | 2414 | "b=TIAS:64000\r\n" |
michael@0 | 2415 | "a=rtpmap:" + ss.str() +" opus/48000/2\r\n" |
michael@0 | 2416 | "a=candidate:0 1 udp 2130706432 148.147.200.251 9000 typ host\r\n" |
michael@0 | 2417 | "a=candidate:0 2 udp 2130706432 148.147.200.251 9005 typ host\r\n" |
michael@0 | 2418 | "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" |
michael@0 | 2419 | "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" |
michael@0 | 2420 | "a=sendrecv\r\n"; |
michael@0 | 2421 | |
michael@0 | 2422 | /* |
michael@0 | 2423 | std::cout << "Setting offer to:" << std::endl |
michael@0 | 2424 | << indent(offer) << std::endl; |
michael@0 | 2425 | */ |
michael@0 | 2426 | a2_->SetRemote(TestObserver::OFFER, offer); |
michael@0 | 2427 | |
michael@0 | 2428 | //std::cout << "Creating answer:" << std::endl; |
michael@0 | 2429 | a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 2430 | |
michael@0 | 2431 | std::string answer = a2_->answer(); |
michael@0 | 2432 | |
michael@0 | 2433 | ASSERT_NE(answer.find(ss.str() + " opus/"), std::string::npos); |
michael@0 | 2434 | } |
michael@0 | 2435 | |
michael@0 | 2436 | } |
michael@0 | 2437 | |
michael@0 | 2438 | TEST_F(SignalingTest, OfferAnswerCheckDescriptions) |
michael@0 | 2439 | { |
michael@0 | 2440 | sipcc::MediaConstraints constraints; |
michael@0 | 2441 | OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, true, |
michael@0 | 2442 | SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2443 | |
michael@0 | 2444 | std::cout << "Caller's Local Description: " << std::endl |
michael@0 | 2445 | << indent(a1_->getLocalDescription()) << std::endl << std::endl; |
michael@0 | 2446 | |
michael@0 | 2447 | std::cout << "Caller's Remote Description: " << std::endl |
michael@0 | 2448 | << indent(a1_->getRemoteDescription()) << std::endl << std::endl; |
michael@0 | 2449 | |
michael@0 | 2450 | std::cout << "Callee's Local Description: " << std::endl |
michael@0 | 2451 | << indent(a2_->getLocalDescription()) << std::endl << std::endl; |
michael@0 | 2452 | |
michael@0 | 2453 | std::cout << "Callee's Remote Description: " << std::endl |
michael@0 | 2454 | << indent(a2_->getRemoteDescription()) << std::endl << std::endl; |
michael@0 | 2455 | |
michael@0 | 2456 | ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription()); |
michael@0 | 2457 | ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription()); |
michael@0 | 2458 | } |
michael@0 | 2459 | |
michael@0 | 2460 | TEST_F(SignalingTest, CheckTrickleSdpChange) |
michael@0 | 2461 | { |
michael@0 | 2462 | sipcc::MediaConstraints constraints; |
michael@0 | 2463 | OfferAnswerTrickle(constraints, constraints, |
michael@0 | 2464 | SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2465 | std::cerr << "ICE handshake completed" << std::endl; |
michael@0 | 2466 | |
michael@0 | 2467 | a1_->CloseSendStreams(); |
michael@0 | 2468 | a2_->CloseReceiveStreams(); |
michael@0 | 2469 | |
michael@0 | 2470 | std::cout << "Caller's Local Description: " << std::endl |
michael@0 | 2471 | << indent(a1_->getLocalDescription()) << std::endl << std::endl; |
michael@0 | 2472 | |
michael@0 | 2473 | std::cout << "Caller's Remote Description: " << std::endl |
michael@0 | 2474 | << indent(a1_->getRemoteDescription()) << std::endl << std::endl; |
michael@0 | 2475 | |
michael@0 | 2476 | std::cout << "Callee's Local Description: " << std::endl |
michael@0 | 2477 | << indent(a2_->getLocalDescription()) << std::endl << std::endl; |
michael@0 | 2478 | |
michael@0 | 2479 | std::cout << "Callee's Remote Description: " << std::endl |
michael@0 | 2480 | << indent(a2_->getRemoteDescription()) << std::endl << std::endl; |
michael@0 | 2481 | |
michael@0 | 2482 | ASSERT_NE(a1_->getLocalDescription().find("\r\na=candidate"), |
michael@0 | 2483 | std::string::npos); |
michael@0 | 2484 | ASSERT_NE(a1_->getRemoteDescription().find("\r\na=candidate"), |
michael@0 | 2485 | std::string::npos); |
michael@0 | 2486 | ASSERT_NE(a2_->getLocalDescription().find("\r\na=candidate"), |
michael@0 | 2487 | std::string::npos); |
michael@0 | 2488 | ASSERT_NE(a2_->getRemoteDescription().find("\r\na=candidate"), |
michael@0 | 2489 | std::string::npos); |
michael@0 | 2490 | /* TODO (abr): These checks aren't quite right, since trickle ICE |
michael@0 | 2491 | * can easily result in SDP that is semantically identical but |
michael@0 | 2492 | * varies syntactically (in particularly, the ordering of attributes |
michael@0 | 2493 | * withing an m-line section can be different). This needs to be updated |
michael@0 | 2494 | * to be a semantic comparision between the SDP. Currently, these checks |
michael@0 | 2495 | * will fail whenever we add any other attributes to the SDP, such as |
michael@0 | 2496 | * RTCP MUX or RTCP feedback. |
michael@0 | 2497 | ASSERT_EQ(a1_->getLocalDescription(),a2_->getRemoteDescription()); |
michael@0 | 2498 | ASSERT_EQ(a2_->getLocalDescription(),a1_->getRemoteDescription()); |
michael@0 | 2499 | */ |
michael@0 | 2500 | } |
michael@0 | 2501 | |
michael@0 | 2502 | TEST_F(SignalingTest, ipAddrAnyOffer) |
michael@0 | 2503 | { |
michael@0 | 2504 | EnsureInit(); |
michael@0 | 2505 | |
michael@0 | 2506 | sipcc::MediaConstraints constraints; |
michael@0 | 2507 | std::string offer = |
michael@0 | 2508 | "v=0\r\n" |
michael@0 | 2509 | "o=- 1 1 IN IP4 127.0.0.1\r\n" |
michael@0 | 2510 | "s=-\r\n" |
michael@0 | 2511 | "b=AS:64\r\n" |
michael@0 | 2512 | "t=0 0\r\n" |
michael@0 | 2513 | "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" |
michael@0 | 2514 | "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" |
michael@0 | 2515 | "m=audio 9000 RTP/AVP 99\r\n" |
michael@0 | 2516 | "c=IN IP4 0.0.0.0\r\n" |
michael@0 | 2517 | "a=rtpmap:99 opus/48000/2\r\n" |
michael@0 | 2518 | "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" |
michael@0 | 2519 | "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" |
michael@0 | 2520 | "a=sendrecv\r\n"; |
michael@0 | 2521 | |
michael@0 | 2522 | a2_->SetRemote(TestObserver::OFFER, offer); |
michael@0 | 2523 | ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateSuccess); |
michael@0 | 2524 | a2_->CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 2525 | ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateSuccess); |
michael@0 | 2526 | std::string answer = a2_->answer(); |
michael@0 | 2527 | ASSERT_NE(answer.find("a=sendrecv"), std::string::npos); |
michael@0 | 2528 | } |
michael@0 | 2529 | |
michael@0 | 2530 | static void CreateSDPForBigOTests(std::string& offer, const char *number) { |
michael@0 | 2531 | offer = |
michael@0 | 2532 | "v=0\r\n" |
michael@0 | 2533 | "o=- "; |
michael@0 | 2534 | offer += number; |
michael@0 | 2535 | offer += " "; |
michael@0 | 2536 | offer += number; |
michael@0 | 2537 | offer += " IN IP4 127.0.0.1\r\n" |
michael@0 | 2538 | "s=-\r\n" |
michael@0 | 2539 | "b=AS:64\r\n" |
michael@0 | 2540 | "t=0 0\r\n" |
michael@0 | 2541 | "a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:" |
michael@0 | 2542 | "7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n" |
michael@0 | 2543 | "m=audio 9000 RTP/AVP 99\r\n" |
michael@0 | 2544 | "c=IN IP4 0.0.0.0\r\n" |
michael@0 | 2545 | "a=rtpmap:99 opus/48000/2\r\n" |
michael@0 | 2546 | "a=ice-ufrag:cYuakxkEKH+RApYE\r\n" |
michael@0 | 2547 | "a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n" |
michael@0 | 2548 | "a=sendrecv\r\n"; |
michael@0 | 2549 | } |
michael@0 | 2550 | |
michael@0 | 2551 | TEST_F(SignalingTest, BigOValues) |
michael@0 | 2552 | { |
michael@0 | 2553 | EnsureInit(); |
michael@0 | 2554 | |
michael@0 | 2555 | std::string offer; |
michael@0 | 2556 | |
michael@0 | 2557 | CreateSDPForBigOTests(offer, "12345678901234567"); |
michael@0 | 2558 | |
michael@0 | 2559 | a2_->SetRemote(TestObserver::OFFER, offer); |
michael@0 | 2560 | ASSERT_EQ(a2_->pObserver->state, TestObserver::stateSuccess); |
michael@0 | 2561 | } |
michael@0 | 2562 | |
michael@0 | 2563 | TEST_F(SignalingTest, BigOValuesExtraChars) |
michael@0 | 2564 | { |
michael@0 | 2565 | EnsureInit(); |
michael@0 | 2566 | |
michael@0 | 2567 | std::string offer; |
michael@0 | 2568 | |
michael@0 | 2569 | CreateSDPForBigOTests(offer, "12345678901234567FOOBAR"); |
michael@0 | 2570 | |
michael@0 | 2571 | // The signaling state will remain "stable" because the unparsable |
michael@0 | 2572 | // SDP leads to a failure in SetRemoteDescription. |
michael@0 | 2573 | a2_->SetRemote(TestObserver::OFFER, offer, true, |
michael@0 | 2574 | PCImplSignalingState::SignalingStable); |
michael@0 | 2575 | ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError); |
michael@0 | 2576 | } |
michael@0 | 2577 | |
michael@0 | 2578 | TEST_F(SignalingTest, BigOValuesTooBig) |
michael@0 | 2579 | { |
michael@0 | 2580 | EnsureInit(); |
michael@0 | 2581 | |
michael@0 | 2582 | std::string offer; |
michael@0 | 2583 | |
michael@0 | 2584 | CreateSDPForBigOTests(offer, "18446744073709551615"); |
michael@0 | 2585 | |
michael@0 | 2586 | // The signaling state will remain "stable" because the unparsable |
michael@0 | 2587 | // SDP leads to a failure in SetRemoteDescription. |
michael@0 | 2588 | a2_->SetRemote(TestObserver::OFFER, offer, true, |
michael@0 | 2589 | PCImplSignalingState::SignalingStable); |
michael@0 | 2590 | ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError); |
michael@0 | 2591 | } |
michael@0 | 2592 | |
michael@0 | 2593 | TEST_F(SignalingTest, SetLocalAnswerInStable) |
michael@0 | 2594 | { |
michael@0 | 2595 | EnsureInit(); |
michael@0 | 2596 | |
michael@0 | 2597 | sipcc::MediaConstraints constraints; |
michael@0 | 2598 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2599 | |
michael@0 | 2600 | // The signaling state will remain "stable" because the |
michael@0 | 2601 | // SetLocalDescription call fails. |
michael@0 | 2602 | a1_->SetLocal(TestObserver::ANSWER, a1_->offer(), true, |
michael@0 | 2603 | PCImplSignalingState::SignalingStable); |
michael@0 | 2604 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2605 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2606 | } |
michael@0 | 2607 | |
michael@0 | 2608 | TEST_F(SignalingTest, SetRemoteAnswerInStable) { |
michael@0 | 2609 | EnsureInit(); |
michael@0 | 2610 | |
michael@0 | 2611 | // The signaling state will remain "stable" because the |
michael@0 | 2612 | // SetRemoteDescription call fails. |
michael@0 | 2613 | a1_->SetRemote(TestObserver::ANSWER, strSampleSdpAudioVideoNoIce, true, |
michael@0 | 2614 | PCImplSignalingState::SignalingStable); |
michael@0 | 2615 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2616 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2617 | } |
michael@0 | 2618 | |
michael@0 | 2619 | TEST_F(SignalingTest, SetLocalAnswerInHaveLocalOffer) { |
michael@0 | 2620 | sipcc::MediaConstraints constraints; |
michael@0 | 2621 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2622 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2623 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2624 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2625 | |
michael@0 | 2626 | // The signaling state will remain "have-local-offer" because the |
michael@0 | 2627 | // SetLocalDescription call fails. |
michael@0 | 2628 | a1_->SetLocal(TestObserver::ANSWER, a1_->offer(), true, |
michael@0 | 2629 | PCImplSignalingState::SignalingHaveLocalOffer); |
michael@0 | 2630 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2631 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2632 | } |
michael@0 | 2633 | |
michael@0 | 2634 | TEST_F(SignalingTest, SetRemoteOfferInHaveLocalOffer) { |
michael@0 | 2635 | sipcc::MediaConstraints constraints; |
michael@0 | 2636 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2637 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2638 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2639 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2640 | |
michael@0 | 2641 | // The signaling state will remain "have-local-offer" because the |
michael@0 | 2642 | // SetRemoteDescription call fails. |
michael@0 | 2643 | a1_->SetRemote(TestObserver::OFFER, a1_->offer(), true, |
michael@0 | 2644 | PCImplSignalingState::SignalingHaveLocalOffer); |
michael@0 | 2645 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2646 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2647 | } |
michael@0 | 2648 | |
michael@0 | 2649 | TEST_F(SignalingTest, SetLocalOfferInHaveRemoteOffer) { |
michael@0 | 2650 | sipcc::MediaConstraints constraints; |
michael@0 | 2651 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2652 | a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2653 | ASSERT_EQ(a2_->pObserver->lastStatusCode, |
michael@0 | 2654 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2655 | |
michael@0 | 2656 | // The signaling state will remain "have-remote-offer" because the |
michael@0 | 2657 | // SetLocalDescription call fails. |
michael@0 | 2658 | a2_->SetLocal(TestObserver::OFFER, a1_->offer(), true, |
michael@0 | 2659 | PCImplSignalingState::SignalingHaveRemoteOffer); |
michael@0 | 2660 | ASSERT_EQ(a2_->pObserver->lastStatusCode, |
michael@0 | 2661 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2662 | } |
michael@0 | 2663 | |
michael@0 | 2664 | TEST_F(SignalingTest, SetRemoteAnswerInHaveRemoteOffer) { |
michael@0 | 2665 | sipcc::MediaConstraints constraints; |
michael@0 | 2666 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2667 | a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2668 | ASSERT_EQ(a2_->pObserver->lastStatusCode, |
michael@0 | 2669 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2670 | |
michael@0 | 2671 | // The signaling state will remain "have-remote-offer" because the |
michael@0 | 2672 | // SetRemoteDescription call fails. |
michael@0 | 2673 | a2_->SetRemote(TestObserver::ANSWER, a1_->offer(), true, |
michael@0 | 2674 | PCImplSignalingState::SignalingHaveRemoteOffer); |
michael@0 | 2675 | ASSERT_EQ(a2_->pObserver->lastStatusCode, |
michael@0 | 2676 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2677 | } |
michael@0 | 2678 | |
michael@0 | 2679 | // Disabled until the spec adds a failure callback to addStream |
michael@0 | 2680 | TEST_F(SignalingTest, DISABLED_AddStreamInHaveLocalOffer) { |
michael@0 | 2681 | sipcc::MediaConstraints constraints; |
michael@0 | 2682 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2683 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2684 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2685 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2686 | a1_->AddStream(); |
michael@0 | 2687 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2688 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2689 | } |
michael@0 | 2690 | |
michael@0 | 2691 | // Disabled until the spec adds a failure callback to removeStream |
michael@0 | 2692 | TEST_F(SignalingTest, DISABLED_RemoveStreamInHaveLocalOffer) { |
michael@0 | 2693 | sipcc::MediaConstraints constraints; |
michael@0 | 2694 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2695 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2696 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2697 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2698 | a1_->RemoveLastStreamAdded(); |
michael@0 | 2699 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2700 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2701 | } |
michael@0 | 2702 | |
michael@0 | 2703 | TEST_F(SignalingTest, AddCandidateInHaveLocalOffer) { |
michael@0 | 2704 | sipcc::MediaConstraints constraints; |
michael@0 | 2705 | CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2706 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 2707 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2708 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2709 | a1_->AddIceCandidate(strSampleCandidate.c_str(), |
michael@0 | 2710 | strSampleMid.c_str(), nSamplelevel, false); |
michael@0 | 2711 | ASSERT_EQ(a1_->pObserver->lastStatusCode, |
michael@0 | 2712 | sipcc::PeerConnectionImpl::kInvalidState); |
michael@0 | 2713 | } |
michael@0 | 2714 | |
michael@0 | 2715 | TEST_F(SignalingAgentTest, CreateOffer) { |
michael@0 | 2716 | CreateAgent(); |
michael@0 | 2717 | sipcc::MediaConstraints constraints; |
michael@0 | 2718 | agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2719 | PR_Sleep(20000); |
michael@0 | 2720 | } |
michael@0 | 2721 | |
michael@0 | 2722 | TEST_F(SignalingAgentTest, CreateOfferTrickleTestServer) { |
michael@0 | 2723 | TestStunServer::GetInstance()->SetActive(false); |
michael@0 | 2724 | TestStunServer::GetInstance()->SetResponseAddr( |
michael@0 | 2725 | kBogusSrflxAddress, kBogusSrflxPort); |
michael@0 | 2726 | |
michael@0 | 2727 | CreateAgent( |
michael@0 | 2728 | TestStunServer::GetInstance()->addr(), |
michael@0 | 2729 | TestStunServer::GetInstance()->port(), |
michael@0 | 2730 | false); |
michael@0 | 2731 | |
michael@0 | 2732 | sipcc::MediaConstraints constraints; |
michael@0 | 2733 | agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2734 | |
michael@0 | 2735 | // Verify that the bogus addr is not there. |
michael@0 | 2736 | ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress)); |
michael@0 | 2737 | |
michael@0 | 2738 | // Now enable the STUN server. |
michael@0 | 2739 | TestStunServer::GetInstance()->SetActive(true); |
michael@0 | 2740 | agent(0)->WaitForGather(); |
michael@0 | 2741 | |
michael@0 | 2742 | // There shouldn't be any candidates until SetLocal. |
michael@0 | 2743 | ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
michael@0 | 2744 | |
michael@0 | 2745 | // Verify that the candidates appear in the offer. |
michael@0 | 2746 | size_t match; |
michael@0 | 2747 | match = agent(0)->getLocalDescription().find(kBogusSrflxAddress); |
michael@0 | 2748 | ASSERT_LT(0U, match); |
michael@0 | 2749 | } |
michael@0 | 2750 | |
michael@0 | 2751 | TEST_F(SignalingAgentTest, CreateOfferSetLocalTrickleTestServer) { |
michael@0 | 2752 | TestStunServer::GetInstance()->SetActive(false); |
michael@0 | 2753 | TestStunServer::GetInstance()->SetResponseAddr( |
michael@0 | 2754 | kBogusSrflxAddress, kBogusSrflxPort); |
michael@0 | 2755 | |
michael@0 | 2756 | CreateAgent( |
michael@0 | 2757 | TestStunServer::GetInstance()->addr(), |
michael@0 | 2758 | TestStunServer::GetInstance()->port(), |
michael@0 | 2759 | false); |
michael@0 | 2760 | |
michael@0 | 2761 | sipcc::MediaConstraints constraints; |
michael@0 | 2762 | agent(0)->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2763 | |
michael@0 | 2764 | // Verify that the bogus addr is not there. |
michael@0 | 2765 | ASSERT_FALSE(agent(0)->OfferContains(kBogusSrflxAddress)); |
michael@0 | 2766 | |
michael@0 | 2767 | // Now enable the STUN server. |
michael@0 | 2768 | TestStunServer::GetInstance()->SetActive(true); |
michael@0 | 2769 | agent(0)->WaitForGather(); |
michael@0 | 2770 | |
michael@0 | 2771 | // There shouldn't be any candidates until SetLocal. |
michael@0 | 2772 | ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
michael@0 | 2773 | |
michael@0 | 2774 | agent(0)->SetLocal(TestObserver::OFFER, agent(0)->offer()); |
michael@0 | 2775 | PR_Sleep(1000); // Give time for the message queues. |
michael@0 | 2776 | |
michael@0 | 2777 | // Verify that we got our candidates. |
michael@0 | 2778 | ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
michael@0 | 2779 | |
michael@0 | 2780 | // Verify that the candidates appear in the offer. |
michael@0 | 2781 | size_t match; |
michael@0 | 2782 | match = agent(0)->getLocalDescription().find(kBogusSrflxAddress); |
michael@0 | 2783 | ASSERT_LT(0U, match); |
michael@0 | 2784 | } |
michael@0 | 2785 | |
michael@0 | 2786 | |
michael@0 | 2787 | TEST_F(SignalingAgentTest, CreateAnswerSetLocalTrickleTestServer) { |
michael@0 | 2788 | TestStunServer::GetInstance()->SetActive(false); |
michael@0 | 2789 | TestStunServer::GetInstance()->SetResponseAddr( |
michael@0 | 2790 | kBogusSrflxAddress, kBogusSrflxPort); |
michael@0 | 2791 | |
michael@0 | 2792 | CreateAgent( |
michael@0 | 2793 | TestStunServer::GetInstance()->addr(), |
michael@0 | 2794 | TestStunServer::GetInstance()->port(), |
michael@0 | 2795 | false); |
michael@0 | 2796 | |
michael@0 | 2797 | std::string offer(strG711SdpOffer); |
michael@0 | 2798 | agent(0)->SetRemote(TestObserver::OFFER, offer, true, |
michael@0 | 2799 | PCImplSignalingState::SignalingHaveRemoteOffer); |
michael@0 | 2800 | ASSERT_EQ(agent(0)->pObserver->lastStatusCode, |
michael@0 | 2801 | sipcc::PeerConnectionImpl::kNoError); |
michael@0 | 2802 | |
michael@0 | 2803 | sipcc::MediaConstraints constraints; |
michael@0 | 2804 | agent(0)->CreateAnswer(constraints, offer, ANSWER_AUDIO, DONT_CHECK_AUDIO); |
michael@0 | 2805 | |
michael@0 | 2806 | // Verify that the bogus addr is not there. |
michael@0 | 2807 | ASSERT_FALSE(agent(0)->AnswerContains(kBogusSrflxAddress)); |
michael@0 | 2808 | |
michael@0 | 2809 | // Now enable the STUN server. |
michael@0 | 2810 | TestStunServer::GetInstance()->SetActive(true); |
michael@0 | 2811 | agent(0)->WaitForGather(); |
michael@0 | 2812 | |
michael@0 | 2813 | // There shouldn't be any candidates until SetLocal. |
michael@0 | 2814 | ASSERT_EQ(0U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
michael@0 | 2815 | |
michael@0 | 2816 | agent(0)->SetLocal(TestObserver::ANSWER, agent(0)->answer()); |
michael@0 | 2817 | PR_Sleep(1000); // Give time for the message queues. |
michael@0 | 2818 | |
michael@0 | 2819 | // Verify that we got our candidates. |
michael@0 | 2820 | ASSERT_LE(2U, agent(0)->MatchingCandidates(kBogusSrflxAddress)); |
michael@0 | 2821 | |
michael@0 | 2822 | // Verify that the candidates appear in the answer. |
michael@0 | 2823 | size_t match; |
michael@0 | 2824 | match = agent(0)->getLocalDescription().find(kBogusSrflxAddress); |
michael@0 | 2825 | ASSERT_LT(0U, match); |
michael@0 | 2826 | } |
michael@0 | 2827 | |
michael@0 | 2828 | |
michael@0 | 2829 | |
michael@0 | 2830 | TEST_F(SignalingAgentTest, CreateUntilFailThenWait) { |
michael@0 | 2831 | int i; |
michael@0 | 2832 | |
michael@0 | 2833 | for (i=0; ; i++) { |
michael@0 | 2834 | if (!CreateAgent()) |
michael@0 | 2835 | break; |
michael@0 | 2836 | std::cerr << "Created agent " << i << std::endl; |
michael@0 | 2837 | } |
michael@0 | 2838 | std::cerr << "Failed after creating " << i << " PCs " << std::endl; |
michael@0 | 2839 | PR_Sleep(10000); // Wait to see if we crash |
michael@0 | 2840 | } |
michael@0 | 2841 | |
michael@0 | 2842 | // Test for bug 856433. |
michael@0 | 2843 | TEST_F(SignalingAgentTest, CreateNoInit) { |
michael@0 | 2844 | CreateAgentNoInit(); |
michael@0 | 2845 | } |
michael@0 | 2846 | |
michael@0 | 2847 | |
michael@0 | 2848 | /* |
michael@0 | 2849 | * Test for Bug 843595 |
michael@0 | 2850 | */ |
michael@0 | 2851 | TEST_F(SignalingTest, missingUfrag) |
michael@0 | 2852 | { |
michael@0 | 2853 | EnsureInit(); |
michael@0 | 2854 | |
michael@0 | 2855 | sipcc::MediaConstraints constraints; |
michael@0 | 2856 | std::string offer = |
michael@0 | 2857 | "v=0\r\n" |
michael@0 | 2858 | "o=Mozilla-SIPUA 2208 0 IN IP4 0.0.0.0\r\n" |
michael@0 | 2859 | "s=SIP Call\r\n" |
michael@0 | 2860 | "t=0 0\r\n" |
michael@0 | 2861 | "a=ice-pwd:4450d5a4a5f097855c16fa079893be18\r\n" |
michael@0 | 2862 | "a=fingerprint:sha-256 23:9A:2E:43:94:42:CF:46:68:FC:62:F9:F4:48:61:DB:" |
michael@0 | 2863 | "2F:8C:C9:FF:6B:25:54:9D:41:09:EF:83:A8:19:FC:B6\r\n" |
michael@0 | 2864 | "m=audio 56187 RTP/SAVPF 109 0 8 101\r\n" |
michael@0 | 2865 | "c=IN IP4 77.9.79.167\r\n" |
michael@0 | 2866 | "a=rtpmap:109 opus/48000/2\r\n" |
michael@0 | 2867 | "a=ptime:20\r\n" |
michael@0 | 2868 | "a=rtpmap:0 PCMU/8000\r\n" |
michael@0 | 2869 | "a=rtpmap:8 PCMA/8000\r\n" |
michael@0 | 2870 | "a=rtpmap:101 telephone-event/8000\r\n" |
michael@0 | 2871 | "a=fmtp:101 0-15\r\n" |
michael@0 | 2872 | "a=sendrecv\r\n" |
michael@0 | 2873 | "a=candidate:0 1 UDP 2113601791 192.168.178.20 56187 typ host\r\n" |
michael@0 | 2874 | "a=candidate:1 1 UDP 1694236671 77.9.79.167 56187 typ srflx raddr " |
michael@0 | 2875 | "192.168.178.20 rport 56187\r\n" |
michael@0 | 2876 | "a=candidate:0 2 UDP 2113601790 192.168.178.20 52955 typ host\r\n" |
michael@0 | 2877 | "a=candidate:1 2 UDP 1694236670 77.9.79.167 52955 typ srflx raddr " |
michael@0 | 2878 | "192.168.178.20 rport 52955\r\n" |
michael@0 | 2879 | "m=video 49929 RTP/SAVPF 120\r\n" |
michael@0 | 2880 | "c=IN IP4 77.9.79.167\r\n" |
michael@0 | 2881 | "a=rtpmap:120 VP8/90000\r\n" |
michael@0 | 2882 | "a=recvonly\r\n" |
michael@0 | 2883 | "a=candidate:0 1 UDP 2113601791 192.168.178.20 49929 typ host\r\n" |
michael@0 | 2884 | "a=candidate:1 1 UDP 1694236671 77.9.79.167 49929 typ srflx raddr " |
michael@0 | 2885 | "192.168.178.20 rport 49929\r\n" |
michael@0 | 2886 | "a=candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ host\r\n" |
michael@0 | 2887 | "a=candidate:1 2 UDP 1694236670 77.9.79.167 50769 typ srflx raddr " |
michael@0 | 2888 | "192.168.178.20 rport 50769\r\n" |
michael@0 | 2889 | "m=application 54054 DTLS/SCTP 5000\r\n" |
michael@0 | 2890 | "c=IN IP4 77.9.79.167\r\n" |
michael@0 | 2891 | "a=fmtp:HuRUu]Dtcl\\zM,7(OmEU%O$gU]x/z\tD protocol=webrtc-datachannel;" |
michael@0 | 2892 | "streams=16\r\n" |
michael@0 | 2893 | "a=sendrecv\r\n"; |
michael@0 | 2894 | |
michael@0 | 2895 | // Need to create an offer, since that's currently required by our |
michael@0 | 2896 | // FSM. This may change in the future. |
michael@0 | 2897 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2898 | a1_->SetLocal(TestObserver::OFFER, offer, true); |
michael@0 | 2899 | // We now detect the missing ICE parameters at SetRemoteDescription |
michael@0 | 2900 | a2_->SetRemote(TestObserver::OFFER, offer, true, |
michael@0 | 2901 | PCImplSignalingState::SignalingStable); |
michael@0 | 2902 | ASSERT_TRUE(a2_->pObserver->state == TestObserver::stateError); |
michael@0 | 2903 | } |
michael@0 | 2904 | |
michael@0 | 2905 | TEST_F(SignalingTest, AudioOnlyCalleeNoRtcpMux) |
michael@0 | 2906 | { |
michael@0 | 2907 | EnsureInit(); |
michael@0 | 2908 | |
michael@0 | 2909 | sipcc::MediaConstraints constraints; |
michael@0 | 2910 | |
michael@0 | 2911 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 2912 | a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false); |
michael@0 | 2913 | ParsedSDP sdpWrapper(a1_->offer()); |
michael@0 | 2914 | sdpWrapper.DeleteLine("a=rtcp-mux"); |
michael@0 | 2915 | std::cout << "Modified SDP " << std::endl |
michael@0 | 2916 | << indent(sdpWrapper.getSdp()) << std::endl; |
michael@0 | 2917 | a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false); |
michael@0 | 2918 | a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), |
michael@0 | 2919 | OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 2920 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 2921 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 2922 | |
michael@0 | 2923 | // Answer should not have a=rtcp-mux |
michael@0 | 2924 | ASSERT_EQ(a2_->getLocalDescription().find("\r\na=rtcp-mux"), |
michael@0 | 2925 | std::string::npos); |
michael@0 | 2926 | |
michael@0 | 2927 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 2928 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 2929 | |
michael@0 | 2930 | // Wait for some data to get written |
michael@0 | 2931 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2932 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2933 | |
michael@0 | 2934 | a1_->CloseSendStreams(); |
michael@0 | 2935 | a2_->CloseReceiveStreams(); |
michael@0 | 2936 | |
michael@0 | 2937 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2938 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2939 | |
michael@0 | 2940 | // Check the low-level media pipeline |
michael@0 | 2941 | // for RTP and RTCP flows |
michael@0 | 2942 | // The first Local pipeline gets stored at 0 |
michael@0 | 2943 | a1_->CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND); |
michael@0 | 2944 | |
michael@0 | 2945 | // The first Remote pipeline gets stored at 1 |
michael@0 | 2946 | a2_->CheckMediaPipeline(0, 1, 0); |
michael@0 | 2947 | } |
michael@0 | 2948 | |
michael@0 | 2949 | TEST_F(SignalingTest, FullCallAudioNoMuxVideoMux) |
michael@0 | 2950 | { |
michael@0 | 2951 | EnsureInit(); |
michael@0 | 2952 | |
michael@0 | 2953 | sipcc::MediaConstraints constraints; |
michael@0 | 2954 | |
michael@0 | 2955 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
michael@0 | 2956 | a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false); |
michael@0 | 2957 | ParsedSDP sdpWrapper(a1_->offer()); |
michael@0 | 2958 | sdpWrapper.DeleteLine("a=rtcp-mux"); |
michael@0 | 2959 | std::cout << "Modified SDP " << std::endl |
michael@0 | 2960 | << indent(sdpWrapper.getSdp()) << std::endl; |
michael@0 | 2961 | a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false); |
michael@0 | 2962 | a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); |
michael@0 | 2963 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 2964 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 2965 | |
michael@0 | 2966 | // Answer should have only one a=rtcp-mux line |
michael@0 | 2967 | size_t match = a2_->getLocalDescription().find("\r\na=rtcp-mux"); |
michael@0 | 2968 | if (fRtcpMux) { |
michael@0 | 2969 | ASSERT_NE(match, std::string::npos); |
michael@0 | 2970 | match = a2_->getLocalDescription().find("\r\na=rtcp-mux", match + 1); |
michael@0 | 2971 | } |
michael@0 | 2972 | ASSERT_EQ(match, std::string::npos); |
michael@0 | 2973 | |
michael@0 | 2974 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 2975 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 2976 | |
michael@0 | 2977 | // Wait for some data to get written |
michael@0 | 2978 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 2979 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 2980 | |
michael@0 | 2981 | a1_->CloseSendStreams(); |
michael@0 | 2982 | a2_->CloseReceiveStreams(); |
michael@0 | 2983 | |
michael@0 | 2984 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 2985 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 2986 | |
michael@0 | 2987 | // Check the low-level media pipeline |
michael@0 | 2988 | // for RTP and RTCP flows |
michael@0 | 2989 | // The first Local pipeline gets stored at 0 |
michael@0 | 2990 | a1_->CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND); |
michael@0 | 2991 | |
michael@0 | 2992 | // Now check video mux. |
michael@0 | 2993 | a1_->CheckMediaPipeline(0, 1, |
michael@0 | 2994 | PIPELINE_LOCAL | (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | PIPELINE_SEND | |
michael@0 | 2995 | PIPELINE_VIDEO); |
michael@0 | 2996 | |
michael@0 | 2997 | // The first Remote pipeline gets stored at 1 |
michael@0 | 2998 | a2_->CheckMediaPipeline(0, 1, 0); |
michael@0 | 2999 | |
michael@0 | 3000 | // Now check video mux. |
michael@0 | 3001 | a2_->CheckMediaPipeline(0, 2, (fRtcpMux ? PIPELINE_RTCP_MUX : 0) | |
michael@0 | 3002 | PIPELINE_VIDEO | PIPELINE_RTCP_NACK, VideoSessionConduit::FrameRequestPli); |
michael@0 | 3003 | } |
michael@0 | 3004 | |
michael@0 | 3005 | TEST_F(SignalingTest, RtcpFbInOffer) |
michael@0 | 3006 | { |
michael@0 | 3007 | EnsureInit(); |
michael@0 | 3008 | sipcc::MediaConstraints constraints; |
michael@0 | 3009 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
michael@0 | 3010 | const char *expected[] = { "nack", "nack pli", "ccm fir" }; |
michael@0 | 3011 | CheckRtcpFbSdp(a1_->offer(), ARRAY_TO_SET(std::string, expected)); |
michael@0 | 3012 | } |
michael@0 | 3013 | |
michael@0 | 3014 | TEST_F(SignalingTest, RtcpFbInAnswer) |
michael@0 | 3015 | { |
michael@0 | 3016 | const char *feedbackTypes[] = { "nack", "nack pli", "ccm fir" }; |
michael@0 | 3017 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3018 | PIPELINE_RTCP_NACK, |
michael@0 | 3019 | VideoSessionConduit::FrameRequestPli); |
michael@0 | 3020 | } |
michael@0 | 3021 | |
michael@0 | 3022 | TEST_F(SignalingTest, RtcpFbNoNackBasic) |
michael@0 | 3023 | { |
michael@0 | 3024 | const char *feedbackTypes[] = { "nack pli", "ccm fir" }; |
michael@0 | 3025 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3026 | 0, |
michael@0 | 3027 | VideoSessionConduit::FrameRequestPli); |
michael@0 | 3028 | } |
michael@0 | 3029 | |
michael@0 | 3030 | TEST_F(SignalingTest, RtcpFbNoNackPli) |
michael@0 | 3031 | { |
michael@0 | 3032 | const char *feedbackTypes[] = { "nack", "ccm fir" }; |
michael@0 | 3033 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3034 | PIPELINE_RTCP_NACK, |
michael@0 | 3035 | VideoSessionConduit::FrameRequestFir); |
michael@0 | 3036 | } |
michael@0 | 3037 | |
michael@0 | 3038 | TEST_F(SignalingTest, RtcpFbNoCcmFir) |
michael@0 | 3039 | { |
michael@0 | 3040 | const char *feedbackTypes[] = { "nack", "nack pli" }; |
michael@0 | 3041 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3042 | PIPELINE_RTCP_NACK, |
michael@0 | 3043 | VideoSessionConduit::FrameRequestPli); |
michael@0 | 3044 | } |
michael@0 | 3045 | |
michael@0 | 3046 | TEST_F(SignalingTest, RtcpFbNoNack) |
michael@0 | 3047 | { |
michael@0 | 3048 | const char *feedbackTypes[] = { "ccm fir" }; |
michael@0 | 3049 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3050 | 0, |
michael@0 | 3051 | VideoSessionConduit::FrameRequestFir); |
michael@0 | 3052 | } |
michael@0 | 3053 | |
michael@0 | 3054 | TEST_F(SignalingTest, RtcpFbNoFrameRequest) |
michael@0 | 3055 | { |
michael@0 | 3056 | const char *feedbackTypes[] = { "nack" }; |
michael@0 | 3057 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3058 | PIPELINE_RTCP_NACK, |
michael@0 | 3059 | VideoSessionConduit::FrameRequestNone); |
michael@0 | 3060 | } |
michael@0 | 3061 | |
michael@0 | 3062 | TEST_F(SignalingTest, RtcpFbPliOnly) |
michael@0 | 3063 | { |
michael@0 | 3064 | const char *feedbackTypes[] = { "nack pli" }; |
michael@0 | 3065 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3066 | 0, |
michael@0 | 3067 | VideoSessionConduit::FrameRequestPli); |
michael@0 | 3068 | } |
michael@0 | 3069 | |
michael@0 | 3070 | TEST_F(SignalingTest, RtcpFbNoFeedback) |
michael@0 | 3071 | { |
michael@0 | 3072 | const char *feedbackTypes[] = { }; |
michael@0 | 3073 | TestRtcpFb(ARRAY_TO_SET(std::string, feedbackTypes), |
michael@0 | 3074 | 0, |
michael@0 | 3075 | VideoSessionConduit::FrameRequestNone); |
michael@0 | 3076 | } |
michael@0 | 3077 | |
michael@0 | 3078 | // In this test we will change the offer SDP's a=setup value |
michael@0 | 3079 | // from actpass to passive. This will make the answer do active. |
michael@0 | 3080 | TEST_F(SignalingTest, AudioCallForceDtlsRoles) |
michael@0 | 3081 | { |
michael@0 | 3082 | EnsureInit(); |
michael@0 | 3083 | |
michael@0 | 3084 | sipcc::MediaConstraints constraints; |
michael@0 | 3085 | size_t match; |
michael@0 | 3086 | |
michael@0 | 3087 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 3088 | |
michael@0 | 3089 | // By default the offer should give actpass |
michael@0 | 3090 | std::string offer(a1_->offer()); |
michael@0 | 3091 | match = offer.find("\r\na=setup:actpass"); |
michael@0 | 3092 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3093 | // Now replace the actpass with passive so that the answer will |
michael@0 | 3094 | // return active |
michael@0 | 3095 | offer.replace(match, strlen("\r\na=setup:actpass"), |
michael@0 | 3096 | "\r\na=setup:passive"); |
michael@0 | 3097 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3098 | << indent(offer) << std::endl; |
michael@0 | 3099 | |
michael@0 | 3100 | a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3101 | a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3102 | a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 3103 | |
michael@0 | 3104 | // Now the answer should contain a=setup:active |
michael@0 | 3105 | std::string answer(a2_->answer()); |
michael@0 | 3106 | match = answer.find("\r\na=setup:active"); |
michael@0 | 3107 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3108 | |
michael@0 | 3109 | // This should setup the DTLS with the same roles |
michael@0 | 3110 | // as the regular tests above. |
michael@0 | 3111 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3112 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3113 | |
michael@0 | 3114 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3115 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3116 | |
michael@0 | 3117 | // Wait for some data to get written |
michael@0 | 3118 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3119 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3120 | |
michael@0 | 3121 | a1_->CloseSendStreams(); |
michael@0 | 3122 | a2_->CloseReceiveStreams(); |
michael@0 | 3123 | |
michael@0 | 3124 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3125 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3126 | } |
michael@0 | 3127 | |
michael@0 | 3128 | // In this test we will change the offer SDP's a=setup value |
michael@0 | 3129 | // from actpass to active. This will make the answer do passive |
michael@0 | 3130 | TEST_F(SignalingTest, AudioCallReverseDtlsRoles) |
michael@0 | 3131 | { |
michael@0 | 3132 | EnsureInit(); |
michael@0 | 3133 | |
michael@0 | 3134 | sipcc::MediaConstraints constraints; |
michael@0 | 3135 | size_t match; |
michael@0 | 3136 | |
michael@0 | 3137 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 3138 | |
michael@0 | 3139 | // By default the offer should give actpass |
michael@0 | 3140 | std::string offer(a1_->offer()); |
michael@0 | 3141 | match = offer.find("\r\na=setup:actpass"); |
michael@0 | 3142 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3143 | // Now replace the actpass with active so that the answer will |
michael@0 | 3144 | // return passive |
michael@0 | 3145 | offer.replace(match, strlen("\r\na=setup:actpass"), |
michael@0 | 3146 | "\r\na=setup:active"); |
michael@0 | 3147 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3148 | << indent(offer) << std::endl; |
michael@0 | 3149 | |
michael@0 | 3150 | a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3151 | a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3152 | a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 3153 | |
michael@0 | 3154 | // Now the answer should contain a=setup:passive |
michael@0 | 3155 | std::string answer(a2_->answer()); |
michael@0 | 3156 | match = answer.find("\r\na=setup:passive"); |
michael@0 | 3157 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3158 | |
michael@0 | 3159 | // This should setup the DTLS with the opposite roles |
michael@0 | 3160 | // than the regular tests above. |
michael@0 | 3161 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3162 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3163 | |
michael@0 | 3164 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3165 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3166 | |
michael@0 | 3167 | // Wait for some data to get written |
michael@0 | 3168 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3169 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3170 | |
michael@0 | 3171 | a1_->CloseSendStreams(); |
michael@0 | 3172 | a2_->CloseReceiveStreams(); |
michael@0 | 3173 | |
michael@0 | 3174 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3175 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3176 | } |
michael@0 | 3177 | |
michael@0 | 3178 | // In this test we will change the answer SDP's a=setup value |
michael@0 | 3179 | // from active to passive. This will make both sides do |
michael@0 | 3180 | // active and should not connect. |
michael@0 | 3181 | TEST_F(SignalingTest, AudioCallMismatchDtlsRoles) |
michael@0 | 3182 | { |
michael@0 | 3183 | EnsureInit(); |
michael@0 | 3184 | |
michael@0 | 3185 | sipcc::MediaConstraints constraints; |
michael@0 | 3186 | size_t match; |
michael@0 | 3187 | |
michael@0 | 3188 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 3189 | |
michael@0 | 3190 | // By default the offer should give actpass |
michael@0 | 3191 | std::string offer(a1_->offer()); |
michael@0 | 3192 | match = offer.find("\r\na=setup:actpass"); |
michael@0 | 3193 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3194 | a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3195 | a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3196 | a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 3197 | |
michael@0 | 3198 | // Now the answer should contain a=setup:active |
michael@0 | 3199 | std::string answer(a2_->answer()); |
michael@0 | 3200 | match = answer.find("\r\na=setup:active"); |
michael@0 | 3201 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3202 | |
michael@0 | 3203 | // Now replace the active with passive so that the offerer will |
michael@0 | 3204 | // also do active. |
michael@0 | 3205 | answer.replace(match, strlen("\r\na=setup:active"), |
michael@0 | 3206 | "\r\na=setup:passive"); |
michael@0 | 3207 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3208 | << indent(answer) << std::endl; |
michael@0 | 3209 | |
michael@0 | 3210 | // This should setup the DTLS with both sides playing active |
michael@0 | 3211 | a2_->SetLocal(TestObserver::ANSWER, answer.c_str(), false); |
michael@0 | 3212 | a1_->SetRemote(TestObserver::ANSWER, answer.c_str(), false); |
michael@0 | 3213 | |
michael@0 | 3214 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3215 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3216 | |
michael@0 | 3217 | // Not using ASSERT_TRUE_WAIT here because we expect failure |
michael@0 | 3218 | PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written |
michael@0 | 3219 | |
michael@0 | 3220 | a1_->CloseSendStreams(); |
michael@0 | 3221 | a2_->CloseReceiveStreams(); |
michael@0 | 3222 | |
michael@0 | 3223 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3224 | // In this case we should receive nothing. |
michael@0 | 3225 | ASSERT_EQ(a2_->GetPacketsReceived(0), 0); |
michael@0 | 3226 | } |
michael@0 | 3227 | |
michael@0 | 3228 | // In this test we will change the offer SDP's a=setup value |
michael@0 | 3229 | // from actpass to garbage. It should ignore the garbage value |
michael@0 | 3230 | // and respond with setup:active |
michael@0 | 3231 | TEST_F(SignalingTest, AudioCallGarbageSetup) |
michael@0 | 3232 | { |
michael@0 | 3233 | EnsureInit(); |
michael@0 | 3234 | |
michael@0 | 3235 | sipcc::MediaConstraints constraints; |
michael@0 | 3236 | size_t match; |
michael@0 | 3237 | |
michael@0 | 3238 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 3239 | |
michael@0 | 3240 | // By default the offer should give actpass |
michael@0 | 3241 | std::string offer(a1_->offer()); |
michael@0 | 3242 | match = offer.find("\r\na=setup:actpass"); |
michael@0 | 3243 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3244 | // Now replace the actpass with a garbage value |
michael@0 | 3245 | offer.replace(match, strlen("\r\na=setup:actpass"), |
michael@0 | 3246 | "\r\na=setup:G4rb4g3V4lu3"); |
michael@0 | 3247 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3248 | << indent(offer) << std::endl; |
michael@0 | 3249 | |
michael@0 | 3250 | a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3251 | a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3252 | a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 3253 | |
michael@0 | 3254 | // Now the answer should contain a=setup:active |
michael@0 | 3255 | std::string answer(a2_->answer()); |
michael@0 | 3256 | match = answer.find("\r\na=setup:active"); |
michael@0 | 3257 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3258 | |
michael@0 | 3259 | // This should setup the DTLS with the same roles |
michael@0 | 3260 | // as the regular tests above. |
michael@0 | 3261 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3262 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3263 | |
michael@0 | 3264 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3265 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3266 | |
michael@0 | 3267 | // Wait for some data to get written |
michael@0 | 3268 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3269 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3270 | |
michael@0 | 3271 | a1_->CloseSendStreams(); |
michael@0 | 3272 | a2_->CloseReceiveStreams(); |
michael@0 | 3273 | |
michael@0 | 3274 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3275 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3276 | } |
michael@0 | 3277 | |
michael@0 | 3278 | // In this test we will change the offer SDP to remove the |
michael@0 | 3279 | // a=setup line. Answer should respond with a=setup:active. |
michael@0 | 3280 | TEST_F(SignalingTest, AudioCallOfferNoSetupOrConnection) |
michael@0 | 3281 | { |
michael@0 | 3282 | EnsureInit(); |
michael@0 | 3283 | |
michael@0 | 3284 | sipcc::MediaConstraints constraints; |
michael@0 | 3285 | size_t match; |
michael@0 | 3286 | |
michael@0 | 3287 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 3288 | |
michael@0 | 3289 | // By default the offer should give setup:actpass |
michael@0 | 3290 | std::string offer(a1_->offer()); |
michael@0 | 3291 | match = offer.find("\r\na=setup:actpass"); |
michael@0 | 3292 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3293 | // Remove the a=setup line |
michael@0 | 3294 | offer.replace(match, strlen("\r\na=setup:actpass"), ""); |
michael@0 | 3295 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3296 | << indent(offer) << std::endl; |
michael@0 | 3297 | |
michael@0 | 3298 | a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3299 | a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3300 | a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 3301 | |
michael@0 | 3302 | // Now the answer should contain a=setup:active |
michael@0 | 3303 | std::string answer(a2_->answer()); |
michael@0 | 3304 | match = answer.find("\r\na=setup:active"); |
michael@0 | 3305 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3306 | |
michael@0 | 3307 | // This should setup the DTLS with the same roles |
michael@0 | 3308 | // as the regular tests above. |
michael@0 | 3309 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3310 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false); |
michael@0 | 3311 | |
michael@0 | 3312 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3313 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3314 | |
michael@0 | 3315 | // Wait for some data to get written |
michael@0 | 3316 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3317 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3318 | |
michael@0 | 3319 | a1_->CloseSendStreams(); |
michael@0 | 3320 | a2_->CloseReceiveStreams(); |
michael@0 | 3321 | |
michael@0 | 3322 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3323 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3324 | } |
michael@0 | 3325 | |
michael@0 | 3326 | // In this test we will change the answer SDP to remove the |
michael@0 | 3327 | // a=setup line. ICE should still connect since active will |
michael@0 | 3328 | // be assumed. |
michael@0 | 3329 | TEST_F(SignalingTest, AudioCallAnswerNoSetupOrConnection) |
michael@0 | 3330 | { |
michael@0 | 3331 | EnsureInit(); |
michael@0 | 3332 | |
michael@0 | 3333 | sipcc::MediaConstraints constraints; |
michael@0 | 3334 | size_t match; |
michael@0 | 3335 | |
michael@0 | 3336 | a1_->CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO); |
michael@0 | 3337 | |
michael@0 | 3338 | // By default the offer should give setup:actpass |
michael@0 | 3339 | std::string offer(a1_->offer()); |
michael@0 | 3340 | match = offer.find("\r\na=setup:actpass"); |
michael@0 | 3341 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3342 | |
michael@0 | 3343 | a1_->SetLocal(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3344 | a2_->SetRemote(TestObserver::OFFER, offer.c_str(), false); |
michael@0 | 3345 | a2_->CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO); |
michael@0 | 3346 | |
michael@0 | 3347 | // Now the answer should contain a=setup:active |
michael@0 | 3348 | std::string answer(a2_->answer()); |
michael@0 | 3349 | match = answer.find("\r\na=setup:active"); |
michael@0 | 3350 | ASSERT_NE(match, std::string::npos); |
michael@0 | 3351 | // Remove the a=setup line |
michael@0 | 3352 | answer.replace(match, strlen("\r\na=setup:active"), ""); |
michael@0 | 3353 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3354 | << indent(answer) << std::endl; |
michael@0 | 3355 | |
michael@0 | 3356 | // This should setup the DTLS with the same roles |
michael@0 | 3357 | // as the regular tests above. |
michael@0 | 3358 | a2_->SetLocal(TestObserver::ANSWER, answer, false); |
michael@0 | 3359 | a1_->SetRemote(TestObserver::ANSWER, answer, false); |
michael@0 | 3360 | |
michael@0 | 3361 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3362 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3363 | |
michael@0 | 3364 | // Wait for some data to get written |
michael@0 | 3365 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3366 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3367 | |
michael@0 | 3368 | a1_->CloseSendStreams(); |
michael@0 | 3369 | a2_->CloseReceiveStreams(); |
michael@0 | 3370 | |
michael@0 | 3371 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3372 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3373 | } |
michael@0 | 3374 | |
michael@0 | 3375 | |
michael@0 | 3376 | TEST_F(SignalingTest, FullCallRealTrickle) |
michael@0 | 3377 | { |
michael@0 | 3378 | wait_for_gather_ = false; |
michael@0 | 3379 | |
michael@0 | 3380 | sipcc::MediaConstraints constraints; |
michael@0 | 3381 | OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, |
michael@0 | 3382 | true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 3383 | |
michael@0 | 3384 | // Wait for some data to get written |
michael@0 | 3385 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3386 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3387 | |
michael@0 | 3388 | a1_->CloseSendStreams(); |
michael@0 | 3389 | a2_->CloseReceiveStreams(); |
michael@0 | 3390 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3391 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3392 | } |
michael@0 | 3393 | |
michael@0 | 3394 | TEST_F(SignalingTest, FullCallRealTrickleTestServer) |
michael@0 | 3395 | { |
michael@0 | 3396 | wait_for_gather_ = false; |
michael@0 | 3397 | SetTestStunServer(); |
michael@0 | 3398 | |
michael@0 | 3399 | sipcc::MediaConstraints constraints; |
michael@0 | 3400 | OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV, |
michael@0 | 3401 | true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV); |
michael@0 | 3402 | |
michael@0 | 3403 | TestStunServer::GetInstance()->SetActive(true); |
michael@0 | 3404 | |
michael@0 | 3405 | // Wait for some data to get written |
michael@0 | 3406 | ASSERT_TRUE_WAIT(a1_->GetPacketsSent(0) >= 40 && |
michael@0 | 3407 | a2_->GetPacketsReceived(0) >= 40, kDefaultTimeout * 2); |
michael@0 | 3408 | |
michael@0 | 3409 | a1_->CloseSendStreams(); |
michael@0 | 3410 | a2_->CloseReceiveStreams(); |
michael@0 | 3411 | ASSERT_GE(a1_->GetPacketsSent(0), 40); |
michael@0 | 3412 | ASSERT_GE(a2_->GetPacketsReceived(0), 40); |
michael@0 | 3413 | } |
michael@0 | 3414 | |
michael@0 | 3415 | TEST_F(SignalingTest, hugeSdp) |
michael@0 | 3416 | { |
michael@0 | 3417 | EnsureInit(); |
michael@0 | 3418 | |
michael@0 | 3419 | sipcc::MediaConstraints constraints; |
michael@0 | 3420 | std::string offer = |
michael@0 | 3421 | "v=0\r\n" |
michael@0 | 3422 | "o=- 1109973417102828257 2 IN IP4 127.0.0.1\r\n" |
michael@0 | 3423 | "s=-\r\n" |
michael@0 | 3424 | "t=0 0\r\n" |
michael@0 | 3425 | "a=group:BUNDLE audio video\r\n" |
michael@0 | 3426 | "a=msid-semantic: WMS 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n" |
michael@0 | 3427 | "m=audio 32952 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\n" |
michael@0 | 3428 | "c=IN IP4 128.64.32.16\r\n" |
michael@0 | 3429 | "a=rtcp:32952 IN IP4 128.64.32.16\r\n" |
michael@0 | 3430 | "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" |
michael@0 | 3431 | "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" |
michael@0 | 3432 | "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" |
michael@0 | 3433 | "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" |
michael@0 | 3434 | "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" |
michael@0 | 3435 | "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" |
michael@0 | 3436 | "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" |
michael@0 | 3437 | "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" |
michael@0 | 3438 | "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" |
michael@0 | 3439 | "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" |
michael@0 | 3440 | "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" |
michael@0 | 3441 | "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" |
michael@0 | 3442 | "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" |
michael@0 | 3443 | "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" |
michael@0 | 3444 | "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" |
michael@0 | 3445 | "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" |
michael@0 | 3446 | "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n" |
michael@0 | 3447 | "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n" |
michael@0 | 3448 | "a=ice-options:google-ice\r\n" |
michael@0 | 3449 | "a=fingerprint:sha-256 59:4A:8B:73:A7:73:53:71:88:D7:4D:58:28:0C:79:72:31:29:9B:05:37:DD:58:43:C2:D4:85:A2:B3:66:38:7A\r\n" |
michael@0 | 3450 | "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" |
michael@0 | 3451 | "a=sendrecv\r\n" |
michael@0 | 3452 | "a=mid:audio\r\n" |
michael@0 | 3453 | "a=rtcp-mux\r\n" |
michael@0 | 3454 | "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n" |
michael@0 | 3455 | "a=rtpmap:111 opus/48000/2\r\n" |
michael@0 | 3456 | "a=fmtp:111 minptime=10\r\n" |
michael@0 | 3457 | "a=rtpmap:103 ISAC/16000\r\n" |
michael@0 | 3458 | "a=rtpmap:104 ISAC/32000\r\n" |
michael@0 | 3459 | "a=rtpmap:0 PCMU/8000\r\n" |
michael@0 | 3460 | "a=rtpmap:8 PCMA/8000\r\n" |
michael@0 | 3461 | "a=rtpmap:107 CN/48000\r\n" |
michael@0 | 3462 | "a=rtpmap:106 CN/32000\r\n" |
michael@0 | 3463 | "a=rtpmap:105 CN/16000\r\n" |
michael@0 | 3464 | "a=rtpmap:13 CN/8000\r\n" |
michael@0 | 3465 | "a=rtpmap:126 telephone-event/8000\r\n" |
michael@0 | 3466 | "a=maxptime:60\r\n" |
michael@0 | 3467 | "a=ssrc:2271517329 cname:mKDNt7SQf6pwDlIn\r\n" |
michael@0 | 3468 | "a=ssrc:2271517329 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n" |
michael@0 | 3469 | "a=ssrc:2271517329 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n" |
michael@0 | 3470 | "a=ssrc:2271517329 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n" |
michael@0 | 3471 | "m=video 32952 RTP/SAVPF 100 116 117\r\n" |
michael@0 | 3472 | "c=IN IP4 128.64.32.16\r\n" |
michael@0 | 3473 | "a=rtcp:32952 IN IP4 128.64.32.16\r\n" |
michael@0 | 3474 | "a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" |
michael@0 | 3475 | "a=candidate:77142221 2 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n" |
michael@0 | 3476 | "a=candidate:983072742 1 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" |
michael@0 | 3477 | "a=candidate:983072742 2 udp 2113937151 172.22.0.56 54082 typ host generation 0\r\n" |
michael@0 | 3478 | "a=candidate:2245074553 1 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" |
michael@0 | 3479 | "a=candidate:2245074553 2 udp 1845501695 32.64.128.1 62397 typ srflx raddr 192.168.137.1 rport 54081 generation 0\r\n" |
michael@0 | 3480 | "a=candidate:2479353907 1 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" |
michael@0 | 3481 | "a=candidate:2479353907 2 udp 1845501695 32.64.128.1 54082 typ srflx raddr 172.22.0.56 rport 54082 generation 0\r\n" |
michael@0 | 3482 | "a=candidate:1243276349 1 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" |
michael@0 | 3483 | "a=candidate:1243276349 2 tcp 1509957375 192.168.137.1 0 typ host generation 0\r\n" |
michael@0 | 3484 | "a=candidate:1947960086 1 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" |
michael@0 | 3485 | "a=candidate:1947960086 2 tcp 1509957375 172.22.0.56 0 typ host generation 0\r\n" |
michael@0 | 3486 | "a=candidate:1808221584 1 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" |
michael@0 | 3487 | "a=candidate:1808221584 2 udp 33562367 128.64.32.16 32952 typ relay raddr 32.64.128.1 rport 62398 generation 0\r\n" |
michael@0 | 3488 | "a=candidate:507872740 1 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" |
michael@0 | 3489 | "a=candidate:507872740 2 udp 33562367 128.64.32.16 40975 typ relay raddr 32.64.128.1 rport 54085 generation 0\r\n" |
michael@0 | 3490 | "a=ice-ufrag:xQuJwjX3V3eMA81k\r\n" |
michael@0 | 3491 | "a=ice-pwd:ZUiRmjS2GDhG140p73dAsSVP\r\n" |
michael@0 | 3492 | "a=ice-options:google-ice\r\n" |
michael@0 | 3493 | "a=fingerprint:sha-256 59:4A:8B:73:A7:73:53:71:88:D7:4D:58:28:0C:79:72:31:29:9B:05:37:DD:58:43:C2:D4:85:A2:B3:66:38:7A\r\n" |
michael@0 | 3494 | "a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n" |
michael@0 | 3495 | "a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" |
michael@0 | 3496 | "a=sendrecv\r\n" |
michael@0 | 3497 | "a=mid:video\r\n" |
michael@0 | 3498 | "a=rtcp-mux\r\n" |
michael@0 | 3499 | "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:/U44g3ULdtapeiSg+T3n6dDLBKIjpOhb/NXAL/2b\r\n" |
michael@0 | 3500 | "a=rtpmap:100 VP8/90000\r\n" |
michael@0 | 3501 | "a=rtcp-fb:100 ccm fir\r\n" |
michael@0 | 3502 | "a=rtcp-fb:100 nack\r\n" |
michael@0 | 3503 | "a=rtcp-fb:100 goog-remb\r\n" |
michael@0 | 3504 | "a=rtpmap:116 red/90000\r\n" |
michael@0 | 3505 | "a=rtpmap:117 ulpfec/90000\r\n" |
michael@0 | 3506 | "a=ssrc:54724160 cname:mKDNt7SQf6pwDlIn\r\n" |
michael@0 | 3507 | "a=ssrc:54724160 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n" |
michael@0 | 3508 | "a=ssrc:54724160 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n" |
michael@0 | 3509 | "a=ssrc:54724160 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPv0\r\n"; |
michael@0 | 3510 | |
michael@0 | 3511 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV); |
michael@0 | 3512 | a1_->SetLocal(TestObserver::OFFER, offer, true); |
michael@0 | 3513 | |
michael@0 | 3514 | a2_->SetRemote(TestObserver::OFFER, offer, true); |
michael@0 | 3515 | ASSERT_GE(a2_->getRemoteDescription().length(), 4096U); |
michael@0 | 3516 | a2_->CreateAnswer(constraints, offer, OFFER_AV); |
michael@0 | 3517 | } |
michael@0 | 3518 | |
michael@0 | 3519 | // Test max_fs and max_fr prefs have proper impact on SDP offer |
michael@0 | 3520 | TEST_F(SignalingTest, MaxFsFrInOffer) |
michael@0 | 3521 | { |
michael@0 | 3522 | EnsureInit(); |
michael@0 | 3523 | |
michael@0 | 3524 | sipcc::MediaConstraints constraints; |
michael@0 | 3525 | |
michael@0 | 3526 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
michael@0 | 3527 | ASSERT_TRUE(prefs); |
michael@0 | 3528 | FsFrPrefClearer prefClearer(prefs); |
michael@0 | 3529 | |
michael@0 | 3530 | SetMaxFsFr(prefs, 300, 30); |
michael@0 | 3531 | |
michael@0 | 3532 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
michael@0 | 3533 | |
michael@0 | 3534 | // Verify that SDP contains correct max-fs and max-fr |
michael@0 | 3535 | CheckMaxFsFrSdp(a1_->offer(), 120, 300, 30); |
michael@0 | 3536 | } |
michael@0 | 3537 | |
michael@0 | 3538 | // Test max_fs and max_fr prefs have proper impact on SDP answer |
michael@0 | 3539 | TEST_F(SignalingTest, MaxFsFrInAnswer) |
michael@0 | 3540 | { |
michael@0 | 3541 | EnsureInit(); |
michael@0 | 3542 | |
michael@0 | 3543 | sipcc::MediaConstraints constraints; |
michael@0 | 3544 | |
michael@0 | 3545 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
michael@0 | 3546 | ASSERT_TRUE(prefs); |
michael@0 | 3547 | FsFrPrefClearer prefClearer(prefs); |
michael@0 | 3548 | |
michael@0 | 3549 | // We don't want max_fs and max_fr prefs impact SDP at this moment |
michael@0 | 3550 | SetMaxFsFr(prefs, 0, 0); |
michael@0 | 3551 | |
michael@0 | 3552 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
michael@0 | 3553 | |
michael@0 | 3554 | // SDP should not contain max-fs and max-fr here |
michael@0 | 3555 | CheckMaxFsFrSdp(a1_->offer(), 120, 0, 0); |
michael@0 | 3556 | |
michael@0 | 3557 | a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
michael@0 | 3558 | |
michael@0 | 3559 | SetMaxFsFr(prefs, 600, 60); |
michael@0 | 3560 | |
michael@0 | 3561 | a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); |
michael@0 | 3562 | |
michael@0 | 3563 | // Verify that SDP contains correct max-fs and max-fr |
michael@0 | 3564 | CheckMaxFsFrSdp(a2_->answer(), 120, 600, 60); |
michael@0 | 3565 | } |
michael@0 | 3566 | |
michael@0 | 3567 | // Test SDP offer has proper impact on callee's codec configuration |
michael@0 | 3568 | TEST_F(SignalingTest, MaxFsFrCalleeCodec) |
michael@0 | 3569 | { |
michael@0 | 3570 | EnsureInit(); |
michael@0 | 3571 | |
michael@0 | 3572 | sipcc::MediaConstraints constraints; |
michael@0 | 3573 | |
michael@0 | 3574 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
michael@0 | 3575 | ASSERT_TRUE(prefs); |
michael@0 | 3576 | FsFrPrefClearer prefClearer(prefs); |
michael@0 | 3577 | |
michael@0 | 3578 | // We don't want max_fs and max_fr prefs impact SDP at this moment |
michael@0 | 3579 | SetMaxFsFr(prefs, 0, 0); |
michael@0 | 3580 | |
michael@0 | 3581 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
michael@0 | 3582 | |
michael@0 | 3583 | ParsedSDP sdpWrapper(a1_->offer()); |
michael@0 | 3584 | |
michael@0 | 3585 | sdpWrapper.ReplaceLine("a=rtpmap:120", |
michael@0 | 3586 | "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=300;max-fr=30\r\n"); |
michael@0 | 3587 | |
michael@0 | 3588 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3589 | << indent(sdpWrapper.getSdp()) << std::endl; |
michael@0 | 3590 | |
michael@0 | 3591 | // Double confirm that SDP offer contains correct max-fs and max-fr |
michael@0 | 3592 | CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 300, 30); |
michael@0 | 3593 | |
michael@0 | 3594 | a1_->SetLocal(TestObserver::OFFER, sdpWrapper.getSdp()); |
michael@0 | 3595 | a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp()); |
michael@0 | 3596 | |
michael@0 | 3597 | a2_->CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV); |
michael@0 | 3598 | |
michael@0 | 3599 | // SDP should not contain max-fs and max-fr here |
michael@0 | 3600 | CheckMaxFsFrSdp(a2_->answer(), 120, 0, 0); |
michael@0 | 3601 | |
michael@0 | 3602 | a2_->SetLocal(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 3603 | a1_->SetRemote(TestObserver::ANSWER, a2_->answer()); |
michael@0 | 3604 | |
michael@0 | 3605 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3606 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3607 | |
michael@0 | 3608 | // Checking callee's video sending configuration does respect max-fs and |
michael@0 | 3609 | // max-fr in SDP offer. |
michael@0 | 3610 | mozilla::RefPtr<mozilla::MediaPipeline> pipeline = |
michael@0 | 3611 | a2_->GetMediaPipeline(1, 0, 1); |
michael@0 | 3612 | ASSERT_TRUE(pipeline); |
michael@0 | 3613 | mozilla::MediaSessionConduit *conduit = pipeline->Conduit(); |
michael@0 | 3614 | ASSERT_TRUE(conduit); |
michael@0 | 3615 | ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO); |
michael@0 | 3616 | mozilla::VideoSessionConduit *video_conduit = |
michael@0 | 3617 | static_cast<mozilla::VideoSessionConduit*>(conduit); |
michael@0 | 3618 | |
michael@0 | 3619 | ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 300); |
michael@0 | 3620 | ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 30); |
michael@0 | 3621 | } |
michael@0 | 3622 | |
michael@0 | 3623 | // Test SDP answer has proper impact on caller's codec configuration |
michael@0 | 3624 | TEST_F(SignalingTest, MaxFsFrCallerCodec) |
michael@0 | 3625 | { |
michael@0 | 3626 | EnsureInit(); |
michael@0 | 3627 | |
michael@0 | 3628 | sipcc::MediaConstraints constraints; |
michael@0 | 3629 | |
michael@0 | 3630 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); |
michael@0 | 3631 | ASSERT_TRUE(prefs); |
michael@0 | 3632 | FsFrPrefClearer prefClearer(prefs); |
michael@0 | 3633 | |
michael@0 | 3634 | // We don't want max_fs and max_fr prefs impact SDP at this moment |
michael@0 | 3635 | SetMaxFsFr(prefs, 0, 0); |
michael@0 | 3636 | |
michael@0 | 3637 | a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); |
michael@0 | 3638 | a1_->SetLocal(TestObserver::OFFER, a1_->offer()); |
michael@0 | 3639 | a2_->SetRemote(TestObserver::OFFER, a1_->offer()); |
michael@0 | 3640 | |
michael@0 | 3641 | a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); |
michael@0 | 3642 | |
michael@0 | 3643 | ParsedSDP sdpWrapper(a2_->answer()); |
michael@0 | 3644 | |
michael@0 | 3645 | sdpWrapper.ReplaceLine("a=rtpmap:120", |
michael@0 | 3646 | "a=rtpmap:120 VP8/90000\r\na=fmtp:120 max-fs=600;max-fr=60\r\n"); |
michael@0 | 3647 | |
michael@0 | 3648 | std::cout << "Modified SDP " << std::endl |
michael@0 | 3649 | << indent(sdpWrapper.getSdp()) << std::endl; |
michael@0 | 3650 | |
michael@0 | 3651 | // Double confirm that SDP answer contains correct max-fs and max-fr |
michael@0 | 3652 | CheckMaxFsFrSdp(sdpWrapper.getSdp(), 120, 600, 60); |
michael@0 | 3653 | |
michael@0 | 3654 | a2_->SetLocal(TestObserver::ANSWER, sdpWrapper.getSdp()); |
michael@0 | 3655 | a1_->SetRemote(TestObserver::ANSWER, sdpWrapper.getSdp()); |
michael@0 | 3656 | |
michael@0 | 3657 | ASSERT_TRUE_WAIT(a1_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3658 | ASSERT_TRUE_WAIT(a2_->IceCompleted() == true, kDefaultTimeout); |
michael@0 | 3659 | |
michael@0 | 3660 | // Checking caller's video sending configuration does respect max-fs and |
michael@0 | 3661 | // max-fr in SDP answer. |
michael@0 | 3662 | mozilla::RefPtr<mozilla::MediaPipeline> pipeline = |
michael@0 | 3663 | a1_->GetMediaPipeline(1, 0, 1); |
michael@0 | 3664 | ASSERT_TRUE(pipeline); |
michael@0 | 3665 | mozilla::MediaSessionConduit *conduit = pipeline->Conduit(); |
michael@0 | 3666 | ASSERT_TRUE(conduit); |
michael@0 | 3667 | ASSERT_EQ(conduit->type(), mozilla::MediaSessionConduit::VIDEO); |
michael@0 | 3668 | mozilla::VideoSessionConduit *video_conduit = |
michael@0 | 3669 | static_cast<mozilla::VideoSessionConduit*>(conduit); |
michael@0 | 3670 | |
michael@0 | 3671 | ASSERT_EQ(video_conduit->SendingMaxFs(), (unsigned short) 600); |
michael@0 | 3672 | ASSERT_EQ(video_conduit->SendingMaxFr(), (unsigned short) 60); |
michael@0 | 3673 | } |
michael@0 | 3674 | |
michael@0 | 3675 | } // End namespace test. |
michael@0 | 3676 | |
michael@0 | 3677 | bool is_color_terminal(const char *terminal) { |
michael@0 | 3678 | if (!terminal) { |
michael@0 | 3679 | return false; |
michael@0 | 3680 | } |
michael@0 | 3681 | const char *color_terms[] = { |
michael@0 | 3682 | "xterm", |
michael@0 | 3683 | "xterm-color", |
michael@0 | 3684 | "xterm-256color", |
michael@0 | 3685 | "screen", |
michael@0 | 3686 | "linux", |
michael@0 | 3687 | "cygwin", |
michael@0 | 3688 | 0 |
michael@0 | 3689 | }; |
michael@0 | 3690 | const char **p = color_terms; |
michael@0 | 3691 | while (*p) { |
michael@0 | 3692 | if (!strcmp(terminal, *p)) { |
michael@0 | 3693 | return true; |
michael@0 | 3694 | } |
michael@0 | 3695 | p++; |
michael@0 | 3696 | } |
michael@0 | 3697 | return false; |
michael@0 | 3698 | } |
michael@0 | 3699 | |
michael@0 | 3700 | static std::string get_environment(const char *name) { |
michael@0 | 3701 | char *value = getenv(name); |
michael@0 | 3702 | |
michael@0 | 3703 | if (!value) |
michael@0 | 3704 | return ""; |
michael@0 | 3705 | |
michael@0 | 3706 | return value; |
michael@0 | 3707 | } |
michael@0 | 3708 | |
michael@0 | 3709 | // This exists to send as an event to trigger shutdown. |
michael@0 | 3710 | static void tests_complete() { |
michael@0 | 3711 | gTestsComplete = true; |
michael@0 | 3712 | } |
michael@0 | 3713 | |
michael@0 | 3714 | // The GTest thread runs this instead of the main thread so it can |
michael@0 | 3715 | // do things like ASSERT_TRUE_WAIT which you could not do on the main thread. |
michael@0 | 3716 | static int gtest_main(int argc, char **argv) { |
michael@0 | 3717 | MOZ_ASSERT(!NS_IsMainThread()); |
michael@0 | 3718 | |
michael@0 | 3719 | ::testing::InitGoogleTest(&argc, argv); |
michael@0 | 3720 | |
michael@0 | 3721 | for(int i=0; i<argc; i++) { |
michael@0 | 3722 | if (!strcmp(argv[i],"-t")) { |
michael@0 | 3723 | kDefaultTimeout = 20000; |
michael@0 | 3724 | } |
michael@0 | 3725 | } |
michael@0 | 3726 | |
michael@0 | 3727 | ::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment); |
michael@0 | 3728 | int result = RUN_ALL_TESTS(); |
michael@0 | 3729 | |
michael@0 | 3730 | test_utils->sts_target()->Dispatch( |
michael@0 | 3731 | WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC); |
michael@0 | 3732 | |
michael@0 | 3733 | // Set the global shutdown flag and tickle the main thread |
michael@0 | 3734 | // The main thread did not go through Init() so calling Shutdown() |
michael@0 | 3735 | // on it will not work. |
michael@0 | 3736 | gMainThread->Dispatch(WrapRunnableNM(tests_complete), NS_DISPATCH_SYNC); |
michael@0 | 3737 | |
michael@0 | 3738 | return result; |
michael@0 | 3739 | } |
michael@0 | 3740 | |
michael@0 | 3741 | |
michael@0 | 3742 | int main(int argc, char **argv) { |
michael@0 | 3743 | |
michael@0 | 3744 | // This test can cause intermittent oranges on the builders |
michael@0 | 3745 | CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS") |
michael@0 | 3746 | |
michael@0 | 3747 | if (isatty(STDOUT_FILENO) && is_color_terminal(getenv("TERM"))) { |
michael@0 | 3748 | std::string ansiMagenta = "\x1b[35m"; |
michael@0 | 3749 | std::string ansiCyan = "\x1b[36m"; |
michael@0 | 3750 | std::string ansiColorOff = "\x1b[0m"; |
michael@0 | 3751 | callerName = ansiCyan + callerName + ansiColorOff; |
michael@0 | 3752 | calleeName = ansiMagenta + calleeName + ansiColorOff; |
michael@0 | 3753 | } |
michael@0 | 3754 | |
michael@0 | 3755 | std::string tmp = get_environment("STUN_SERVER_ADDRESS"); |
michael@0 | 3756 | if (tmp != "") |
michael@0 | 3757 | g_stun_server_address = tmp; |
michael@0 | 3758 | |
michael@0 | 3759 | tmp = get_environment("STUN_SERVER_PORT"); |
michael@0 | 3760 | if (tmp != "") |
michael@0 | 3761 | g_stun_server_port = atoi(tmp.c_str()); |
michael@0 | 3762 | |
michael@0 | 3763 | test_utils = new MtransportTestUtils(); |
michael@0 | 3764 | NSS_NoDB_Init(nullptr); |
michael@0 | 3765 | NSS_SetDomesticPolicy(); |
michael@0 | 3766 | |
michael@0 | 3767 | ::testing::TestEventListeners& listeners = |
michael@0 | 3768 | ::testing::UnitTest::GetInstance()->listeners(); |
michael@0 | 3769 | // Adds a listener to the end. Google Test takes the ownership. |
michael@0 | 3770 | listeners.Append(new test::RingbufferDumper(test_utils)); |
michael@0 | 3771 | test_utils->sts_target()->Dispatch( |
michael@0 | 3772 | WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC); |
michael@0 | 3773 | |
michael@0 | 3774 | // Set the main thread global which is this thread. |
michael@0 | 3775 | nsIThread *thread; |
michael@0 | 3776 | NS_GetMainThread(&thread); |
michael@0 | 3777 | gMainThread = thread; |
michael@0 | 3778 | MOZ_ASSERT(NS_IsMainThread()); |
michael@0 | 3779 | |
michael@0 | 3780 | // Now create the GTest thread and run all of the tests on it |
michael@0 | 3781 | // When it is complete it will set gTestsComplete |
michael@0 | 3782 | NS_NewNamedThread("gtest_thread", &thread); |
michael@0 | 3783 | gGtestThread = thread; |
michael@0 | 3784 | |
michael@0 | 3785 | int result; |
michael@0 | 3786 | gGtestThread->Dispatch( |
michael@0 | 3787 | WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL); |
michael@0 | 3788 | |
michael@0 | 3789 | // Here we handle the event queue for dispatches to the main thread |
michael@0 | 3790 | // When the GTest thread is complete it will send one more dispatch |
michael@0 | 3791 | // with gTestsComplete == true. |
michael@0 | 3792 | while (!gTestsComplete && NS_ProcessNextEvent()); |
michael@0 | 3793 | |
michael@0 | 3794 | gGtestThread->Shutdown(); |
michael@0 | 3795 | |
michael@0 | 3796 | sipcc::PeerConnectionCtx::Destroy(); |
michael@0 | 3797 | delete test_utils; |
michael@0 | 3798 | |
michael@0 | 3799 | return result; |
michael@0 | 3800 | } |