ChangesModelTests.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using JetBrains.Annotations;
  4. using NUnit.Framework;
  5. using Unity.Cloud.Collaborate.Models;
  6. using Unity.Cloud.Collaborate.Models.Structures;
  7. namespace Unity.Cloud.Collaborate.Tests.Models
  8. {
  9. public class ChangesModelTests
  10. {
  11. class TestableChangesModel : ChangesModel
  12. {
  13. public TestSourceControlProvider Provider => (TestSourceControlProvider)m_Provider;
  14. public TestableChangesModel() : base (new TestSourceControlProvider())
  15. {
  16. }
  17. public void SetToggled([CanBeNull] Dictionary<string, bool> toggled = null)
  18. {
  19. if (toggled != null)
  20. {
  21. toggledEntries = toggled;
  22. }
  23. }
  24. internal override void UpdateChangeList(IReadOnlyList<IChangeEntry> list)
  25. {
  26. base.UpdateChangeList(list);
  27. ValidateData();
  28. }
  29. public override bool UpdateEntryToggle(string path, bool value)
  30. {
  31. var refresh = base.UpdateEntryToggle(path, value);
  32. ValidateData();
  33. return refresh;
  34. }
  35. void ValidateData()
  36. {
  37. var toggledCount = 0;
  38. foreach (var x in entryData.Select(entry => entry.Value))
  39. {
  40. Assert.IsTrue(toggledEntries.TryGetValue(x.Entry.Path, out var toggled) && x.Toggled == toggled);
  41. if (!x.All && toggled) toggledCount++;
  42. }
  43. Assert.AreEqual(toggledCount, ToggledCount);
  44. }
  45. }
  46. [Test]
  47. public void ChangesModel_NullSourceControlEntries_EmptyResultLists()
  48. {
  49. var model = new TestableChangesModel();
  50. model.OnStart();
  51. model.UpdateChangeList(new List<IChangeEntry>());
  52. var fullList = model.GetAllEntries();
  53. Assert.AreEqual(1, fullList.Count);
  54. Assert.IsTrue(fullList[0].All);
  55. Assert.AreEqual(0, model.GetToggledEntries().Count);
  56. Assert.AreEqual(0, model.GetUntoggledEntries().Count);
  57. Assert.AreEqual(0, model.ToggledCount);
  58. }
  59. [Test]
  60. public void ChangesModel_EmptySourceControlEntries_EmptyResultLists()
  61. {
  62. var model = new TestableChangesModel();
  63. model.OnStart();
  64. model.UpdateChangeList(new List<IChangeEntry>());
  65. var fullList = model.GetAllEntries();
  66. Assert.AreEqual(1, fullList.Count);
  67. Assert.IsTrue(fullList[0].All);
  68. Assert.AreEqual(0, model.GetToggledEntries().Count);
  69. Assert.AreEqual(0, model.GetUntoggledEntries().Count);
  70. Assert.AreEqual(0, model.ToggledCount);
  71. }
  72. [Test]
  73. public void ChangesModel_SingleSourceControlEntries_SingleUntoggledResult()
  74. {
  75. var model = new TestableChangesModel();
  76. model.OnStart();
  77. var changes = BuildChangesList(1);
  78. model.UpdateChangeList(changes);
  79. var fullList = model.GetAllEntries();
  80. Assert.AreEqual(2, fullList.Count);
  81. Assert.IsTrue(fullList[0].All);
  82. Assert.IsFalse(fullList[0].Toggled);
  83. Assert.IsFalse(fullList[1].All);
  84. Assert.IsFalse(fullList[1].Toggled);
  85. var toggledList = model.GetToggledEntries();
  86. Assert.AreEqual(0, toggledList.Count);
  87. var untoggledList = model.GetUntoggledEntries();
  88. Assert.AreEqual(1, untoggledList.Count);
  89. Assert.IsFalse(untoggledList[0].All);
  90. Assert.IsFalse(untoggledList[0].Toggled);
  91. Assert.AreEqual(0, model.ToggledCount);
  92. }
  93. [Test]
  94. public void ChangesModel_MultipleSourceControlEntries_ToggleSingle()
  95. {
  96. const int entryCount = 5;
  97. var model = new TestableChangesModel();
  98. model.OnStart();
  99. var changes = BuildChangesList(entryCount);
  100. model.UpdateChangeList(changes);
  101. var fullList = model.GetAllEntries();
  102. Assert.AreEqual(entryCount, model.TotalCount);
  103. Assert.AreEqual(entryCount + 1, fullList.Count);
  104. Assert.IsTrue(fullList[0].All);
  105. var toggledEntry = fullList[entryCount / 2 + 1];
  106. model.UpdateEntryToggle(toggledEntry.Entry.Path, true);
  107. Assert.IsTrue(toggledEntry.Toggled);
  108. fullList = model.GetAllEntries();
  109. Assert.AreEqual(entryCount + 1, fullList.Count);
  110. foreach (var entry in fullList)
  111. {
  112. if (entry == fullList[0])
  113. {
  114. Assert.IsTrue(entry.All);
  115. }
  116. else
  117. {
  118. Assert.IsFalse(entry.All);
  119. }
  120. if (entry == toggledEntry)
  121. {
  122. Assert.IsTrue(entry.Toggled);
  123. }
  124. else
  125. {
  126. Assert.IsFalse(entry.Toggled);
  127. }
  128. }
  129. var toggledList = model.GetToggledEntries();
  130. Assert.AreEqual(1, toggledList.Count);
  131. Assert.AreEqual(toggledEntry, toggledList[0]);
  132. var untoggledList = model.GetUntoggledEntries();
  133. Assert.AreEqual(entryCount -1, untoggledList.Count);
  134. foreach (var entry in untoggledList)
  135. {
  136. Assert.IsFalse(entry.All);
  137. Assert.AreNotEqual(toggledEntry, entry);
  138. }
  139. Assert.AreEqual(1, model.ToggledCount);
  140. }
  141. [Test]
  142. public void ChangesModel_MultipleSourceControlEntries_ToggleAll()
  143. {
  144. const int entryCount = 5;
  145. var model = new TestableChangesModel();
  146. model.OnStart();
  147. var changes = BuildChangesList(entryCount);
  148. model.UpdateChangeList(changes);
  149. var fullList = model.GetAllEntries();
  150. Assert.AreEqual(entryCount + 1, fullList.Count);
  151. Assert.IsTrue(fullList[0].All);
  152. model.UpdateEntryToggle(fullList[0].Entry.Path, true);
  153. fullList = model.GetAllEntries();
  154. Assert.AreEqual(entryCount + 1, fullList.Count);
  155. foreach (var entry in fullList)
  156. {
  157. if (entry == fullList[0])
  158. {
  159. Assert.IsTrue(entry.All);
  160. }
  161. else
  162. {
  163. Assert.IsFalse(entry.All);
  164. }
  165. Assert.IsTrue(entry.Toggled);
  166. }
  167. var toggledList = model.GetToggledEntries();
  168. Assert.AreEqual(entryCount, toggledList.Count);
  169. foreach (var entry in toggledList)
  170. {
  171. Assert.IsFalse(entry.All);
  172. }
  173. var untoggledList = model.GetUntoggledEntries();
  174. Assert.AreEqual(0, untoggledList.Count);
  175. Assert.AreEqual(entryCount, model.ToggledCount);
  176. }
  177. [Test]
  178. public void ChangesModel_MultipleSourceControlEntries_ToggleAllIndividually()
  179. {
  180. const int entryCount = 5;
  181. var model = new TestableChangesModel();
  182. model.OnStart();
  183. var changes = BuildChangesList(entryCount);
  184. model.UpdateChangeList(changes);
  185. var fullList = model.GetAllEntries();
  186. Assert.AreEqual(entryCount + 1, fullList.Count);
  187. Assert.IsTrue(fullList[0].All);
  188. fullList = model.GetAllEntries();
  189. foreach (var entry in fullList.Where(entry => !entry.All))
  190. {
  191. model.UpdateEntryToggle(entry.Entry.Path, true);
  192. }
  193. Assert.AreEqual(entryCount + 1, fullList.Count);
  194. foreach (var entry in fullList)
  195. {
  196. if (entry == fullList[0])
  197. {
  198. Assert.IsTrue(entry.All);
  199. }
  200. else
  201. {
  202. Assert.IsFalse(entry.All);
  203. }
  204. Assert.IsTrue(entry.Toggled);
  205. }
  206. var toggledList = model.GetToggledEntries();
  207. Assert.AreEqual(entryCount, toggledList.Count);
  208. foreach (var entry in toggledList)
  209. {
  210. Assert.IsFalse(entry.All);
  211. }
  212. var untoggledList = model.GetUntoggledEntries();
  213. Assert.AreEqual(0, untoggledList.Count);
  214. Assert.AreEqual(entryCount, model.ToggledCount);
  215. }
  216. [Test]
  217. public void ChangesModel_MultipleSourceControlEntries_UntoggleSingleFromAll()
  218. {
  219. const int entryCount = 5;
  220. var model = new TestableChangesModel();
  221. model.OnStart();
  222. var changes = BuildChangesList(entryCount);
  223. model.UpdateChangeList(changes);
  224. var fullList = model.GetAllEntries();
  225. Assert.AreEqual(entryCount + 1, fullList.Count);
  226. Assert.IsTrue(fullList[0].All);
  227. model.UpdateEntryToggle(fullList[0].Entry.Path, true);
  228. var untoggledEntry = fullList[entryCount / 2 + 1];
  229. model.UpdateEntryToggle(untoggledEntry.Entry.Path, false);
  230. Assert.IsFalse(untoggledEntry.Toggled);
  231. fullList = model.GetAllEntries();
  232. Assert.AreEqual(entryCount + 1, fullList.Count);
  233. foreach (var entry in fullList)
  234. {
  235. if (entry == fullList[0])
  236. {
  237. Assert.IsTrue(entry.All);
  238. }
  239. else
  240. {
  241. Assert.IsFalse(entry.All);
  242. }
  243. if (entry == untoggledEntry || entry.All)
  244. {
  245. Assert.IsFalse(entry.Toggled);
  246. }
  247. else
  248. {
  249. Assert.IsTrue(entry.Toggled);
  250. }
  251. }
  252. var toggledList = model.GetToggledEntries();
  253. Assert.AreEqual(entryCount - 1, toggledList.Count);
  254. foreach (var entry in toggledList)
  255. {
  256. Assert.IsFalse(entry.All);
  257. Assert.AreNotEqual(untoggledEntry, entry);
  258. }
  259. var untoggledList = model.GetUntoggledEntries();
  260. Assert.AreEqual(1, untoggledList.Count);
  261. Assert.AreEqual(untoggledEntry, untoggledList[0]);
  262. Assert.AreEqual(entryCount - 1, model.ToggledCount);
  263. }
  264. [Test]
  265. public void ChangesModel_MultipleSourceControlEntries_SomeConflicted()
  266. {
  267. const string conflictedPrefix = "conflicted-path";
  268. var model = new TestableChangesModel();
  269. model.OnStart();
  270. var changes = new List<IChangeEntry>();
  271. AddEntry(changes, "path1", ChangeEntryStatus.Modified, false);
  272. AddEntry(changes, "path2", ChangeEntryStatus.Modified, false);
  273. AddEntry(changes, "path3", ChangeEntryStatus.Modified, false);
  274. AddEntry(changes, $"{conflictedPrefix}4", ChangeEntryStatus.Modified, false, true);
  275. AddEntry(changes, $"{conflictedPrefix}5", ChangeEntryStatus.Modified, false, true);
  276. model.UpdateChangeList(changes);
  277. var conflictedList = model.GetConflictedEntries();
  278. model.Provider.ConflictedState = true;
  279. Assert.IsTrue(model.Conflicted);
  280. Assert.AreEqual(2, model.ConflictedCount);
  281. Assert.AreEqual(2, conflictedList.Count);
  282. Assert.IsFalse(conflictedList[0].All);
  283. Assert.IsFalse(conflictedList[1].All);
  284. Assert.IsTrue(conflictedList[0].Conflicted);
  285. Assert.IsTrue(conflictedList[1].Conflicted);
  286. Assert.IsTrue(conflictedList[0].Entry.Path.StartsWith(conflictedPrefix));
  287. Assert.IsTrue(conflictedList[1].Entry.Path.StartsWith(conflictedPrefix));
  288. }
  289. [Test]
  290. public void ChangesModel_InitializeFromDictionary_TransfersToggledFlag()
  291. {
  292. const int entryCount = 5;
  293. const int toggledCount = 2;
  294. const int toggledIndex1 = 0;
  295. const int toggledIndex2 = entryCount / 2 + 1;
  296. const int untoggledIndex = entryCount - 1;
  297. var changes = BuildChangesList(entryCount);
  298. var dictionary = new Dictionary<string, bool>();
  299. changes.ForEach( (x) => dictionary[x.Path] = false );
  300. dictionary[changes[toggledIndex1].Path] = true;
  301. dictionary[changes[toggledIndex2].Path] = true;
  302. dictionary[changes[untoggledIndex].Path] = false;
  303. var model = new TestableChangesModel();
  304. model.OnStart();
  305. model.SetToggled(dictionary);
  306. model.UpdateChangeList(changes);
  307. var fullList = model.GetAllEntries();
  308. Assert.AreEqual(entryCount + 1, fullList.Count);
  309. foreach (var entry in fullList)
  310. {
  311. if (entry == fullList[0])
  312. {
  313. Assert.IsTrue(entry.All);
  314. }
  315. else
  316. {
  317. Assert.IsFalse(entry.All);
  318. }
  319. if (entry.Entry.Path == changes[toggledIndex1].Path || entry.Entry.Path == changes[toggledIndex2].Path)
  320. {
  321. Assert.IsTrue(entry.Toggled);
  322. }
  323. else
  324. {
  325. Assert.IsFalse(entry.Toggled);
  326. }
  327. }
  328. var toggledList = model.GetToggledEntries();
  329. Assert.AreEqual(toggledCount, toggledList.Count);
  330. foreach (var entry in toggledList)
  331. {
  332. Assert.IsTrue(entry.Entry.Path == changes[toggledIndex1].Path || entry.Entry.Path == changes[toggledIndex2].Path);
  333. Assert.IsFalse(entry.All);
  334. Assert.IsTrue(entry.Toggled);
  335. }
  336. var untoggledList = model.GetUntoggledEntries();
  337. Assert.AreEqual(entryCount - toggledCount, untoggledList.Count);
  338. foreach (var entry in untoggledList)
  339. {
  340. Assert.IsTrue(entry.Entry.Path != changes[toggledIndex1].Path && entry.Entry.Path != changes[toggledIndex2].Path);
  341. Assert.IsFalse(entry.All);
  342. Assert.IsFalse(entry.Toggled);
  343. }
  344. }
  345. [Test]
  346. public void ChangesModel_SearchFilters_CaseInsensitive()
  347. {
  348. var changes = new List<IChangeEntry>();
  349. AddEntry(changes, "alpha1", ChangeEntryStatus.Modified, false);
  350. AddEntry(changes, "alpha2", ChangeEntryStatus.Modified, false);
  351. AddEntry(changes, "bravo", ChangeEntryStatus.Modified, false);
  352. AddEntry(changes, "charlie", ChangeEntryStatus.Modified, false);
  353. AddEntry(changes, "Delta3", ChangeEntryStatus.Modified, false);
  354. AddEntry(changes, "delta4", ChangeEntryStatus.Modified, false);
  355. AddEntry(changes, "delta5", ChangeEntryStatus.Modified, false);
  356. AddEntry(changes, "echo", ChangeEntryStatus.Modified, false);
  357. AddEntry(changes, "Foxtrot6", ChangeEntryStatus.Modified, false);
  358. AddEntry(changes, "Foxtrot7", ChangeEntryStatus.Modified, false);
  359. AddEntry(changes, "golf", ChangeEntryStatus.Modified, false);
  360. var dictionary = new Dictionary<string, bool>
  361. {
  362. ["delta5"] = true, ["Foxtrot6"] = true, ["Foxtrot7"] = true, ["golf"] = true
  363. };
  364. var model = new TestableChangesModel();
  365. model.OnStart();
  366. model.SetToggled(dictionary);
  367. model.UpdateChangeList(changes);
  368. var fullList = model.GetAllEntries();
  369. Assert.AreEqual(changes.Count, model.TotalCount);
  370. Assert.AreEqual(changes.Count + 1, fullList.Count);
  371. Assert.IsTrue(fullList[0].All);
  372. var searchFullList = model.GetAllEntries("alpha");
  373. Assert.AreEqual(2, searchFullList.Count);
  374. foreach (var entry in searchFullList)
  375. {
  376. Assert.IsFalse(entry.All);
  377. Assert.IsFalse(entry.Toggled);
  378. }
  379. var toggledList = model.GetToggledEntries();
  380. Assert.AreEqual(dictionary.Count, toggledList.Count);
  381. foreach (var entry in toggledList)
  382. {
  383. Assert.IsFalse(entry.All);
  384. }
  385. var searchToggledList = model.GetToggledEntries("fox");
  386. Assert.AreEqual(2, searchToggledList.Count);
  387. foreach (var entry in searchToggledList)
  388. {
  389. Assert.IsTrue(entry.Entry.Path.ToLower().Contains("fox"));
  390. Assert.IsFalse(entry.All);
  391. Assert.IsTrue(entry.Toggled);
  392. }
  393. var untoggledList = model.GetUntoggledEntries();
  394. Assert.AreEqual(changes.Count - dictionary.Count, untoggledList.Count);
  395. var searchUntoggledList = model.GetUntoggledEntries("Del");
  396. Assert.AreEqual(2, searchUntoggledList.Count);
  397. foreach (var entry in searchUntoggledList)
  398. {
  399. Assert.IsTrue(entry.Entry.Path.ToLower().Contains("del"));
  400. Assert.AreNotEqual("delta5", entry.Entry.Path);
  401. Assert.IsFalse(entry.All);
  402. Assert.IsFalse(entry.Toggled);
  403. }
  404. Assert.AreEqual(dictionary.Count, model.ToggledCount);
  405. }
  406. [Test]
  407. public void TestRequestInitialData()
  408. {
  409. var provider = new TestSourceControlProvider();
  410. var model = new ChangesModel(provider);
  411. model.OnStart();
  412. var callCount = 0;
  413. bool? callValue = null;
  414. model.BusyStatusUpdated += b =>
  415. {
  416. callCount++;
  417. callValue = b;
  418. };
  419. Assert.IsFalse(model.Busy);
  420. model.RequestInitialData();
  421. Assert.AreEqual(1, provider.RequestedChangeListCount);
  422. Assert.IsNotNull(provider.RequestedChangeListCallback);
  423. Assert.IsTrue(model.Busy);
  424. Assert.IsTrue(callValue);
  425. provider.RequestedChangeListCallback.Invoke(new List<IChangeEntry>());
  426. Assert.IsFalse(model.Busy);
  427. Assert.IsFalse(callValue);
  428. Assert.AreEqual(2, callCount);
  429. }
  430. [Test]
  431. public void TestReceiveUpdatedChangeListEvent()
  432. {
  433. var provider = new TestSourceControlProvider();
  434. var model = new ChangesModel(provider);
  435. model.OnStart();
  436. var callCount = 0;
  437. bool? callValue = null;
  438. model.BusyStatusUpdated += b =>
  439. {
  440. callCount++;
  441. callValue = b;
  442. };
  443. Assert.IsFalse(model.Busy);
  444. provider.TriggerUpdatedChangeEntries();
  445. Assert.AreEqual(1, provider.RequestedChangeListCount);
  446. Assert.IsNotNull(provider.RequestedChangeListCallback);
  447. Assert.IsTrue(model.Busy);
  448. Assert.IsTrue(callValue);
  449. provider.RequestedChangeListCallback.Invoke(new List<IChangeEntry>());
  450. Assert.IsFalse(model.Busy);
  451. Assert.IsFalse(callValue);
  452. Assert.AreEqual(2, callCount);
  453. }
  454. [Test]
  455. public void TestRequestDiff()
  456. {
  457. var provider = new TestSourceControlProvider();
  458. var model = new ChangesModel(provider);
  459. model.OnStart();
  460. const string path = "path";
  461. model.RequestDiffChanges(path);
  462. Assert.AreEqual(1, provider.RequestedDiffChangesCount);
  463. Assert.AreEqual(path, provider.RequestedDiffChangesPath);
  464. }
  465. [Test]
  466. public void TestRequestDiscard()
  467. {
  468. var provider = new TestSourceControlProvider();
  469. var model = new ChangesModel(provider);
  470. model.OnStart();
  471. const string path = "path";
  472. var entry = new ChangeEntry(path);
  473. model.RequestDiscard(entry);
  474. Assert.AreEqual(1, provider.RequestedDiscardCount);
  475. Assert.AreEqual(path, provider.RequestedDiscardEntry?.Path);
  476. }
  477. [Test]
  478. public void TestRequestPublish()
  479. {
  480. var provider = new TestSourceControlProvider();
  481. var model = new ChangesModel(provider);
  482. model.OnStart();
  483. const string message = "message";
  484. model.RequestPublish(message, new List<IChangeEntry> { new ChangeEntry("path1"), new ChangeEntry("path2")});
  485. Assert.AreEqual(1, provider.RequestedPublishCount);
  486. Assert.AreEqual(message, provider.RequestedPublishMessage);
  487. Assert.AreEqual(2, provider.RequestedPublishList?.Count);
  488. }
  489. static void AddEntry(ICollection<IChangeEntry> list, string pathTag, ChangeEntryStatus status, bool staged, bool unmerged = false)
  490. {
  491. list.Add(new ChangeEntry(pathTag, $"Original{pathTag}", status, staged, unmerged));
  492. }
  493. static List<IChangeEntry> BuildChangesList(int count)
  494. {
  495. var changes = new List<IChangeEntry>();
  496. for (var i = 0; i < count; i++)
  497. {
  498. AddEntry(changes, $"Path{i}", ChangeEntryStatus.Modified, false);
  499. }
  500. return changes;
  501. }
  502. }
  503. }