2
0

ApplicationTests.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494
  1. using System;
  2. using System.Linq;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using Xunit;
  6. // Alias Console to MockConsole so we don't accidentally use Console
  7. using Console = Terminal.Gui.FakeConsole;
  8. namespace Terminal.Gui.Core {
  9. public class ApplicationTests {
  10. public ApplicationTests ()
  11. {
  12. #if DEBUG_IDISPOSABLE
  13. Responder.Instances.Clear ();
  14. #endif
  15. }
  16. [Fact]
  17. public void Init_Shutdown_Cleans_Up ()
  18. {
  19. // Verify initial state is per spec
  20. Pre_Init_State ();
  21. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  22. // Verify post-Init state is correct
  23. Post_Init_State ();
  24. // MockDriver is always 80x25
  25. Assert.Equal (80, Application.Driver.Cols);
  26. Assert.Equal (25, Application.Driver.Rows);
  27. Application.Shutdown ();
  28. // Verify state is back to initial
  29. Pre_Init_State ();
  30. }
  31. void Pre_Init_State ()
  32. {
  33. Assert.Null (Application.Driver);
  34. Assert.Null (Application.Top);
  35. Assert.Null (Application.Current);
  36. Assert.Throws<ArgumentNullException> (() => Application.HeightAsBuffer == true);
  37. Assert.Null (Application.MainLoop);
  38. Assert.Null (Application.Iteration);
  39. Assert.Null (Application.RootMouseEvent);
  40. Assert.Null (Application.Resized);
  41. }
  42. void Post_Init_State ()
  43. {
  44. Assert.NotNull (Application.Driver);
  45. Assert.NotNull (Application.Top);
  46. Assert.NotNull (Application.Current);
  47. Assert.False (Application.HeightAsBuffer);
  48. Assert.NotNull (Application.MainLoop);
  49. Assert.Null (Application.Iteration);
  50. Assert.Null (Application.RootMouseEvent);
  51. Assert.Null (Application.Resized);
  52. }
  53. [Fact]
  54. public void RunState_Dispose_Cleans_Up ()
  55. {
  56. var rs = new Application.RunState (null);
  57. Assert.NotNull (rs);
  58. // Should not throw because Toplevel was null
  59. rs.Dispose ();
  60. var top = new Toplevel ();
  61. rs = new Application.RunState (top);
  62. Assert.NotNull (rs);
  63. // Should throw because there's no stack
  64. Assert.Throws<InvalidOperationException> (() => rs.Dispose ());
  65. }
  66. void Init ()
  67. {
  68. Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
  69. Assert.NotNull (Application.Driver);
  70. Assert.NotNull (Application.MainLoop);
  71. Assert.NotNull (SynchronizationContext.Current);
  72. }
  73. void Shutdown ()
  74. {
  75. Application.Shutdown ();
  76. }
  77. [Fact]
  78. public void Begin_End_Cleana_Up ()
  79. {
  80. // Setup Mock driver
  81. Init ();
  82. // Test null Toplevel
  83. Assert.Throws<ArgumentNullException> (() => Application.Begin (null));
  84. var top = new Toplevel ();
  85. var rs = Application.Begin (top);
  86. Assert.NotNull (rs);
  87. Assert.Equal (top, Application.Current);
  88. Application.End (rs);
  89. Assert.Null (Application.Current);
  90. Assert.NotNull (Application.Top);
  91. Assert.NotNull (Application.MainLoop);
  92. Assert.NotNull (Application.Driver);
  93. Shutdown ();
  94. Assert.Null (Application.Top);
  95. Assert.Null (Application.MainLoop);
  96. Assert.Null (Application.Driver);
  97. }
  98. [Fact]
  99. public void RequestStop_Stops ()
  100. {
  101. // Setup Mock driver
  102. Init ();
  103. var top = new Toplevel ();
  104. var rs = Application.Begin (top);
  105. Assert.NotNull (rs);
  106. Assert.Equal (top, Application.Current);
  107. Application.Iteration = () => {
  108. Application.RequestStop ();
  109. };
  110. Application.Run (top);
  111. Application.Shutdown ();
  112. Assert.Null (Application.Current);
  113. Assert.Null (Application.Top);
  114. Assert.Null (Application.MainLoop);
  115. Assert.Null (Application.Driver);
  116. }
  117. [Fact]
  118. public void RunningFalse_Stops ()
  119. {
  120. // Setup Mock driver
  121. Init ();
  122. var top = new Toplevel ();
  123. var rs = Application.Begin (top);
  124. Assert.NotNull (rs);
  125. Assert.Equal (top, Application.Current);
  126. Application.Iteration = () => {
  127. top.Running = false;
  128. };
  129. Application.Run (top);
  130. Application.Shutdown ();
  131. Assert.Null (Application.Current);
  132. Assert.Null (Application.Top);
  133. Assert.Null (Application.MainLoop);
  134. Assert.Null (Application.Driver);
  135. }
  136. [Fact]
  137. public void KeyUp_Event ()
  138. {
  139. // Setup Mock driver
  140. Init ();
  141. // Setup some fake keypresses (This)
  142. var input = "Tests";
  143. // Put a control-q in at the end
  144. Console.MockKeyPresses.Push (new ConsoleKeyInfo ('q', ConsoleKey.Q, shift: false, alt: false, control: true));
  145. foreach (var c in input.Reverse ()) {
  146. if (char.IsLetter (c)) {
  147. Console.MockKeyPresses.Push (new ConsoleKeyInfo (c, (ConsoleKey)char.ToUpper (c), shift: char.IsUpper (c), alt: false, control: false));
  148. } else {
  149. Console.MockKeyPresses.Push (new ConsoleKeyInfo (c, (ConsoleKey)c, shift: false, alt: false, control: false));
  150. }
  151. }
  152. int stackSize = Console.MockKeyPresses.Count;
  153. int iterations = 0;
  154. Application.Iteration = () => {
  155. iterations++;
  156. // Stop if we run out of control...
  157. if (iterations > 10) {
  158. Application.RequestStop ();
  159. }
  160. };
  161. int keyUps = 0;
  162. var output = string.Empty;
  163. Application.Top.KeyUp += (View.KeyEventEventArgs args) => {
  164. if (args.KeyEvent.Key != (Key.CtrlMask | Key.Q)) {
  165. output += (char)args.KeyEvent.KeyValue;
  166. }
  167. keyUps++;
  168. };
  169. Application.Run (Application.Top);
  170. // Input string should match output
  171. Assert.Equal (input, output);
  172. // # of key up events should match stack size
  173. //Assert.Equal (stackSize, keyUps);
  174. // We can't use numbers variables on the left side of an Assert.Equal/NotEqual,
  175. // it must be literal (Linux only).
  176. Assert.Equal (6, keyUps);
  177. // # of key up events should match # of iterations
  178. Assert.Equal (stackSize, iterations);
  179. Application.Shutdown ();
  180. Assert.Null (Application.Current);
  181. Assert.Null (Application.Top);
  182. Assert.Null (Application.MainLoop);
  183. Assert.Null (Application.Driver);
  184. }
  185. [Fact]
  186. public void Loaded_Ready_Unlodaded_Events ()
  187. {
  188. Init ();
  189. var top = Application.Top;
  190. var count = 0;
  191. top.Loaded += () => count++;
  192. top.Ready += () => count++;
  193. top.Unloaded += () => count++;
  194. Application.Iteration = () => Application.RequestStop ();
  195. Application.Run ();
  196. Application.Shutdown ();
  197. Assert.Equal (3, count);
  198. }
  199. [Fact]
  200. public void Shutdown_Allows_Async ()
  201. {
  202. static async Task TaskWithAsyncContinuation ()
  203. {
  204. await Task.Yield ();
  205. await Task.Yield ();
  206. }
  207. Init ();
  208. Application.Shutdown ();
  209. var task = TaskWithAsyncContinuation ();
  210. Thread.Sleep (20);
  211. Assert.True (task.IsCompletedSuccessfully);
  212. }
  213. [Fact]
  214. public void Shutdown_Resets_SyncContext ()
  215. {
  216. Init ();
  217. Application.Shutdown ();
  218. Assert.Null (SynchronizationContext.Current);
  219. }
  220. [Fact]
  221. public void AlternateForwardKey_AlternateBackwardKey_Tests ()
  222. {
  223. Init ();
  224. var top = Application.Top;
  225. var w1 = new Window ();
  226. var v1 = new TextField ();
  227. var v2 = new TextView ();
  228. w1.Add (v1, v2);
  229. var w2 = new Window ();
  230. var v3 = new CheckBox ();
  231. var v4 = new Button ();
  232. w2.Add (v3, v4);
  233. top.Add (w1, w2);
  234. Application.Iteration += () => {
  235. Assert.True (v1.HasFocus);
  236. // Using default keys.
  237. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  238. new KeyModifiers () { Ctrl = true }));
  239. Assert.True (v2.HasFocus);
  240. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  241. new KeyModifiers () { Ctrl = true }));
  242. Assert.True (v3.HasFocus);
  243. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  244. new KeyModifiers () { Ctrl = true }));
  245. Assert.True (v4.HasFocus);
  246. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
  247. new KeyModifiers () { Ctrl = true }));
  248. Assert.True (v1.HasFocus);
  249. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  250. new KeyModifiers () { Shift = true, Ctrl = true }));
  251. Assert.True (v4.HasFocus);
  252. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  253. new KeyModifiers () { Shift = true, Ctrl = true }));
  254. Assert.True (v3.HasFocus);
  255. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  256. new KeyModifiers () { Shift = true, Ctrl = true }));
  257. Assert.True (v2.HasFocus);
  258. top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
  259. new KeyModifiers () { Shift = true, Ctrl = true }));
  260. Assert.True (v1.HasFocus);
  261. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  262. new KeyModifiers () { Ctrl = true }));
  263. Assert.True (v2.HasFocus);
  264. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  265. new KeyModifiers () { Ctrl = true }));
  266. Assert.True (v3.HasFocus);
  267. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  268. new KeyModifiers () { Ctrl = true }));
  269. Assert.True (v4.HasFocus);
  270. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
  271. new KeyModifiers () { Ctrl = true }));
  272. Assert.True (v1.HasFocus);
  273. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  274. new KeyModifiers () { Ctrl = true }));
  275. Assert.True (v4.HasFocus);
  276. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  277. new KeyModifiers () { Ctrl = true }));
  278. Assert.True (v3.HasFocus);
  279. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  280. new KeyModifiers () { Ctrl = true }));
  281. Assert.True (v2.HasFocus);
  282. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
  283. new KeyModifiers () { Ctrl = true }));
  284. Assert.True (v1.HasFocus);
  285. // Using another's alternate keys.
  286. Application.AlternateForwardKey = Key.F7;
  287. Application.AlternateBackwardKey = Key.F6;
  288. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  289. Assert.True (v2.HasFocus);
  290. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  291. Assert.True (v3.HasFocus);
  292. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  293. Assert.True (v4.HasFocus);
  294. top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
  295. Assert.True (v1.HasFocus);
  296. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  297. Assert.True (v4.HasFocus);
  298. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  299. Assert.True (v3.HasFocus);
  300. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  301. Assert.True (v2.HasFocus);
  302. top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
  303. Assert.True (v1.HasFocus);
  304. Application.RequestStop ();
  305. };
  306. Application.Run (top);
  307. // Replacing the defaults keys to avoid errors on others unit tests that are using it.
  308. Application.AlternateForwardKey = Key.PageDown | Key.CtrlMask;
  309. Application.AlternateBackwardKey = Key.PageUp | Key.CtrlMask;
  310. Application.QuitKey = Key.Q | Key.CtrlMask;
  311. Assert.Equal (Key.PageDown | Key.CtrlMask, Application.AlternateForwardKey);
  312. Assert.Equal (Key.PageUp | Key.CtrlMask, Application.AlternateBackwardKey);
  313. Assert.Equal (Key.Q | Key.CtrlMask, Application.QuitKey);
  314. // Shutdown must be called to safely clean up Application if Init has been called
  315. Application.Shutdown ();
  316. }
  317. [Fact]
  318. public void Application_RequestStop_With_Params_On_A_Not_MdiContainer_Always_Use_The_Application_Current ()
  319. {
  320. Init ();
  321. var top1 = new Toplevel ();
  322. var top2 = new Toplevel ();
  323. var top3 = new Window ();
  324. var top4 = new Window ();
  325. var d = new Dialog ();
  326. // top1, top2, top3, d1 = 4
  327. var iterations = 4;
  328. top1.Ready += () => {
  329. Assert.Null (Application.MdiChildes);
  330. Application.Run (top2);
  331. };
  332. top2.Ready += () => {
  333. Assert.Null (Application.MdiChildes);
  334. Application.Run (top3);
  335. };
  336. top3.Ready += () => {
  337. Assert.Null (Application.MdiChildes);
  338. Application.Run (top4);
  339. };
  340. top4.Ready += () => {
  341. Assert.Null (Application.MdiChildes);
  342. Application.Run (d);
  343. };
  344. d.Ready += () => {
  345. Assert.Null (Application.MdiChildes);
  346. // This will close the d because on a not MdiContainer the Application.Current it always used.
  347. Application.RequestStop (top1);
  348. Assert.True (Application.Current == d);
  349. };
  350. d.Closed += (e) => Application.RequestStop (top1);
  351. Application.Iteration += () => {
  352. Assert.Null (Application.MdiChildes);
  353. if (iterations == 4) {
  354. Assert.True (Application.Current == d);
  355. } else if (iterations == 3) {
  356. Assert.True (Application.Current == top4);
  357. } else if (iterations == 2) {
  358. Assert.True (Application.Current == top3);
  359. } else if (iterations == 1) {
  360. Assert.True (Application.Current == top2);
  361. } else {
  362. Assert.True (Application.Current == top1);
  363. }
  364. Application.RequestStop (top1);
  365. iterations--;
  366. };
  367. Application.Run (top1);
  368. Assert.Null (Application.MdiChildes);
  369. Application.Shutdown ();
  370. }
  371. class Mdi : Toplevel {
  372. public Mdi ()
  373. {
  374. IsMdiContainer = true;
  375. }
  376. }
  377. [Fact]
  378. public void MdiContainer_With_Toplevel_RequestStop_Balanced ()
  379. {
  380. Init ();
  381. var mdi = new Mdi ();
  382. var c1 = new Toplevel ();
  383. var c2 = new Window ();
  384. var c3 = new Window ();
  385. var d = new Dialog ();
  386. // MdiChild = c1, c2, c3
  387. // d1 = 1
  388. var iterations = 4;
  389. mdi.Ready += () => {
  390. Assert.Empty (Application.MdiChildes);
  391. Application.Run (c1);
  392. };
  393. c1.Ready += () => {
  394. Assert.Single (Application.MdiChildes);
  395. Application.Run (c2);
  396. };
  397. c2.Ready += () => {
  398. Assert.Equal (2, Application.MdiChildes.Count);
  399. Application.Run (c3);
  400. };
  401. c3.Ready += () => {
  402. Assert.Equal (3, Application.MdiChildes.Count);
  403. Application.Run (d);
  404. };
  405. // More easy because the Mdi Container handles all at once
  406. d.Ready += () => {
  407. Assert.Equal (3, Application.MdiChildes.Count);
  408. // This will not close the MdiContainer because d is a modal toplevel and will be closed.
  409. mdi.RequestStop ();
  410. };
  411. // Now this will close the MdiContainer propagating through the MdiChildes.
  412. d.Closed += (e) => {
  413. mdi.RequestStop ();
  414. };
  415. Application.Iteration += () => {
  416. if (iterations == 4) {
  417. // The Dialog was not closed before and will be closed now.
  418. Assert.True (Application.Current == d);
  419. Assert.False (d.Running);
  420. } else {
  421. Assert.Equal (iterations, Application.MdiChildes.Count);
  422. for (int i = 0; i < iterations; i++) {
  423. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  424. }
  425. }
  426. iterations--;
  427. };
  428. Application.Run (mdi);
  429. Assert.Empty (Application.MdiChildes);
  430. Application.Shutdown ();
  431. }
  432. [Fact]
  433. public void MdiContainer_With_Application_RequestStop_MdiTop_With_Params ()
  434. {
  435. Init ();
  436. var mdi = new Mdi ();
  437. var c1 = new Toplevel ();
  438. var c2 = new Window ();
  439. var c3 = new Window ();
  440. var d = new Dialog ();
  441. // MdiChild = c1, c2, c3
  442. // d1 = 1
  443. var iterations = 4;
  444. mdi.Ready += () => {
  445. Assert.Empty (Application.MdiChildes);
  446. Application.Run (c1);
  447. };
  448. c1.Ready += () => {
  449. Assert.Single (Application.MdiChildes);
  450. Application.Run (c2);
  451. };
  452. c2.Ready += () => {
  453. Assert.Equal (2, Application.MdiChildes.Count);
  454. Application.Run (c3);
  455. };
  456. c3.Ready += () => {
  457. Assert.Equal (3, Application.MdiChildes.Count);
  458. Application.Run (d);
  459. };
  460. // Also easy because the Mdi Container handles all at once
  461. d.Ready += () => {
  462. Assert.Equal (3, Application.MdiChildes.Count);
  463. // This will not close the MdiContainer because d is a modal toplevel
  464. Application.RequestStop (mdi);
  465. };
  466. // Now this will close the MdiContainer propagating through the MdiChildes.
  467. d.Closed += (e) => Application.RequestStop (mdi);
  468. Application.Iteration += () => {
  469. if (iterations == 4) {
  470. // The Dialog was not closed before and will be closed now.
  471. Assert.True (Application.Current == d);
  472. Assert.False (d.Running);
  473. } else {
  474. Assert.Equal (iterations, Application.MdiChildes.Count);
  475. for (int i = 0; i < iterations; i++) {
  476. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  477. }
  478. }
  479. iterations--;
  480. };
  481. Application.Run (mdi);
  482. Assert.Empty (Application.MdiChildes);
  483. Application.Shutdown ();
  484. }
  485. [Fact]
  486. public void MdiContainer_With_Application_RequestStop_MdiTop_Without_Params ()
  487. {
  488. Init ();
  489. var mdi = new Mdi ();
  490. var c1 = new Toplevel ();
  491. var c2 = new Window ();
  492. var c3 = new Window ();
  493. var d = new Dialog ();
  494. // MdiChild = c1, c2, c3 = 3
  495. // d1 = 1
  496. var iterations = 4;
  497. mdi.Ready += () => {
  498. Assert.Empty (Application.MdiChildes);
  499. Application.Run (c1);
  500. };
  501. c1.Ready += () => {
  502. Assert.Single (Application.MdiChildes);
  503. Application.Run (c2);
  504. };
  505. c2.Ready += () => {
  506. Assert.Equal (2, Application.MdiChildes.Count);
  507. Application.Run (c3);
  508. };
  509. c3.Ready += () => {
  510. Assert.Equal (3, Application.MdiChildes.Count);
  511. Application.Run (d);
  512. };
  513. //More harder because it's sequential.
  514. d.Ready += () => {
  515. Assert.Equal (3, Application.MdiChildes.Count);
  516. // Close the Dialog
  517. Application.RequestStop ();
  518. };
  519. // Now this will close the MdiContainer propagating through the MdiChildes.
  520. d.Closed += (e) => Application.RequestStop (mdi);
  521. Application.Iteration += () => {
  522. if (iterations == 4) {
  523. // The Dialog still is the current top and we can't request stop to MdiContainer
  524. // because we are not using parameter calls.
  525. Assert.True (Application.Current == d);
  526. Assert.False (d.Running);
  527. } else {
  528. Assert.Equal (iterations, Application.MdiChildes.Count);
  529. for (int i = 0; i < iterations; i++) {
  530. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  531. }
  532. }
  533. iterations--;
  534. };
  535. Application.Run (mdi);
  536. Assert.Empty (Application.MdiChildes);
  537. Application.Shutdown ();
  538. }
  539. [Fact]
  540. public void IsMdiChild_Testing ()
  541. {
  542. Init ();
  543. var mdi = new Mdi ();
  544. var c1 = new Toplevel ();
  545. var c2 = new Window ();
  546. var c3 = new Window ();
  547. var d = new Dialog ();
  548. Application.Iteration += () => {
  549. Assert.False (mdi.IsMdiChild);
  550. Assert.True (c1.IsMdiChild);
  551. Assert.True (c2.IsMdiChild);
  552. Assert.True (c3.IsMdiChild);
  553. Assert.False (d.IsMdiChild);
  554. mdi.RequestStop ();
  555. };
  556. Application.Run (mdi);
  557. Application.Shutdown ();
  558. }
  559. [Fact]
  560. public void Modal_Toplevel_Can_Open_Another_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too ()
  561. {
  562. Init ();
  563. var mdi = new Mdi ();
  564. var c1 = new Toplevel ();
  565. var c2 = new Window ();
  566. var c3 = new Window ();
  567. var d1 = new Dialog ();
  568. var d2 = new Dialog ();
  569. // MdiChild = c1, c2, c3 = 3
  570. // d1, d2 = 2
  571. var iterations = 5;
  572. mdi.Ready += () => {
  573. Assert.Empty (Application.MdiChildes);
  574. Application.Run (c1);
  575. };
  576. c1.Ready += () => {
  577. Assert.Single (Application.MdiChildes);
  578. Application.Run (c2);
  579. };
  580. c2.Ready += () => {
  581. Assert.Equal (2, Application.MdiChildes.Count);
  582. Application.Run (c3);
  583. };
  584. c3.Ready += () => {
  585. Assert.Equal (3, Application.MdiChildes.Count);
  586. Application.Run (d1);
  587. };
  588. d1.Ready += () => {
  589. Assert.Equal (3, Application.MdiChildes.Count);
  590. Application.Run (d2);
  591. };
  592. d2.Ready += () => {
  593. Assert.Equal (3, Application.MdiChildes.Count);
  594. Assert.True (Application.Current == d2);
  595. Assert.True (Application.Current.Running);
  596. // Trying to close the Dialog1
  597. d1.RequestStop ();
  598. };
  599. // Now this will close the MdiContainer propagating through the MdiChildes.
  600. d1.Closed += (e) => {
  601. Assert.True (Application.Current == d1);
  602. Assert.False (Application.Current.Running);
  603. mdi.RequestStop ();
  604. };
  605. Application.Iteration += () => {
  606. if (iterations == 5) {
  607. // The Dialog2 still is the current top and we can't request stop to MdiContainer
  608. // because Dialog2 and Dialog1 must be closed first.
  609. // Dialog2 will be closed in this iteration.
  610. Assert.True (Application.Current == d2);
  611. Assert.False (Application.Current.Running);
  612. Assert.False (d1.Running);
  613. } else if (iterations == 4) {
  614. // Dialog1 will be closed in this iteration.
  615. Assert.True (Application.Current == d1);
  616. Assert.False (Application.Current.Running);
  617. } else {
  618. Assert.Equal (iterations, Application.MdiChildes.Count);
  619. for (int i = 0; i < iterations; i++) {
  620. Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
  621. }
  622. }
  623. iterations--;
  624. };
  625. Application.Run (mdi);
  626. Assert.Empty (Application.MdiChildes);
  627. Application.Shutdown ();
  628. }
  629. [Fact]
  630. public void Modal_Toplevel_Can_Open_Another_Not_Modal_Toplevel_But_RequestStop_To_The_Caller_Also_Sets_Current_Running_To_False_Too ()
  631. {
  632. Init ();
  633. var mdi = new Mdi ();
  634. var c1 = new Toplevel ();
  635. var c2 = new Window ();
  636. var c3 = new Window ();
  637. var d1 = new Dialog ();
  638. var c4 = new Toplevel ();
  639. // MdiChild = c1, c2, c3, c4 = 4
  640. // d1 = 1
  641. var iterations = 5;
  642. mdi.Ready += () => {
  643. Assert.Empty (Application.MdiChildes);
  644. Application.Run (c1);
  645. };
  646. c1.Ready += () => {
  647. Assert.Single (Application.MdiChildes);
  648. Application.Run (c2);
  649. };
  650. c2.Ready += () => {
  651. Assert.Equal (2, Application.MdiChildes.Count);
  652. Application.Run (c3);
  653. };
  654. c3.Ready += () => {
  655. Assert.Equal (3, Application.MdiChildes.Count);
  656. Application.Run (d1);
  657. };
  658. d1.Ready += () => {
  659. Assert.Equal (3, Application.MdiChildes.Count);
  660. Application.Run (c4);
  661. };
  662. c4.Ready += () => {
  663. Assert.Equal (4, Application.MdiChildes.Count);
  664. // Trying to close the Dialog1
  665. d1.RequestStop ();
  666. };
  667. // Now this will close the MdiContainer propagating through the MdiChildes.
  668. d1.Closed += (e) => {
  669. mdi.RequestStop ();
  670. };
  671. Application.Iteration += () => {
  672. if (iterations == 5) {
  673. // The Dialog2 still is the current top and we can't request stop to MdiContainer
  674. // because Dialog2 and Dialog1 must be closed first.
  675. // Using request stop here will call the Dialog again without need
  676. Assert.True (Application.Current == d1);
  677. Assert.False (Application.Current.Running);
  678. Assert.True (c4.Running);
  679. } else {
  680. Assert.Equal (iterations, Application.MdiChildes.Count);
  681. for (int i = 0; i < iterations; i++) {
  682. Assert.Equal ((iterations - i + (iterations == 4 && i == 0 ? 2 : 1)).ToString (),
  683. Application.MdiChildes [i].Id);
  684. }
  685. }
  686. iterations--;
  687. };
  688. Application.Run (mdi);
  689. Assert.Empty (Application.MdiChildes);
  690. Application.Shutdown ();
  691. }
  692. [Fact]
  693. public void MoveCurrent_Returns_False_If_The_Current_And_Top_Parameter_Are_Both_With_Running_Set_To_False ()
  694. {
  695. Init ();
  696. var mdi = new Mdi ();
  697. var c1 = new Toplevel ();
  698. var c2 = new Window ();
  699. var c3 = new Window ();
  700. // MdiChild = c1, c2, c3
  701. var iterations = 3;
  702. mdi.Ready += () => {
  703. Assert.Empty (Application.MdiChildes);
  704. Application.Run (c1);
  705. };
  706. c1.Ready += () => {
  707. Assert.Single (Application.MdiChildes);
  708. Application.Run (c2);
  709. };
  710. c2.Ready += () => {
  711. Assert.Equal (2, Application.MdiChildes.Count);
  712. Application.Run (c3);
  713. };
  714. c3.Ready += () => {
  715. Assert.Equal (3, Application.MdiChildes.Count);
  716. c3.RequestStop ();
  717. c1.RequestStop ();
  718. };
  719. // Now this will close the MdiContainer propagating through the MdiChildes.
  720. c1.Closed += (e) => {
  721. mdi.RequestStop ();
  722. };
  723. Application.Iteration += () => {
  724. if (iterations == 3) {
  725. // The Current still is c3 because Current.Running is false.
  726. Assert.True (Application.Current == c3);
  727. Assert.False (Application.Current.Running);
  728. // But the childes order were reorder by Running = false
  729. Assert.True (Application.MdiChildes [0] == c3);
  730. Assert.True (Application.MdiChildes [1] == c1);
  731. Assert.True (Application.MdiChildes [^1] == c2);
  732. } else if (iterations == 2) {
  733. // The Current is c1 and Current.Running is false.
  734. Assert.True (Application.Current == c1);
  735. Assert.False (Application.Current.Running);
  736. Assert.True (Application.MdiChildes [0] == c1);
  737. Assert.True (Application.MdiChildes [^1] == c2);
  738. } else if (iterations == 1) {
  739. // The Current is c2 and Current.Running is false.
  740. Assert.True (Application.Current == c2);
  741. Assert.False (Application.Current.Running);
  742. Assert.True (Application.MdiChildes [^1] == c2);
  743. } else {
  744. // The Current is mdi.
  745. Assert.True (Application.Current == mdi);
  746. Assert.Empty (Application.MdiChildes);
  747. }
  748. iterations--;
  749. };
  750. Application.Run (mdi);
  751. Assert.Empty (Application.MdiChildes);
  752. Application.Shutdown ();
  753. }
  754. [Fact]
  755. public void MdiContainer_Throws_If_More_Than_One ()
  756. {
  757. Init ();
  758. var mdi = new Mdi ();
  759. var mdi2 = new Mdi ();
  760. mdi.Ready += () => {
  761. Assert.Throws<InvalidOperationException> (() => Application.Run (mdi2));
  762. mdi.RequestStop ();
  763. };
  764. Application.Run (mdi);
  765. Application.Shutdown ();
  766. }
  767. [Fact]
  768. public void MdiContainer_Open_And_Close_Modal_And_Open_Not_Modal_Toplevels_Randomly ()
  769. {
  770. Init ();
  771. var mdi = new Mdi ();
  772. var logger = new Toplevel ();
  773. var iterations = 1; // The logger
  774. var running = true;
  775. var stageCompleted = true;
  776. var allStageClosed = false;
  777. var mdiRequestStop = false;
  778. mdi.Ready += () => {
  779. Assert.Empty (Application.MdiChildes);
  780. Application.Run (logger);
  781. };
  782. logger.Ready += () => Assert.Single (Application.MdiChildes);
  783. Application.Iteration += () => {
  784. if (stageCompleted && running) {
  785. stageCompleted = false;
  786. var stage = new Window () { Modal = true };
  787. stage.Ready += () => {
  788. Assert.Equal (iterations, Application.MdiChildes.Count);
  789. stage.RequestStop ();
  790. };
  791. stage.Closed += (_) => {
  792. if (iterations == 11) {
  793. allStageClosed = true;
  794. }
  795. Assert.Equal (iterations, Application.MdiChildes.Count);
  796. if (running) {
  797. stageCompleted = true;
  798. var rpt = new Window ();
  799. rpt.Ready += () => {
  800. iterations++;
  801. Assert.Equal (iterations, Application.MdiChildes.Count);
  802. };
  803. Application.Run (rpt);
  804. }
  805. };
  806. Application.Run (stage);
  807. } else if (iterations == 11 && running) {
  808. running = false;
  809. Assert.Equal (iterations, Application.MdiChildes.Count);
  810. } else if (!mdiRequestStop && running && !allStageClosed) {
  811. Assert.Equal (iterations, Application.MdiChildes.Count);
  812. } else if (!mdiRequestStop && !running && allStageClosed) {
  813. Assert.Equal (iterations, Application.MdiChildes.Count);
  814. mdiRequestStop = true;
  815. mdi.RequestStop ();
  816. } else {
  817. Assert.Empty (Application.MdiChildes);
  818. }
  819. };
  820. Application.Run (mdi);
  821. Assert.Empty (Application.MdiChildes);
  822. Application.Shutdown ();
  823. }
  824. [Fact]
  825. public void AllChildClosed_Event_Test ()
  826. {
  827. Init ();
  828. var mdi = new Mdi ();
  829. var c1 = new Toplevel ();
  830. var c2 = new Window ();
  831. var c3 = new Window ();
  832. // MdiChild = c1, c2, c3
  833. var iterations = 3;
  834. mdi.Ready += () => {
  835. Assert.Empty (Application.MdiChildes);
  836. Application.Run (c1);
  837. };
  838. c1.Ready += () => {
  839. Assert.Single (Application.MdiChildes);
  840. Application.Run (c2);
  841. };
  842. c2.Ready += () => {
  843. Assert.Equal (2, Application.MdiChildes.Count);
  844. Application.Run (c3);
  845. };
  846. c3.Ready += () => {
  847. Assert.Equal (3, Application.MdiChildes.Count);
  848. c3.RequestStop ();
  849. c2.RequestStop ();
  850. c1.RequestStop ();
  851. };
  852. // Now this will close the MdiContainer when all MdiChildes was closed
  853. mdi.AllChildClosed += () => {
  854. mdi.RequestStop ();
  855. };
  856. Application.Iteration += () => {
  857. if (iterations == 3) {
  858. // The Current still is c3 because Current.Running is false.
  859. Assert.True (Application.Current == c3);
  860. Assert.False (Application.Current.Running);
  861. // But the childes order were reorder by Running = false
  862. Assert.True (Application.MdiChildes [0] == c3);
  863. Assert.True (Application.MdiChildes [1] == c2);
  864. Assert.True (Application.MdiChildes [^1] == c1);
  865. } else if (iterations == 2) {
  866. // The Current is c2 and Current.Running is false.
  867. Assert.True (Application.Current == c2);
  868. Assert.False (Application.Current.Running);
  869. Assert.True (Application.MdiChildes [0] == c2);
  870. Assert.True (Application.MdiChildes [^1] == c1);
  871. } else if (iterations == 1) {
  872. // The Current is c1 and Current.Running is false.
  873. Assert.True (Application.Current == c1);
  874. Assert.False (Application.Current.Running);
  875. Assert.True (Application.MdiChildes [^1] == c1);
  876. } else {
  877. // The Current is mdi.
  878. Assert.True (Application.Current == mdi);
  879. Assert.False (Application.Current.Running);
  880. Assert.Empty (Application.MdiChildes);
  881. }
  882. iterations--;
  883. };
  884. Application.Run (mdi);
  885. Assert.Empty (Application.MdiChildes);
  886. Application.Shutdown ();
  887. }
  888. [Fact]
  889. public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Application_Top ()
  890. {
  891. Init ();
  892. var t1 = new Toplevel ();
  893. var t2 = new Toplevel ();
  894. var t3 = new Toplevel ();
  895. var d = new Dialog ();
  896. var t4 = new Toplevel ();
  897. // t1, t2, t3, d, t4
  898. var iterations = 5;
  899. t1.Ready += () => {
  900. Assert.Equal (t1, Application.Top);
  901. Application.Run (t2);
  902. };
  903. t2.Ready += () => {
  904. Assert.Equal (t2, Application.Top);
  905. Application.Run (t3);
  906. };
  907. t3.Ready += () => {
  908. Assert.Equal (t3, Application.Top);
  909. Application.Run (d);
  910. };
  911. d.Ready += () => {
  912. Assert.Equal (t3, Application.Top);
  913. Application.Run (t4);
  914. };
  915. t4.Ready += () => {
  916. Assert.Equal (t4, Application.Top);
  917. t4.RequestStop ();
  918. d.RequestStop ();
  919. t3.RequestStop ();
  920. t2.RequestStop ();
  921. };
  922. // Now this will close the MdiContainer when all MdiChildes was closed
  923. t2.Closed += (_) => {
  924. t1.RequestStop ();
  925. };
  926. Application.Iteration += () => {
  927. if (iterations == 5) {
  928. // The Current still is t4 because Current.Running is false.
  929. Assert.Equal (t4, Application.Current);
  930. Assert.False (Application.Current.Running);
  931. Assert.Equal (t4, Application.Top);
  932. } else if (iterations == 4) {
  933. // The Current is d and Current.Running is false.
  934. Assert.Equal (d, Application.Current);
  935. Assert.False (Application.Current.Running);
  936. Assert.Equal (t4, Application.Top);
  937. } else if (iterations == 3) {
  938. // The Current is t3 and Current.Running is false.
  939. Assert.Equal (t3, Application.Current);
  940. Assert.False (Application.Current.Running);
  941. Assert.Equal (t3, Application.Top);
  942. } else if (iterations == 2) {
  943. // The Current is t2 and Current.Running is false.
  944. Assert.Equal (t2, Application.Current);
  945. Assert.False (Application.Current.Running);
  946. Assert.Equal (t2, Application.Top);
  947. } else {
  948. // The Current is t1.
  949. Assert.Equal (t1, Application.Current);
  950. Assert.False (Application.Current.Running);
  951. Assert.Equal (t1, Application.Top);
  952. }
  953. iterations--;
  954. };
  955. Application.Run (t1);
  956. Assert.Equal (t1, Application.Top);
  957. Application.Shutdown ();
  958. Assert.Null (Application.Top);
  959. }
  960. [Fact]
  961. [AutoInitShutdown]
  962. public void Internal_Tests ()
  963. {
  964. Assert.True (Application._initialized);
  965. Assert.NotNull (Application.Top);
  966. var rs = Application.Begin (Application.Top);
  967. Assert.Equal (Application.Top, rs.Toplevel);
  968. Assert.Null (Application.mouseGrabView);
  969. Assert.Null (Application.WantContinuousButtonPressedView);
  970. Assert.False (Application.DebugDrawBounds);
  971. Assert.False (Application.ShowChild (Application.Top));
  972. Application.End (Application.Top);
  973. }
  974. [Fact]
  975. [AutoInitShutdown]
  976. public void QuitKey_Getter_Setter ()
  977. {
  978. var top = Application.Top;
  979. var isQuiting = false;
  980. top.Closing += (e) => {
  981. isQuiting = true;
  982. e.Cancel = true;
  983. };
  984. Application.Begin (top);
  985. top.Running = true;
  986. Assert.Equal (Key.Q | Key.CtrlMask, Application.QuitKey);
  987. Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
  988. Assert.True (isQuiting);
  989. isQuiting = false;
  990. Application.QuitKey = Key.C | Key.CtrlMask;
  991. Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
  992. Assert.False (isQuiting);
  993. Application.Driver.SendKeys ('c', ConsoleKey.C, false, false, true);
  994. Assert.True (isQuiting);
  995. // Reset the QuitKey to avoid throws errors on another tests
  996. Application.QuitKey = Key.Q | Key.CtrlMask;
  997. }
  998. [Fact]
  999. [AutoInitShutdown]
  1000. public void EnsuresTopOnFront_CanFocus_True_By_Keyboard_And_Mouse ()
  1001. {
  1002. var top = Application.Top;
  1003. var win = new Window ("win") { X = 0, Y = 0, Width = 20, Height = 10 };
  1004. var tf = new TextField () { Width = 10 };
  1005. win.Add (tf);
  1006. var win2 = new Window ("win2") { X = 22, Y = 0, Width = 20, Height = 10 };
  1007. var tf2 = new TextField () { Width = 10 };
  1008. win2.Add (tf2);
  1009. top.Add (win, win2);
  1010. Application.Begin (top);
  1011. Assert.True (win.CanFocus);
  1012. Assert.True (win.HasFocus);
  1013. Assert.True (win2.CanFocus);
  1014. Assert.False (win2.HasFocus);
  1015. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1016. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1017. Assert.True (win.CanFocus);
  1018. Assert.False (win.HasFocus);
  1019. Assert.True (win2.CanFocus);
  1020. Assert.True (win2.HasFocus);
  1021. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1022. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1023. Assert.True (win.CanFocus);
  1024. Assert.True (win.HasFocus);
  1025. Assert.True (win2.CanFocus);
  1026. Assert.False (win2.HasFocus);
  1027. Assert.Equal ("win", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1028. win2.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Pressed });
  1029. Assert.True (win.CanFocus);
  1030. Assert.False (win.HasFocus);
  1031. Assert.True (win2.CanFocus);
  1032. Assert.True (win2.HasFocus);
  1033. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1034. win2.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Released });
  1035. Assert.Null (Toplevel.dragPosition);
  1036. }
  1037. [Fact]
  1038. [AutoInitShutdown]
  1039. public void EnsuresTopOnFront_CanFocus_False_By_Keyboard_And_Mouse ()
  1040. {
  1041. var top = Application.Top;
  1042. var win = new Window ("win") { X = 0, Y = 0, Width = 20, Height = 10 };
  1043. var tf = new TextField () { Width = 10 };
  1044. win.Add (tf);
  1045. var win2 = new Window ("win2") { X = 22, Y = 0, Width = 20, Height = 10 };
  1046. var tf2 = new TextField () { Width = 10 };
  1047. win2.Add (tf2);
  1048. top.Add (win, win2);
  1049. Application.Begin (top);
  1050. Assert.True (win.CanFocus);
  1051. Assert.True (win.HasFocus);
  1052. Assert.True (win2.CanFocus);
  1053. Assert.False (win2.HasFocus);
  1054. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1055. win.CanFocus = false;
  1056. Assert.False (win.CanFocus);
  1057. Assert.False (win.HasFocus);
  1058. Assert.True (win2.CanFocus);
  1059. Assert.True (win2.HasFocus);
  1060. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1061. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1062. Assert.True (win2.CanFocus);
  1063. Assert.False (win.HasFocus);
  1064. Assert.True (win2.CanFocus);
  1065. Assert.True (win2.HasFocus);
  1066. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1067. top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab, new KeyModifiers ()));
  1068. Assert.False (win.CanFocus);
  1069. Assert.False (win.HasFocus);
  1070. Assert.True (win2.CanFocus);
  1071. Assert.True (win2.HasFocus);
  1072. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1073. win.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Pressed });
  1074. Assert.False (win.CanFocus);
  1075. Assert.False (win.HasFocus);
  1076. Assert.True (win2.CanFocus);
  1077. Assert.True (win2.HasFocus);
  1078. Assert.Equal ("win2", ((Window)top.Subviews [top.Subviews.Count - 1]).Title);
  1079. win2.MouseEvent (new MouseEvent () { Flags = MouseFlags.Button1Released });
  1080. Assert.Null (Toplevel.dragPosition);
  1081. }
  1082. [Fact, AutoInitShutdown]
  1083. public void GetSupportedCultures_Method ()
  1084. {
  1085. var cultures = Application.GetSupportedCultures ();
  1086. Assert.Equal (cultures.Count, Application.SupportedCultures.Count);
  1087. }
  1088. [Fact, AutoInitShutdown]
  1089. public void TestAddManyTimeouts ()
  1090. {
  1091. int delegatesRun = 0;
  1092. int numberOfThreads = 100;
  1093. int numberOfTimeoutsPerThread = 100;
  1094. lock (Application.Top) {
  1095. // start lots of threads
  1096. for (int i = 0; i < numberOfThreads; i++) {
  1097. var myi = i;
  1098. Task.Run (() => {
  1099. Task.Delay (100).Wait ();
  1100. // each thread registers lots of 1s timeouts
  1101. for (int j = 0; j < numberOfTimeoutsPerThread; j++) {
  1102. Application.MainLoop.AddTimeout (TimeSpan.FromSeconds (1), (s) => {
  1103. // each timeout delegate increments delegatesRun count by 1 every second
  1104. Interlocked.Increment (ref delegatesRun);
  1105. return true;
  1106. });
  1107. }
  1108. // if this is the first Thread created
  1109. if (myi == 0) {
  1110. // let the timeouts run for a bit
  1111. Task.Delay (5000).Wait ();
  1112. // then tell the application to quit
  1113. Application.MainLoop.Invoke (() => Application.RequestStop ());
  1114. }
  1115. });
  1116. }
  1117. // blocks here until the RequestStop is processed at the end of the test
  1118. Application.Run ();
  1119. // undershoot a bit to be on the safe side. The 5000 ms wait allows the timeouts to run
  1120. // a lot but all those timeout delegates could end up going slowly on a slow machine perhaps
  1121. // so the final number of delegatesRun might vary by computer. So for this assert we say
  1122. // that it should have run at least 2 seconds worth of delegates
  1123. Assert.True (delegatesRun >= numberOfThreads * numberOfTimeoutsPerThread * 2);
  1124. }
  1125. }
  1126. [Fact]
  1127. public void SynchronizationContext_Post ()
  1128. {
  1129. Init ();
  1130. var context = SynchronizationContext.Current;
  1131. var success = false;
  1132. Task.Run (() => {
  1133. Thread.Sleep (1_000);
  1134. // non blocking
  1135. context.Post (
  1136. delegate (object o) {
  1137. success = true;
  1138. // then tell the application to quit
  1139. Application.MainLoop.Invoke (() => Application.RequestStop ());
  1140. }, null);
  1141. Assert.False (success);
  1142. });
  1143. // blocks here until the RequestStop is processed at the end of the test
  1144. Application.Run ();
  1145. Assert.True (success);
  1146. Application.Shutdown ();
  1147. }
  1148. [Fact]
  1149. public void SynchronizationContext_Send ()
  1150. {
  1151. Init ();
  1152. var context = SynchronizationContext.Current;
  1153. var success = false;
  1154. Task.Run (() => {
  1155. Thread.Sleep (1_000);
  1156. // blocking
  1157. context.Send (
  1158. delegate (object o) {
  1159. success = true;
  1160. // then tell the application to quit
  1161. Application.MainLoop.Invoke (() => Application.RequestStop ());
  1162. }, null);
  1163. Assert.True (success);
  1164. });
  1165. // blocks here until the RequestStop is processed at the end of the test
  1166. Application.Run ();
  1167. Assert.True (success);
  1168. Application.Shutdown ();
  1169. }
  1170. [Fact]
  1171. public void SynchronizationContext_CreateCopy ()
  1172. {
  1173. Init ();
  1174. var context = SynchronizationContext.Current;
  1175. Assert.NotNull (context);
  1176. var contextCopy = context.CreateCopy ();
  1177. Assert.NotNull (contextCopy);
  1178. Assert.NotEqual (context, contextCopy);
  1179. Application.Shutdown ();
  1180. }
  1181. [Fact, AutoInitShutdown]
  1182. public void MouseGrabView_WithNullMouseEventView ()
  1183. {
  1184. var tf = new TextField () { Width = 10 };
  1185. var sv = new ScrollView () {
  1186. Width = Dim.Fill (),
  1187. Height = Dim.Fill (),
  1188. ContentSize = new Size (100, 100)
  1189. };
  1190. sv.Add (tf);
  1191. Application.Top.Add (sv);
  1192. var iterations = -1;
  1193. Application.Iteration = () => {
  1194. iterations++;
  1195. if (iterations == 0) {
  1196. Assert.True (tf.HasFocus);
  1197. Assert.Null (Application.mouseGrabView);
  1198. ReflectionTools.InvokePrivate (
  1199. typeof (Application),
  1200. "ProcessMouseEvent",
  1201. new MouseEvent () {
  1202. X = 5,
  1203. Y = 5,
  1204. Flags = MouseFlags.ReportMousePosition
  1205. });
  1206. Assert.Equal (sv, Application.mouseGrabView);
  1207. MessageBox.Query ("Title", "Test", "Ok");
  1208. Assert.Null (Application.mouseGrabView);
  1209. } else if (iterations == 1) {
  1210. Assert.Equal (sv, Application.mouseGrabView);
  1211. ReflectionTools.InvokePrivate (
  1212. typeof (Application),
  1213. "ProcessMouseEvent",
  1214. new MouseEvent () {
  1215. X = 5,
  1216. Y = 5,
  1217. Flags = MouseFlags.ReportMousePosition
  1218. });
  1219. Assert.Null (Application.mouseGrabView);
  1220. ReflectionTools.InvokePrivate (
  1221. typeof (Application),
  1222. "ProcessMouseEvent",
  1223. new MouseEvent () {
  1224. X = 40,
  1225. Y = 12,
  1226. Flags = MouseFlags.ReportMousePosition
  1227. });
  1228. Assert.Null (Application.mouseGrabView);
  1229. ReflectionTools.InvokePrivate (
  1230. typeof (Application),
  1231. "ProcessMouseEvent",
  1232. new MouseEvent () {
  1233. X = 0,
  1234. Y = 0,
  1235. Flags = MouseFlags.Button1Pressed
  1236. });
  1237. Assert.Null (Application.mouseGrabView);
  1238. Application.RequestStop ();
  1239. } else if (iterations == 2) {
  1240. Assert.Null (Application.mouseGrabView);
  1241. Application.RequestStop ();
  1242. }
  1243. };
  1244. Application.Run ();
  1245. }
  1246. }
  1247. }