SignalingManagerInternalTest.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. using System;
  2. using System.Linq;
  3. using System.Collections;
  4. using NUnit.Framework;
  5. using Unity.RenderStreaming.RuntimeTest.Signaling;
  6. using Unity.WebRTC;
  7. using UnityEngine;
  8. using UnityEngine.TestTools;
  9. namespace Unity.RenderStreaming.RuntimeTest
  10. {
  11. enum TestMode
  12. {
  13. PrivateMode,
  14. PublicMode
  15. }
  16. static class SignalingManagerInternalExtension
  17. {
  18. public static RTCRtpTransceiver AddSenderTrack(this SignalingManagerInternal target, string connectionId, MediaStreamTrack track)
  19. {
  20. RTCRtpTransceiverInit init = new RTCRtpTransceiverInit() { direction = RTCRtpTransceiverDirection.SendOnly };
  21. return target.AddTransceiver(connectionId, track, init);
  22. }
  23. }
  24. class SignalingManagerInternalTest
  25. {
  26. class MyMonoBehaviourTest : MonoBehaviour, IMonoBehaviourTest
  27. {
  28. public bool IsTestFinished
  29. {
  30. get { return true; }
  31. }
  32. }
  33. private MonoBehaviourTest<MyMonoBehaviourTest> test;
  34. [SetUp]
  35. public void SetUp()
  36. {
  37. test = new MonoBehaviourTest<MyMonoBehaviourTest>();
  38. }
  39. [TearDown]
  40. public void TearDown()
  41. {
  42. test.component.StopAllCoroutines();
  43. UnityEngine.Object.Destroy(test.gameObject);
  44. }
  45. // workaround: More time for SetDescription process
  46. const float ResendOfferInterval = 3f;
  47. private RenderStreamingDependencies CreateDependencies()
  48. {
  49. return new RenderStreamingDependencies
  50. {
  51. signaling = new MockSignaling(),
  52. config = new RTCConfiguration
  53. {
  54. iceServers = new[] { new RTCIceServer { urls = new[] { "stun:stun.l.google.com:19302" } } },
  55. },
  56. startCoroutine = test.component.StartCoroutine,
  57. stopCoroutine = test.component.StopCoroutine,
  58. resentOfferInterval = ResendOfferInterval,
  59. };
  60. }
  61. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  62. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  63. [UnityTest, Timeout(10000)]
  64. public IEnumerator Construct(TestMode mode)
  65. {
  66. MockSignaling.Reset(mode == TestMode.PrivateMode);
  67. var dependencies = CreateDependencies();
  68. var target = new SignalingManagerInternal(ref dependencies);
  69. bool isStarted = false;
  70. target.onStart += () => { isStarted = true; };
  71. yield return new WaitUntil(() => isStarted);
  72. Assert.That(isStarted, Is.True);
  73. target.Dispose();
  74. }
  75. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  76. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  77. [UnityTest, Timeout(10000)]
  78. public IEnumerator ConstructMultiple(TestMode mode)
  79. {
  80. MockSignaling.Reset(mode == TestMode.PrivateMode);
  81. var dependencies1 = CreateDependencies();
  82. var dependencies2 = CreateDependencies();
  83. var target1 = new SignalingManagerInternal(ref dependencies1);
  84. var target2 = new SignalingManagerInternal(ref dependencies2);
  85. bool isStarted1 = false;
  86. bool isStarted2 = false;
  87. target1.onStart += () => { isStarted1 = true; };
  88. target2.onStart += () => { isStarted2 = true; };
  89. yield return new WaitUntil(() => isStarted1);
  90. yield return new WaitUntil(() => isStarted2);
  91. Assert.That(isStarted1, Is.True);
  92. Assert.That(isStarted2, Is.True);
  93. target1.Dispose();
  94. target2.Dispose();
  95. }
  96. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  97. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  98. [UnityTest, Timeout(10000)]
  99. public IEnumerator OpenConnection(TestMode mode)
  100. {
  101. MockSignaling.Reset(mode == TestMode.PrivateMode);
  102. var dependencies = CreateDependencies();
  103. var target = new SignalingManagerInternal(ref dependencies);
  104. bool isStarted = false;
  105. target.onStart += () => { isStarted = true; };
  106. yield return new WaitUntil(() => isStarted);
  107. Assert.That(isStarted, Is.True);
  108. string connectionId = "12345";
  109. Assert.That(target.ExistConnection(connectionId), Is.False);
  110. target.CreateConnection(connectionId);
  111. bool isCreatedConnection = false;
  112. target.onCreatedConnection += _ => { isCreatedConnection = true; };
  113. yield return new WaitUntil(() => isCreatedConnection);
  114. Assert.That(isCreatedConnection, Is.True);
  115. Assert.That(target.ExistConnection(connectionId), Is.True);
  116. target.DeleteConnection(connectionId);
  117. bool isDeletedConnection = false;
  118. target.onDeletedConnection += _ => { isDeletedConnection = true; };
  119. yield return new WaitUntil(() => isDeletedConnection);
  120. Assert.That(isDeletedConnection, Is.True);
  121. Assert.That(target.ExistConnection(connectionId), Is.False);
  122. target.Dispose();
  123. }
  124. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  125. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  126. [UnityTest, Timeout(10000)]
  127. public IEnumerator OpenConnectionThrowException(TestMode mode)
  128. {
  129. MockSignaling.Reset(mode == TestMode.PrivateMode);
  130. var dependencies = CreateDependencies();
  131. var target = new SignalingManagerInternal(ref dependencies);
  132. bool isStarted = false;
  133. target.onStart += () => { isStarted = true; };
  134. yield return new WaitUntil(() => isStarted);
  135. Assert.That(isStarted, Is.True);
  136. Assert.That(() => target.CreateConnection(null), Throws.TypeOf<ArgumentException>());
  137. Assert.That(() => target.CreateConnection(string.Empty), Throws.TypeOf<ArgumentException>());
  138. target.Dispose();
  139. }
  140. //todo:: crash in dispose process on standalone linux
  141. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  142. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  143. [UnityTest, Timeout(10000)]
  144. [UnityPlatform(exclude = new[] { RuntimePlatform.LinuxPlayer })]
  145. public IEnumerator AddTrack(TestMode mode)
  146. {
  147. MockSignaling.Reset(mode == TestMode.PrivateMode);
  148. var dependencies = CreateDependencies();
  149. var target = new SignalingManagerInternal(ref dependencies);
  150. bool isStarted = false;
  151. target.onStart += () => { isStarted = true; };
  152. yield return new WaitUntil(() => isStarted);
  153. Assert.That(isStarted, Is.True);
  154. var connectionId = "12345";
  155. bool isCreatedConnection = false;
  156. target.onCreatedConnection += _ => { isCreatedConnection = true; };
  157. target.CreateConnection(connectionId);
  158. yield return new WaitUntil(() => isCreatedConnection);
  159. Assert.That(isCreatedConnection, Is.True);
  160. Assert.That(target.GetTransceivers(connectionId).Count(), Is.EqualTo(0));
  161. var camObj = new GameObject("Camera");
  162. var camera = camObj.AddComponent<Camera>();
  163. VideoStreamTrack track = camera.CaptureStreamTrack(1280, 720);
  164. var transceiver = target.AddSenderTrack(connectionId, track);
  165. Assert.That(transceiver.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
  166. Assert.That(target.GetTransceivers(connectionId).Count(), Is.EqualTo(1));
  167. target.RemoveSenderTrack(connectionId, track);
  168. bool isDeletedConnection = false;
  169. target.onDeletedConnection += _ => { isDeletedConnection = true; };
  170. target.DeleteConnection(connectionId);
  171. yield return new WaitUntil(() => isDeletedConnection);
  172. Assert.That(isDeletedConnection, Is.True);
  173. target.Dispose();
  174. track.Dispose();
  175. UnityEngine.Object.Destroy(camObj);
  176. }
  177. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  178. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  179. [UnityTest]
  180. public IEnumerator AddTrackThrowException(TestMode mode)
  181. {
  182. MockSignaling.Reset(mode == TestMode.PrivateMode);
  183. var dependencies = CreateDependencies();
  184. var target = new SignalingManagerInternal(ref dependencies);
  185. bool isStarted = false;
  186. target.onStart += () => { isStarted = true; };
  187. yield return new WaitUntil(() => isStarted);
  188. Assert.That(isStarted, Is.True);
  189. var connectionId = "12345";
  190. target.CreateConnection(connectionId);
  191. bool isCreatedConnection = false;
  192. target.onCreatedConnection += _ => { isCreatedConnection = true; };
  193. yield return new WaitUntil(() => isCreatedConnection);
  194. Assert.That(isCreatedConnection, Is.True);
  195. Assert.That(() => target.AddSenderTrack(null, null), Throws.TypeOf<ArgumentNullException>());
  196. Assert.That(() => target.AddSenderTrack(connectionId, null), Throws.TypeOf<ArgumentNullException>());
  197. Assert.That(() => target.RemoveSenderTrack(null, null), Throws.TypeOf<ArgumentNullException>());
  198. Assert.That(() => target.RemoveSenderTrack(connectionId, null), Throws.TypeOf<InvalidOperationException>());
  199. target.DeleteConnection(connectionId);
  200. bool isDeletedConnection = false;
  201. target.onDeletedConnection += _ => { isDeletedConnection = true; };
  202. yield return new WaitUntil(() => isDeletedConnection);
  203. Assert.That(isDeletedConnection, Is.True);
  204. target.Dispose();
  205. }
  206. //todo:: crash in dispose process on standalone linux
  207. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  208. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  209. [UnityTest, Timeout(10000)]
  210. [UnityPlatform(exclude = new[] { RuntimePlatform.LinuxPlayer })]
  211. public IEnumerator AddTrackMultiple(TestMode mode)
  212. {
  213. MockSignaling.Reset(mode == TestMode.PrivateMode);
  214. var dependencies = CreateDependencies();
  215. var target = new SignalingManagerInternal(ref dependencies);
  216. bool isStarted = false;
  217. target.onStart += () => { isStarted = true; };
  218. yield return new WaitUntil(() => isStarted);
  219. Assert.That(isStarted, Is.True);
  220. var connectionId = "12345";
  221. target.CreateConnection(connectionId);
  222. bool isCreatedConnection = false;
  223. target.onCreatedConnection += _ => { isCreatedConnection = true; };
  224. yield return new WaitUntil(() => isCreatedConnection);
  225. Assert.That(isCreatedConnection, Is.True);
  226. var camObj = new GameObject("Camera");
  227. var camera = camObj.AddComponent<Camera>();
  228. VideoStreamTrack track = camera.CaptureStreamTrack(1280, 720);
  229. var transceiver1 = target.AddSenderTrack(connectionId, track);
  230. Assert.That(transceiver1.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
  231. var camObj2 = new GameObject("Camera2");
  232. var camera2 = camObj2.AddComponent<Camera>();
  233. VideoStreamTrack track2 = camera2.CaptureStreamTrack(1280, 720);
  234. var transceiver2 = target.AddSenderTrack(connectionId, track2);
  235. Assert.That(transceiver2.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
  236. target.DeleteConnection(connectionId);
  237. bool isDeletedConnection = false;
  238. target.onDeletedConnection += _ => { isDeletedConnection = true; };
  239. yield return new WaitUntil(() => isDeletedConnection);
  240. Assert.That(isDeletedConnection, Is.True);
  241. target.Dispose();
  242. track.Dispose();
  243. track2.Dispose();
  244. UnityEngine.Object.Destroy(camObj);
  245. UnityEngine.Object.Destroy(camObj2);
  246. }
  247. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  248. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  249. [UnityTest, Timeout(10000)]
  250. public IEnumerator CreateChannel(TestMode mode)
  251. {
  252. MockSignaling.Reset(mode == TestMode.PrivateMode);
  253. var dependencies = CreateDependencies();
  254. var target = new SignalingManagerInternal(ref dependencies);
  255. bool isStarted = false;
  256. target.onStart += () => { isStarted = true; };
  257. yield return new WaitUntil(() => isStarted);
  258. Assert.That(isStarted, Is.True);
  259. var connectionId = "12345";
  260. target.CreateConnection(connectionId);
  261. bool isCreatedConnection = false;
  262. target.onCreatedConnection += _ => { isCreatedConnection = true; };
  263. yield return new WaitUntil(() => isCreatedConnection);
  264. string channelName = "test";
  265. var channel = target.CreateChannel(connectionId, channelName);
  266. Assert.That(channel.Label, Is.EqualTo(channelName));
  267. target.DeleteConnection(connectionId);
  268. bool isDeletedConnection = false;
  269. target.onDeletedConnection += _ => { isDeletedConnection = true; };
  270. yield return new WaitUntil(() => isDeletedConnection);
  271. Assert.That(isDeletedConnection, Is.True);
  272. target.Dispose();
  273. channel.Dispose();
  274. }
  275. //todo:: crash in dispose process on standalone linux
  276. [UnityTest, Timeout(10000)]
  277. [UnityPlatform(exclude = new[] { RuntimePlatform.LinuxPlayer, RuntimePlatform.Android })]
  278. public IEnumerator OnAddReceiverPrivateMode()
  279. {
  280. MockSignaling.Reset(true);
  281. var dependencies1 = CreateDependencies();
  282. var dependencies2 = CreateDependencies();
  283. var target1 = new SignalingManagerInternal(ref dependencies1);
  284. var target2 = new SignalingManagerInternal(ref dependencies2);
  285. bool isStarted1 = false;
  286. bool isStarted2 = false;
  287. target1.onStart += () => { isStarted1 = true; };
  288. target2.onStart += () => { isStarted2 = true; };
  289. yield return new WaitUntil(() => isStarted1 && isStarted2);
  290. Assert.That(isStarted1, Is.True);
  291. Assert.That(isStarted2, Is.True);
  292. bool isCreatedConnection1 = false;
  293. bool isCreatedConnection2 = false;
  294. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  295. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  296. var connectionId = "12345";
  297. // target1 is Receiver in private mode
  298. target1.CreateConnection(connectionId);
  299. yield return new WaitUntil(() => isCreatedConnection1);
  300. Assert.That(isCreatedConnection1, Is.True);
  301. // target2 is sender in private mode
  302. target2.CreateConnection(connectionId);
  303. yield return new WaitUntil(() => isCreatedConnection2);
  304. Assert.That(isCreatedConnection2, Is.True);
  305. bool isAddReceiver1 = false;
  306. bool isGotAnswer2 = false;
  307. target1.onAddTransceiver += (_, receiver) => { isAddReceiver1 = true; };
  308. target1.onGotOffer += (_, sdp) => { target1.SendAnswer(connectionId); };
  309. target2.onGotAnswer += (_, sdp) => { isGotAnswer2 = true; };
  310. var camObj = new GameObject("Camera");
  311. var camera = camObj.AddComponent<Camera>();
  312. VideoStreamTrack track = camera.CaptureStreamTrack(1280, 720);
  313. // send offer automatically after adding a Track
  314. var transceiver = target2.AddSenderTrack(connectionId, track);
  315. Assert.That(transceiver, Is.Not.Null);
  316. Assert.That(transceiver.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
  317. yield return new WaitUntil(() => isAddReceiver1 && isGotAnswer2);
  318. Assert.That(isAddReceiver1, Is.True);
  319. Assert.That(isGotAnswer2, Is.True);
  320. target1.DeleteConnection(connectionId);
  321. target2.DeleteConnection(connectionId);
  322. bool isDeletedConnection1 = false;
  323. bool isDeletedConnection2 = false;
  324. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  325. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  326. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  327. Assert.That(isDeletedConnection1, Is.True);
  328. Assert.That(isDeletedConnection2, Is.True);
  329. target1.Dispose();
  330. target2.Dispose();
  331. track.Dispose();
  332. UnityEngine.Object.Destroy(camObj);
  333. }
  334. //todo:: crash in dispose process on standalone linux
  335. [UnityTest, Timeout(10000)]
  336. [UnityPlatform(exclude = new[] { RuntimePlatform.LinuxPlayer, RuntimePlatform.Android })]
  337. public IEnumerator OnAddReceiverPublicMode()
  338. {
  339. MockSignaling.Reset(false);
  340. var dependencies1 = CreateDependencies();
  341. var dependencies2 = CreateDependencies();
  342. var target1 = new SignalingManagerInternal(ref dependencies1);
  343. var target2 = new SignalingManagerInternal(ref dependencies2);
  344. bool isStarted1 = false;
  345. bool isStarted2 = false;
  346. target1.onStart += () => { isStarted1 = true; };
  347. target2.onStart += () => { isStarted2 = true; };
  348. yield return new WaitUntil(() => isStarted1 && isStarted2);
  349. Assert.That(isStarted1, Is.True);
  350. Assert.That(isStarted2, Is.True);
  351. bool isCreatedConnection1 = false;
  352. bool isOnGotOffer2 = false;
  353. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  354. target2.onGotOffer += (_, sdp) => { isOnGotOffer2 = true; };
  355. var connectionId = "12345";
  356. // target1 is Receiver in public mode
  357. target1.CreateConnection(connectionId);
  358. yield return new WaitUntil(() => isCreatedConnection1);
  359. Assert.That(isCreatedConnection1, Is.True);
  360. RTCRtpTransceiverInit init = new RTCRtpTransceiverInit()
  361. {
  362. direction = RTCRtpTransceiverDirection.RecvOnly
  363. };
  364. target1.AddTransceiver(connectionId, TrackKind.Video, init);
  365. // target2 is sender in private mode
  366. yield return new WaitUntil(() => isOnGotOffer2);
  367. Assert.That(isOnGotOffer2, Is.True);
  368. bool isAddReceiver1 = false;
  369. bool isGotAnswer1 = false;
  370. target1.onAddTransceiver += (_, receiver) => { isAddReceiver1 = true; };
  371. target1.onGotAnswer += (_, sdp) => { isGotAnswer1 = true; };
  372. var camObj = new GameObject("Camera");
  373. var camera = camObj.AddComponent<Camera>();
  374. VideoStreamTrack track = camera.CaptureStreamTrack(1280, 720);
  375. var transceiver2 = target2.AddSenderTrack(connectionId, track);
  376. Assert.That(transceiver2.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
  377. target2.SendAnswer(connectionId);
  378. yield return new WaitUntil(() => isAddReceiver1 & isGotAnswer1);
  379. target1.DeleteConnection(connectionId);
  380. target2.DeleteConnection(connectionId);
  381. bool isDeletedConnection1 = false;
  382. bool isDeletedConnection2 = false;
  383. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  384. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  385. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  386. Assert.That(isDeletedConnection1, Is.True);
  387. Assert.That(isDeletedConnection2, Is.True);
  388. target1.Dispose();
  389. target2.Dispose();
  390. track.Dispose();
  391. UnityEngine.Object.DestroyImmediate(camObj);
  392. }
  393. [UnityTest, Timeout(10000)]
  394. public IEnumerator OnAddChannelPrivateMode()
  395. {
  396. MockSignaling.Reset(true);
  397. var dependencies1 = CreateDependencies();
  398. var dependencies2 = CreateDependencies();
  399. var target1 = new SignalingManagerInternal(ref dependencies1);
  400. var target2 = new SignalingManagerInternal(ref dependencies2);
  401. bool isStarted1 = false;
  402. bool isStarted2 = false;
  403. target1.onStart += () => { isStarted1 = true; };
  404. target2.onStart += () => { isStarted2 = true; };
  405. yield return new WaitUntil(() => isStarted1 && isStarted2);
  406. bool isCreatedConnection1 = false;
  407. bool isCreatedConnection2 = false;
  408. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  409. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  410. var connectionId = "12345";
  411. // target1 is Receiver in private mode
  412. target1.CreateConnection(connectionId);
  413. yield return new WaitUntil(() => isCreatedConnection1);
  414. // target2 is sender in private mode
  415. target2.CreateConnection(connectionId);
  416. yield return new WaitUntil(() => isCreatedConnection2);
  417. bool isAddChannel1 = false;
  418. bool isGotOffer1 = false;
  419. bool isGotAnswer2 = false;
  420. target1.onAddChannel += (_, _channel) => { isAddChannel1 = true; };
  421. target1.onGotOffer += (_, sdp) => { isGotOffer1 = true; };
  422. target2.onGotAnswer += (_, sdp) => { isGotAnswer2 = true; };
  423. // send offer automatically after creating channel
  424. RTCDataChannel channel = target2.CreateChannel(connectionId, "test");
  425. Assert.That(channel, Is.Not.Null);
  426. yield return new WaitUntil(() => isGotOffer1);
  427. Assert.That(isGotOffer1, Is.True);
  428. target1.SendAnswer(connectionId);
  429. yield return new WaitUntil(() => isAddChannel1 && isGotAnswer2);
  430. Assert.That(isAddChannel1, Is.True);
  431. Assert.That(isGotAnswer2, Is.True);
  432. target1.DeleteConnection(connectionId);
  433. target2.DeleteConnection(connectionId);
  434. bool isDeletedConnection1 = false;
  435. bool isDeletedConnection2 = false;
  436. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  437. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  438. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  439. Assert.That(isDeletedConnection1, Is.True);
  440. Assert.That(isDeletedConnection2, Is.True);
  441. target1.Dispose();
  442. target2.Dispose();
  443. }
  444. [UnityTest, Timeout(10000), LongRunning]
  445. public IEnumerator SendOfferThrowExceptionPrivateMode()
  446. {
  447. MockSignaling.Reset(true);
  448. var dependencies1 = CreateDependencies();
  449. var dependencies2 = CreateDependencies();
  450. var target1 = new SignalingManagerInternal(ref dependencies1);
  451. var target2 = new SignalingManagerInternal(ref dependencies2);
  452. bool isStarted1 = false;
  453. bool isStarted2 = false;
  454. target1.onStart += () => { isStarted1 = true; };
  455. target2.onStart += () => { isStarted2 = true; };
  456. yield return new WaitUntil(() => isStarted1 && isStarted2);
  457. bool isCreatedConnection1 = false;
  458. bool isCreatedConnection2 = false;
  459. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  460. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  461. var connectionId = "12345";
  462. // target1 is Receiver in private mode
  463. target1.CreateConnection(connectionId);
  464. yield return new WaitUntil(() => isCreatedConnection1);
  465. // target2 is sender in private mode
  466. target2.CreateConnection(connectionId);
  467. yield return new WaitUntil(() => isCreatedConnection2);
  468. bool isGotOffer1 = false;
  469. bool isGotAnswer2 = false;
  470. target1.onGotOffer += (_, sdp) => { isGotOffer1 = true; };
  471. target2.onGotAnswer += (_, sdp) => { isGotAnswer2 = true; };
  472. target2.SendOffer(connectionId);
  473. // each peer are not stable, signaling process not complete.
  474. yield return new WaitUntil(() => isGotOffer1);
  475. Assert.That(target1.IsStable(connectionId), Is.False);
  476. Assert.That(target2.IsStable(connectionId), Is.False);
  477. Assert.That(() => target1.SendOffer(connectionId), Throws.TypeOf<InvalidOperationException>());
  478. target1.SendAnswer(connectionId);
  479. yield return new WaitUntil(() => isGotAnswer2);
  480. Assert.That(isGotAnswer2, Is.True);
  481. // If target1 processes resent Offer from target2, target1 is not stable.
  482. Assert.That(target2.IsStable(connectionId), Is.True);
  483. target1.DeleteConnection(connectionId);
  484. target2.DeleteConnection(connectionId);
  485. bool isDeletedConnection1 = false;
  486. bool isDeletedConnection2 = false;
  487. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  488. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  489. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  490. Assert.That(isDeletedConnection1, Is.True);
  491. Assert.That(isDeletedConnection2, Is.True);
  492. target1.Dispose();
  493. target2.Dispose();
  494. }
  495. [UnityTest, Timeout(30000), LongRunning]
  496. public IEnumerator SwapTransceiverPrivateMode()
  497. {
  498. MockSignaling.Reset(true);
  499. var dependencies1 = CreateDependencies();
  500. var dependencies2 = CreateDependencies();
  501. var target1 = new SignalingManagerInternal(ref dependencies1);
  502. var target2 = new SignalingManagerInternal(ref dependencies2);
  503. bool isStarted1 = false;
  504. bool isStarted2 = false;
  505. target1.onStart += () => { isStarted1 = true; };
  506. target2.onStart += () => { isStarted2 = true; };
  507. yield return new WaitUntil(() => isStarted1 && isStarted2);
  508. Assert.That(isStarted1, Is.True);
  509. Assert.That(isStarted2, Is.True);
  510. bool isCreatedConnection1 = false;
  511. bool isCreatedConnection2 = false;
  512. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  513. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  514. var connectionId = "12345";
  515. // target1 has impolite peer (request first)
  516. target1.CreateConnection(connectionId);
  517. yield return new WaitUntil(() => isCreatedConnection1);
  518. Assert.That(isCreatedConnection1, Is.True);
  519. // target2 has polite peer (request second)
  520. target2.CreateConnection(connectionId);
  521. yield return new WaitUntil(() => isCreatedConnection2);
  522. Assert.That(isCreatedConnection2, Is.True);
  523. bool isGotOffer1 = false;
  524. bool isGotOffer2 = false;
  525. bool isGotAnswer1 = false;
  526. target1.onGotOffer += (_, sdp) => { isGotOffer1 = true; };
  527. target2.onGotOffer += (_, sdp) => { isGotOffer2 = true; };
  528. target1.onGotAnswer += (_, sdp) => { isGotAnswer1 = true; };
  529. RTCRtpTransceiverInit init1 = new RTCRtpTransceiverInit()
  530. {
  531. direction = RTCRtpTransceiverDirection.SendOnly
  532. };
  533. RTCRtpTransceiverInit init2 = new RTCRtpTransceiverInit()
  534. {
  535. direction = RTCRtpTransceiverDirection.SendOnly
  536. };
  537. target1.AddTransceiver(connectionId, TrackKind.Audio, init1);
  538. target2.AddTransceiver(connectionId, TrackKind.Audio, init2);
  539. // check each target invoke onGotOffer
  540. yield return new WaitForSeconds(ResendOfferInterval * 5);
  541. // ignore offer because impolite peer
  542. Assert.That(isGotOffer1, Is.False, $"{nameof(isGotOffer1)} is not False.");
  543. // accept offer because polite peer
  544. Assert.That(isGotOffer2, Is.True, $"{nameof(isGotOffer2)} is not True.");
  545. target2.SendAnswer(connectionId);
  546. yield return new WaitUntil(() => isGotAnswer1);
  547. Assert.That(isGotAnswer1, Is.True, $"{nameof(isGotAnswer1)} is not True.");
  548. target1.DeleteConnection(connectionId);
  549. target2.DeleteConnection(connectionId);
  550. bool isDeletedConnection1 = false;
  551. bool isDeletedConnection2 = false;
  552. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  553. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  554. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  555. Assert.That(isDeletedConnection1, Is.True, $"{nameof(isDeletedConnection1)} is not True.");
  556. Assert.That(isDeletedConnection2, Is.True, $"{nameof(isDeletedConnection2)} is not True.");
  557. target1.Dispose();
  558. target2.Dispose();
  559. }
  560. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  561. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  562. [UnityTest, Timeout(30000), LongRunning]
  563. public IEnumerator ResendOfferUntilGotAnswer(TestMode mode)
  564. {
  565. MockSignaling.Reset(mode == TestMode.PrivateMode);
  566. var dependencies1 = CreateDependencies();
  567. var dependencies2 = CreateDependencies();
  568. var target1 = new SignalingManagerInternal(ref dependencies1);
  569. var target2 = new SignalingManagerInternal(ref dependencies2);
  570. bool isStarted1 = false;
  571. bool isStarted2 = false;
  572. target1.onStart += () => { isStarted1 = true; };
  573. target2.onStart += () => { isStarted2 = true; };
  574. yield return new WaitUntil(() => isStarted1 && isStarted2);
  575. bool isCreatedConnection1 = false;
  576. bool isCreatedConnection2 = false;
  577. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  578. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  579. var connectionId = "12345";
  580. target1.CreateConnection(connectionId);
  581. yield return new WaitUntil(() => isCreatedConnection1);
  582. Assert.That(isCreatedConnection1, Is.True);
  583. target2.CreateConnection(connectionId);
  584. yield return new WaitUntil(() => isCreatedConnection2);
  585. Assert.That(isCreatedConnection2, Is.True);
  586. int countGotOffer2 = 0;
  587. target2.onGotOffer += (_, sdp) => { countGotOffer2++; };
  588. target1.SendOffer(connectionId);
  589. yield return new WaitUntil(() => countGotOffer2 > 1);
  590. Assert.That(countGotOffer2, Is.GreaterThan(1));
  591. bool isGotAnswer1 = false;
  592. target1.onGotAnswer += (_, sdp) => { isGotAnswer1 = true; };
  593. target2.SendAnswer(connectionId);
  594. yield return new WaitUntil(() => isGotAnswer1);
  595. Assert.That(isGotAnswer1, Is.True);
  596. yield return new WaitForSeconds(ResendOfferInterval * 2);
  597. var currentCount = countGotOffer2;
  598. yield return new WaitForSeconds(ResendOfferInterval * 2);
  599. Assert.That(countGotOffer2, Is.EqualTo(currentCount),
  600. $"{nameof(currentCount)} is not Equal {nameof(countGotOffer2)}");
  601. target1.DeleteConnection(connectionId);
  602. target2.DeleteConnection(connectionId);
  603. bool isDeletedConnection1 = false;
  604. bool isDeletedConnection2 = false;
  605. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  606. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  607. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  608. Assert.That(isDeletedConnection1, Is.True, $"{nameof(isDeletedConnection1)} is not True.");
  609. Assert.That(isDeletedConnection2, Is.True, $"{nameof(isDeletedConnection2)} is not True.");
  610. target1.Dispose();
  611. target2.Dispose();
  612. }
  613. [TestCase(TestMode.PublicMode, ExpectedResult = null)]
  614. [TestCase(TestMode.PrivateMode, ExpectedResult = null)]
  615. [UnityTest, Timeout(30000), LongRunning]
  616. public IEnumerator DeleteFailedPeers(TestMode mode)
  617. {
  618. MockSignaling.Reset(mode == TestMode.PrivateMode);
  619. var dependencies1 = CreateDependencies();
  620. var dependencies2 = CreateDependencies();
  621. var target1 = new SignalingManagerInternal(ref dependencies1);
  622. var target2 = new SignalingManagerInternal(ref dependencies2);
  623. bool isStarted1 = false;
  624. bool isStarted2 = false;
  625. target1.onStart += () => { isStarted1 = true; };
  626. target2.onStart += () => { isStarted2 = true; };
  627. yield return new WaitUntil(() => isStarted1 && isStarted2);
  628. Assert.That(isStarted1, Is.True);
  629. Assert.That(isStarted2, Is.True);
  630. bool isCreatedConnection1 = false;
  631. bool isCreatedConnection2 = false;
  632. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  633. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  634. var connectionId = "12345";
  635. // target1 has impolite peer (request first)
  636. target1.CreateConnection(connectionId);
  637. yield return new WaitUntil(() => isCreatedConnection1);
  638. Assert.That(isCreatedConnection1, Is.True);
  639. target2.CreateConnection(connectionId);
  640. yield return new WaitUntil(() => isCreatedConnection2);
  641. Assert.That(isCreatedConnection2, Is.True);
  642. bool isGotOffer2 = false;
  643. bool isGotAnswer1 = false;
  644. target2.onGotOffer += (_, sdp) => { isGotOffer2 = true; };
  645. target1.onGotAnswer += (_, sdp) => { isGotAnswer1 = true; };
  646. RTCRtpTransceiverInit init1 = new RTCRtpTransceiverInit()
  647. {
  648. direction = RTCRtpTransceiverDirection.SendOnly
  649. };
  650. target1.AddTransceiver(connectionId, TrackKind.Video, init1);
  651. yield return new WaitUntil(() => isGotOffer2);
  652. Assert.That(isGotOffer2, Is.True, $"{nameof(isGotOffer2)} is not True.");
  653. target2.SendAnswer(connectionId);
  654. yield return new WaitUntil(() => isGotAnswer1);
  655. Assert.That(isGotAnswer1, Is.True, $"{nameof(isGotAnswer1)} is not True.");
  656. // Improperly dispose of target1 to force failed state on target2
  657. target1.Dispose();
  658. bool isDeletedConnection2 = false;
  659. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  660. yield return new WaitUntil(() => isDeletedConnection2);
  661. Assert.That(isDeletedConnection2, Is.True, $"{nameof(isDeletedConnection2)} is not True.");
  662. target2.Dispose();
  663. }
  664. [UnityTest, Timeout(10000)]
  665. public IEnumerator ReNegotiationAfterReceivingFirstOffer()
  666. {
  667. MockSignaling.Reset(true);
  668. var dependencies1 = CreateDependencies();
  669. var dependencies2 = CreateDependencies();
  670. var target1 = new SignalingManagerInternal(ref dependencies1);
  671. var target2 = new SignalingManagerInternal(ref dependencies2);
  672. bool isStarted1 = false;
  673. bool isStarted2 = false;
  674. target1.onStart += () => { isStarted1 = true; };
  675. target2.onStart += () => { isStarted2 = true; };
  676. yield return new WaitUntil(() => isStarted1 && isStarted2);
  677. bool isCreatedConnection1 = false;
  678. bool isCreatedConnection2 = false;
  679. target1.onCreatedConnection += _ => { isCreatedConnection1 = true; };
  680. target2.onCreatedConnection += _ => { isCreatedConnection2 = true; };
  681. var connectionId = "12345";
  682. // target1 has impolite peer (request first)
  683. target1.CreateConnection(connectionId);
  684. yield return new WaitUntil(() => isCreatedConnection1);
  685. // target2 has polite peer (request second)
  686. target2.CreateConnection(connectionId);
  687. yield return new WaitUntil(() => isCreatedConnection2);
  688. bool isGotOffer1 = false;
  689. bool isGotOffer2 = false;
  690. bool isGotAnswer1 = false;
  691. bool isGotAnswer2 = false;
  692. target1.onGotOffer += (_, sdp) => { isGotOffer1 = true; };
  693. target2.onGotOffer += (_, sdp) => { isGotOffer2 = true; };
  694. target1.onGotAnswer += (_, sdp) => { isGotAnswer1 = true; };
  695. target2.onGotAnswer += (_, sdp) => { isGotAnswer2 = true; };
  696. var init1 = new RTCRtpTransceiverInit() { direction = RTCRtpTransceiverDirection.SendOnly };
  697. var init2 = new RTCRtpTransceiverInit() { direction = RTCRtpTransceiverDirection.RecvOnly };
  698. var init3 = new RTCRtpTransceiverInit() { direction = RTCRtpTransceiverDirection.SendOnly };
  699. var init4 = new RTCRtpTransceiverInit() { direction = RTCRtpTransceiverDirection.RecvOnly };
  700. target1.AddTransceiver(connectionId, TrackKind.Video, init1);
  701. target1.AddTransceiver(connectionId, TrackKind.Video, init2);
  702. target2.AddTransceiver(connectionId, TrackKind.Video, init3);
  703. target2.AddTransceiver(connectionId, TrackKind.Video, init4);
  704. yield return new WaitUntil(() => isGotOffer2);
  705. Assert.That(isGotOffer2, Is.True, $"{nameof(isGotOffer2)} is not True.");
  706. target2.SendAnswer(connectionId);
  707. yield return new WaitUntil(() => isGotAnswer1);
  708. Assert.That(isGotAnswer1, Is.True, $"{nameof(isGotAnswer1)} is not True.");
  709. yield return new WaitUntil(() => isGotOffer1);
  710. Assert.That(isGotOffer1, Is.True, $"{nameof(isGotOffer1)} is not True.");
  711. target1.SendAnswer(connectionId);
  712. yield return new WaitUntil(() => isGotAnswer2);
  713. Assert.That(isGotAnswer2, Is.True, $"{nameof(isGotAnswer2)} is not True.");
  714. target1.DeleteConnection(connectionId);
  715. target2.DeleteConnection(connectionId);
  716. bool isDeletedConnection1 = false;
  717. bool isDeletedConnection2 = false;
  718. target1.onDeletedConnection += _ => { isDeletedConnection1 = true; };
  719. target2.onDeletedConnection += _ => { isDeletedConnection2 = true; };
  720. yield return new WaitUntil(() => isDeletedConnection1 && isDeletedConnection2);
  721. Assert.That(isDeletedConnection1, Is.True, $"{nameof(isDeletedConnection1)} is not True.");
  722. Assert.That(isDeletedConnection2, Is.True, $"{nameof(isDeletedConnection1)} is not True.");
  723. target1.Dispose();
  724. target2.Dispose();
  725. }
  726. }
  727. }