/test/SlowTests/Smuggler/SmugglerConflicts.cs

https://github.com/fitzchak/ravendb · C# · 352 lines · 300 code · 52 blank · 0 comment · 4 complexity · 8e9604cc87ec750fc543e6d186b61938 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using FastTests;
  7. using FastTests.Server.Replication;
  8. using Raven.Client.Documents;
  9. using Raven.Client.Documents.Operations;
  10. using Raven.Client.Documents.Smuggler;
  11. using Raven.Client.ServerWide;
  12. using Raven.Tests.Core.Utils.Entities;
  13. using Xunit;
  14. namespace SlowTests.Smuggler
  15. {
  16. public class SmugglerConflicts : ReplicationTestBase
  17. {
  18. private readonly string _file;
  19. private readonly DocumentStore _store1, _store2;
  20. public SmugglerConflicts()
  21. {
  22. _file = Path.GetTempFileName();
  23. _store1 = GetDocumentStore(new Options
  24. {
  25. ModifyDatabaseName = s => $"{s}_store1",
  26. ModifyDatabaseRecord = record =>
  27. {
  28. record.ConflictSolverConfig = new ConflictSolver
  29. {
  30. ResolveToLatest = false,
  31. ResolveByCollection = new Dictionary<string, ScriptResolver>()
  32. };
  33. }
  34. });
  35. _store2 = GetDocumentStore(new Options
  36. {
  37. ModifyDatabaseName = s => $"{s}_store2",
  38. ModifyDatabaseRecord = record =>
  39. {
  40. record.ConflictSolverConfig = new ConflictSolver
  41. {
  42. ResolveToLatest = false,
  43. ResolveByCollection = new Dictionary<string, ScriptResolver>()
  44. };
  45. }
  46. });
  47. }
  48. public override void Dispose()
  49. {
  50. _store1.Dispose();
  51. _store2.Dispose();
  52. File.Delete(_file);
  53. base.Dispose();
  54. }
  55. [Fact]
  56. public async Task CanExportAndImportWithConflicts_ToTheSameDatabase()
  57. {
  58. await GenerateConflict(_store1, _store2);
  59. await _store1.Smuggler.ExportAsync(new DatabaseSmugglerExportOptions(), _file);
  60. await AssertImport(_store1);
  61. }
  62. [Fact]
  63. public async Task CanExportAndImportWithConflicts_ToNewDatabase()
  64. {
  65. await GenerateConflict(_store1, _store2);
  66. await _store1.Smuggler.ExportAsync(new DatabaseSmugglerExportOptions(), _file);
  67. using (var store3 = GetDocumentStore(new Options
  68. {
  69. ModifyDatabaseName = s => $"{s}_store3"
  70. }))
  71. {
  72. await AssertImport(store3);
  73. }
  74. }
  75. [Fact]
  76. public async Task ToDatabaseWithSameDocumentWithoutConflicts_DeleteTheDocumentAndGenerateTheSameConflicts()
  77. {
  78. await GenerateConflict(_store1, _store2);
  79. await _store1.Smuggler.ExportAsync(new DatabaseSmugglerExportOptions(), _file);
  80. using (var store3 = GetDocumentStore(new Options
  81. {
  82. ModifyDatabaseName = s => $"{s}_store3"
  83. }))
  84. {
  85. await SetupReplicationAsync(_store2, store3);
  86. WaitForDocument(store3, "people/1-A");
  87. var stats = await store3.Maintenance.SendAsync(new GetStatisticsOperation());
  88. Assert.Equal(7, stats.CountOfDocuments);
  89. Assert.Equal(0, stats.CountOfDocumentsConflicts);
  90. Assert.Equal(0, stats.CountOfConflicts);
  91. Assert.Equal(0, stats.CountOfTombstones);
  92. await AssertImport(store3);
  93. }
  94. }
  95. [Fact]
  96. public async Task CanExportAndImportWithConflicts_ToDatabaseWithDifferentDocument_DeleteTheDocumentWithoutCreatingConflictForIt()
  97. {
  98. await GenerateConflict(_store1, _store2);
  99. await _store1.Smuggler.ExportAsync(new DatabaseSmugglerExportOptions(), _file);
  100. using (var session = _store2.OpenAsyncSession())
  101. {
  102. var user = await session.LoadAsync<User>("users/fitzchak");
  103. user.LastName = "Update to generate another conflict.";
  104. user.Name = "Fitzchak 3";
  105. await session.SaveChangesAsync();
  106. }
  107. await AssertImport(_store2);
  108. }
  109. [Fact]
  110. public async Task ToDatabaseWithDifferentConflicts_AndTheImportedConflictsInAdditionToTheExistingConflicts()
  111. {
  112. await GenerateConflict(_store1, _store2);
  113. await _store1.Smuggler.ExportAsync(new DatabaseSmugglerExportOptions(), _file);
  114. using (var store3 = GetDocumentStore(new Options
  115. {
  116. ModifyDatabaseName = s => $"{s}_store3",
  117. ModifyDatabaseRecord = record =>
  118. {
  119. record.ConflictSolverConfig = new ConflictSolver
  120. {
  121. ResolveToLatest = false,
  122. ResolveByCollection = new Dictionary<string, ScriptResolver>()
  123. };
  124. }
  125. }))
  126. using (var store4 = GetDocumentStore(new Options
  127. {
  128. ModifyDatabaseName = s => $"{s}_store4",
  129. ModifyDatabaseRecord = record =>
  130. {
  131. record.ConflictSolverConfig = new ConflictSolver
  132. {
  133. ResolveToLatest = false,
  134. ResolveByCollection = new Dictionary<string, ScriptResolver>()
  135. };
  136. }
  137. }))
  138. {
  139. await GenerateConflict2(store3, store4);
  140. await AssertImport2(store3);
  141. }
  142. }
  143. private async Task GenerateConflict(DocumentStore store1, DocumentStore store2)
  144. {
  145. await SetDatabaseId(store1, new Guid("11111111-1111-1111-1111-111111111111"));
  146. await SetDatabaseId(store2, new Guid("22222222-2222-2222-2222-222222222222"));
  147. using (var session = store1.OpenAsyncSession())
  148. {
  149. await session.StoreAsync(new User { Name = "Fitzchak 1", Id = "users/fitzchak" });
  150. await session.StoreAsync(new Person { Name = "Name1" });
  151. await session.StoreAsync(new Person { Name = "Name2" });
  152. await session.StoreAsync(new Person { Name = "Name - No conflict" });
  153. await session.StoreAsync(new Company { Name = "Hibernating Rhinos " });
  154. await session.SaveChangesAsync();
  155. }
  156. using (var session = store2.OpenAsyncSession())
  157. {
  158. await session.StoreAsync(new User { Name = "Fitzchak 2", Id = "users/fitzchak" });
  159. await session.StoreAsync(new Person { Name = "Name11" });
  160. await session.StoreAsync(new Person { Name = "Name12" });
  161. await session.StoreAsync(new Person { Name = "Name - No conflict" });
  162. await session.StoreAsync(new Company { Name = "Hibernating Rhinos 2 " });
  163. await session.SaveChangesAsync();
  164. }
  165. for (int i = 0; i < 2; i++)
  166. {
  167. using (var session = store1.OpenAsyncSession())
  168. {
  169. var company = await session.LoadAsync<Company>("companies/1-A");
  170. var person = await session.LoadAsync<Person>("people/1-A");
  171. company.Name += " update " + i;
  172. person.Name += " update " + i;
  173. await session.StoreAsync(company);
  174. await session.StoreAsync(person);
  175. await session.SaveChangesAsync();
  176. }
  177. }
  178. using (var session = store1.OpenAsyncSession())
  179. {
  180. var person = await session.LoadAsync<Person>("people/2-A");
  181. Assert.NotNull(person);
  182. session.Delete(person);
  183. await session.SaveChangesAsync();
  184. }
  185. await SetupReplicationAsync(store2, store1);
  186. Assert.Equal(2, WaitUntilHasConflict(store1, "users/fitzchak").Length);
  187. var stats = await store1.Maintenance.SendAsync(new GetStatisticsOperation());
  188. Assert.Equal(3, stats.CountOfDocuments);
  189. Assert.Equal(4, stats.CountOfDocumentsConflicts);
  190. Assert.Equal(8, stats.CountOfConflicts);
  191. Assert.Equal(0, stats.CountOfTombstones);
  192. stats = await store2.Maintenance.SendAsync(new GetStatisticsOperation());
  193. Assert.Equal(7, stats.CountOfDocuments);
  194. Assert.Equal(0, stats.CountOfDocumentsConflicts);
  195. Assert.Equal(0, stats.CountOfConflicts);
  196. Assert.Equal(0, stats.CountOfTombstones);
  197. }
  198. private async Task GenerateConflict2(DocumentStore store3, DocumentStore store4)
  199. {
  200. await SetDatabaseId(store3, new Guid("33333333-3333-3333-3333-333333333333"));
  201. await SetDatabaseId(store4, new Guid("44444444-4444-4444-4444-444444444444"));
  202. using (var session = store3.OpenAsyncSession())
  203. {
  204. await session.StoreAsync(new User { Name = "Fitzchak 3", Id = "users/fitzchak" });
  205. await session.StoreAsync(new Person { Name = "Name13" });
  206. await session.StoreAsync(new Person { Name = "Name23" });
  207. await session.StoreAsync(new Person { Name = "Name - No conflict" });
  208. await session.StoreAsync(new Company { Name = "Hibernating Rhinos " });
  209. await session.SaveChangesAsync();
  210. }
  211. using (var session = store4.OpenAsyncSession())
  212. {
  213. await session.StoreAsync(new User { Name = "Fitzchak 4", Id = "users/fitzchak" });
  214. await session.StoreAsync(new Person { Name = "Name14" });
  215. await session.StoreAsync(new Person { Name = "Name14" });
  216. await session.StoreAsync(new Person { Name = "Name - No conflict" });
  217. await session.StoreAsync(new Company { Name = "Hibernating Rhinos 2 " });
  218. await session.SaveChangesAsync();
  219. }
  220. for (int i = 0; i < 2; i++)
  221. {
  222. using (var session = store3.OpenAsyncSession())
  223. {
  224. var company = await session.LoadAsync<Company>("companies/1-A");
  225. var person = await session.LoadAsync<Person>("people/1-A");
  226. company.Name += " update " + i;
  227. person.Name += " update " + i;
  228. await session.StoreAsync(company);
  229. await session.StoreAsync(person);
  230. await session.SaveChangesAsync();
  231. }
  232. }
  233. using (var session = store3.OpenAsyncSession())
  234. {
  235. var person = await session.LoadAsync<Person>("people/2-A");
  236. Assert.NotNull(person);
  237. session.Delete(person);
  238. await session.SaveChangesAsync();
  239. }
  240. await SetupReplicationAsync(store4, store3);
  241. Assert.Equal(2, WaitUntilHasConflict(store3, "users/fitzchak").Length);
  242. var stats = await store3.Maintenance.SendAsync(new GetStatisticsOperation());
  243. Assert.Equal(3, stats.CountOfDocuments);
  244. Assert.Equal(4, stats.CountOfDocumentsConflicts);
  245. Assert.Equal(8, stats.CountOfConflicts);
  246. Assert.Equal(0, stats.CountOfTombstones);
  247. stats = await store4.Maintenance.SendAsync(new GetStatisticsOperation());
  248. Assert.Equal(7, stats.CountOfDocuments);
  249. Assert.Equal(0, stats.CountOfDocumentsConflicts);
  250. Assert.Equal(0, stats.CountOfConflicts);
  251. Assert.Equal(0, stats.CountOfTombstones);
  252. }
  253. private async Task AssertImport(DocumentStore store)
  254. {
  255. for (int i = 0; i < 3; i++)
  256. {
  257. await store.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), _file);
  258. var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());
  259. Assert.Equal(3, stats.CountOfDocuments);
  260. Assert.Equal(4, stats.CountOfDocumentsConflicts);
  261. Assert.Equal(8, stats.CountOfConflicts);
  262. Assert.Equal(0, stats.CountOfTombstones);
  263. var conflicts = (await store.Commands().GetConflictsForAsync("users/fitzchak")).ToList();
  264. Assert.Equal(2, conflicts.Count);
  265. Assert.Equal("A:3-EREREREREREREREREREREQ", conflicts[0].ChangeVector);
  266. Assert.True(conflicts[0].Doc.TryGet(nameof(User.Name), out string name));
  267. Assert.Equal("Fitzchak 1", name);
  268. Assert.Equal("A:3-IiIiIiIiIiIiIiIiIiIiIg", conflicts[1].ChangeVector);
  269. Assert.True(conflicts[1].Doc.TryGet(nameof(User.Name), out name));
  270. Assert.Equal("Fitzchak 2", name);
  271. }
  272. }
  273. private async Task AssertImport2(DocumentStore store)
  274. {
  275. for (int i = 0; i < 3; i++)
  276. {
  277. await store.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), _file);
  278. var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());
  279. Assert.Equal(3, stats.CountOfDocuments);
  280. Assert.Equal(4, stats.CountOfDocumentsConflicts);
  281. Assert.Equal(13, stats.CountOfConflicts);
  282. Assert.Equal(0, stats.CountOfTombstones);
  283. var conflicts = (await store.Commands().GetConflictsForAsync("users/fitzchak")).ToList();
  284. Assert.Equal(4, conflicts.Count);
  285. Assert.Equal("A:3-EREREREREREREREREREREQ", conflicts[0].ChangeVector);
  286. Assert.True(conflicts[0].Doc.TryGet(nameof(User.Name), out string name));
  287. Assert.Equal("Fitzchak 1", name);
  288. Assert.Equal("A:3-IiIiIiIiIiIiIiIiIiIiIg", conflicts[1].ChangeVector);
  289. Assert.True(conflicts[1].Doc.TryGet(nameof(User.Name), out name));
  290. Assert.Equal("Fitzchak 2", name);
  291. Assert.Equal("A:3-MzMzMzMzMzMzMzMzMzMzMw", conflicts[2].ChangeVector);
  292. Assert.True(conflicts[2].Doc.TryGet(nameof(User.Name), out name));
  293. Assert.Equal("Fitzchak 3", name);
  294. Assert.Equal("A:3-RERERERERERERERERERERA", conflicts[3].ChangeVector);
  295. Assert.True(conflicts[3].Doc.TryGet(nameof(User.Name), out name));
  296. Assert.Equal("Fitzchak 4", name);
  297. }
  298. }
  299. }
  300. }