PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Xtensive.Core/Xtensive.Core.Tests/ObjectMapping/MapperHandlingCollectionTests.cs

https://code.google.com/p/dataobjectsdotnet/
C# | 395 lines | 367 code | 23 blank | 5 comment | 13 complexity | 3816b902985bde508b2f923b8dcf6ac9 MD5 | raw file
Possible License(s): AGPL-3.0
  1. // Copyright (C) 2010 Xtensive LLC.
  2. // All rights reserved.
  3. // For conditions of distribution and use, see license.
  4. // Created by: Alexander Nikolaev
  5. // Created: 2010.01.14
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using Xtensive.Core.ObjectMapping;
  10. using Xtensive.Core.ObjectMapping.Model;
  11. using Xtensive.Core.Testing;
  12. using Xtensive.Core.Tests.ObjectMapping.SourceModel;
  13. using Xtensive.Core.Tests.ObjectMapping.TargetModel;
  14. using NUnit.Framework;
  15. using Action=Xtensive.Core.Tests.ObjectMapping.SourceModel.Action;
  16. namespace Xtensive.Core.Tests.ObjectMapping
  17. {
  18. [TestFixture]
  19. public sealed class MapperHandlingCollectionTests : MapperTestBase
  20. {
  21. [Test]
  22. public void CollectionTransformationTest()
  23. {
  24. var mapper = GetPetOwnerAnimalMapper();
  25. var source = GetSourcePetOwner();
  26. var target = (PetOwnerDto) mapper.Transform(source);
  27. Assert.IsNotNull(target);
  28. AssertAreEqual(source, target);
  29. Assert.AreEqual(source.Pets.Count, target.Pets.Count);
  30. foreach (var animalDto in target.Pets)
  31. Assert.IsNotNull(source.Pets.Where(p => p.Id == animalDto.Id).Single());
  32. }
  33. [Test]
  34. public void CollectionComparisonTest()
  35. {
  36. var mapper = GetPetOwnerAnimalMapper();
  37. var source = GetSourcePetOwner();
  38. var original = (PetOwnerDto) mapper.Transform(source);
  39. var modified = (PetOwnerDto) original.Clone();
  40. const int removedIndex = 1;
  41. var key = modified.Pets[removedIndex].Id;
  42. var removedAnimal0 = original.Pets.Single(p => p.Id == key);
  43. modified.Pets.RemoveAt(removedIndex);
  44. key = modified.Pets[removedIndex].Id;
  45. var removedAnimal1 = original.Pets.Single(p => p.Id == key);
  46. modified.Pets.RemoveAt(removedIndex);
  47. var newAnimal = new AnimalDto {Id = Guid.NewGuid(), Name = "N"};
  48. modified.Pets.Add(newAnimal);
  49. ValidateCollectionComparison(mapper, original, modified, newAnimal, removedAnimal0, removedAnimal1);
  50. }
  51. [Test]
  52. public void TransformationOfPrimitiveCustomCollectionTest()
  53. {
  54. var mapping = new MappingBuilder()
  55. .MapType<PrimitiveCollectionContainer, PrimitiveCollectionContainerDto, Guid>(c => c.Id, c => c.Id)
  56. .Build();
  57. var mapper = new DefaultMapper(mapping);
  58. var source = new PrimitiveCollectionContainer();
  59. source.Collection.Add(3);
  60. source.Collection.Add(2);
  61. source.Collection.Add(1);
  62. var target = (PrimitiveCollectionContainerDto) mapper.Transform(source);
  63. Assert.AreEqual(3, target.Collection[0]);
  64. Assert.AreEqual(2, target.Collection[1]);
  65. Assert.AreEqual(1, target.Collection[2]);
  66. }
  67. [Test]
  68. public void TransformationOfComplexCustomCollectionTest()
  69. {
  70. var mapping = new MappingBuilder().MapType<ComplexCollectionContainer, ComplexCollectionContainerDto, Guid>(c => c.Id, c => c.Id)
  71. .MapType<Person, PersonDto, int>(p => p.Id, p => p.Id).Build();
  72. var mapper = new DefaultMapper(mapping);
  73. var source = new ComplexCollectionContainer();
  74. source.Collection.Add(GetSourcePerson(3));
  75. source.Collection.Add(GetSourcePerson(2));
  76. source.Collection.Add(GetSourcePerson(1));
  77. var target = (ComplexCollectionContainerDto) mapper.Transform(source);
  78. Assert.AreEqual(3, target.Collection[0].Id);
  79. Assert.AreEqual(2, target.Collection[1].Id);
  80. Assert.AreEqual(1, target.Collection[2].Id);
  81. }
  82. [Test]
  83. public void TransformationWhenGraphRootContainsPrimitiveObjectsTest()
  84. {
  85. var mapper = GetPersonStructureMapper();
  86. Person person;
  87. int intItem;
  88. string stringItem;
  89. Structure structureItem;
  90. var source = GetSourcePersonStructure(out person, out intItem, out stringItem, out structureItem);
  91. var target = (List<object>) mapper.Transform(source);
  92. Assert.AreEqual(source.Count, target.Count);
  93. Assert.AreEqual(((Person) source[0]).Id, ((PersonDto) target[0]).Id);
  94. Assert.AreEqual(((Person) source[0]).FirstName, ((PersonDto) target[0]).FirstName);
  95. Assert.AreEqual(intItem, target[1]);
  96. Assert.AreEqual(stringItem, target[2]);
  97. var targetStructureItem = (StructureDto) target[3];
  98. Assert.AreEqual(structureItem.DateTime, targetStructureItem.DateTime);
  99. Assert.AreEqual(structureItem.Int, targetStructureItem.Int);
  100. Assert.AreEqual(structureItem.String, targetStructureItem.String);
  101. var intArray = new[] {8, 9, 0};
  102. source.Add(intArray);
  103. AssertEx.ThrowsArgumentException(() => mapper.Transform(source));
  104. }
  105. [Test]
  106. public void ComparisonWhenRootsContainsValueObjectsTest()
  107. {
  108. var mapper = GetPersonStructureMapper();
  109. Person person;
  110. int intItem;
  111. string stringItem;
  112. Structure structureItem;
  113. var source = GetSourcePersonStructure(out person, out intItem, out stringItem, out structureItem);
  114. var original = (List<object>) mapper.Transform(source);
  115. var modified = Clone(original);
  116. var newFirstName = ((PersonDto) modified[0]).FirstName + "Modified0";
  117. ((PersonDto) modified[0]).FirstName = newFirstName;
  118. modified[1] = ((int) modified[1]) + 3;
  119. modified[2] = ((string) modified[2]) + "Modified1";
  120. var modifiedStructureItem = (StructureDto) modified[3];
  121. modifiedStructureItem.Int += 5;
  122. var operations = ((DefaultOperationLog) mapper.Compare(original, modified).Operations).ToList();
  123. Assert.AreEqual(1, operations.Count);
  124. ValidatePropertyOperation((PersonDto) original[0], operations[0], p => p.FirstName,
  125. newFirstName, OperationType.SetProperty);
  126. var intArray = new[] {8, 9, 0};
  127. modified.Add(intArray);
  128. AssertEx.ThrowsArgumentException(() => mapper.Compare(original, modified));
  129. }
  130. [Test]
  131. public void TransformationOfValueTypesCollectionTest()
  132. {
  133. var mapper = GetAccountMapper();
  134. var source = GetSourceAccount();
  135. var target = (AccountDto) mapper.Transform(source);
  136. Assert.AreEqual(source.Id, target.Id);
  137. Assert.IsTrue(source.AccessRights
  138. .All(ar => target.AccessRights
  139. .Where(tar => tar.Action==ar.Action && tar.ObjectId.SequenceEqual(ar.ObjectId)).Count()==1));
  140. Assert.IsTrue(source.PasswordHash.SequenceEqual(target.PasswordHash));
  141. }
  142. [Test]
  143. public void ComparisonOfValueTypesCollectionTest()
  144. {
  145. var mapper = GetAccountMapper();
  146. var source = GetSourceAccount();
  147. var original = (AccountDto) mapper.Transform(source);
  148. var modified = Clone(original);
  149. modified.PasswordHash[3] += 5;
  150. var oldAccessRight = modified.AccessRights[0];
  151. modified.AccessRights[0] = new AccessRightDto {
  152. Action = Action.Write, ObjectId = oldAccessRight.ObjectId
  153. };
  154. modified.AccessRights[0].ObjectId[2] += 7;
  155. var operations = ((DefaultOperationLog) mapper.Compare(original, modified).Operations).ToList();
  156. Assert.AreEqual(1, operations.Count);
  157. ValidatePropertyOperation(original, operations[0], a => a.PasswordHash,
  158. modified.PasswordHash, OperationType.SetProperty);
  159. }
  160. [Test]
  161. public void EnsureDepthLimitWhenCollectionPropertyLocatedOnGraphTruncationPointTest()
  162. {
  163. var settings = new MapperSettings {
  164. GraphDepthLimit = 1, GraphTruncationType = GraphTruncationType.SetDefaultValue
  165. };
  166. var mapping = new MappingBuilder()
  167. .MapType<CollectionContainer, CollectionContainerDto, Guid>(c => c.Id, c => c.Id).Build();
  168. var mapper = new DefaultMapper(mapping, settings);
  169. var source0 = new CollectionContainer {AuxInt = 1};
  170. var source10 = new CollectionContainer {AuxInt = 11};
  171. var source11 = new CollectionContainer {AuxInt = 12};
  172. source0.Collection.Add(source10);
  173. source0.Collection.Add(source11);
  174. var source20 = new CollectionContainer {AuxInt = 20};
  175. var source21 = new CollectionContainer {AuxInt = 21};
  176. source10.Collection.Add(source20);
  177. source10.Collection.Add(source21);
  178. var target = (CollectionContainerDto) mapper.Transform(source0);
  179. Assert.IsNull(target.Collection[0].Collection);
  180. Assert.IsNull(target.Collection[1].Collection);
  181. }
  182. [Test]
  183. public void ArrayTransformationTest()
  184. {
  185. var mapping = GetArrayContainerMapping();
  186. var source = GetSourceArrayContainer();
  187. var mapper = new DefaultMapper(mapping);
  188. var target = (ArrayContainerDto) mapper.Transform(source);
  189. Assert.AreEqual(source.Id, target.Id);
  190. Assert.IsTrue(source.IntArray.SequenceEqual(target.IntArray));
  191. Action<ArrayElement[], ArrayElementDto[]> validator = null;
  192. validator = (sourceArray, targetArray) => {
  193. Assert.AreEqual(sourceArray.Length, targetArray.Length);
  194. for (var i = 0; i < sourceArray.Length; i++) {
  195. var sourceItem = sourceArray[i];
  196. var targetItem = targetArray[i];
  197. Assert.AreEqual(sourceItem.Id, targetItem.Id);
  198. Assert.AreEqual(sourceItem.Aux, targetItem.Aux);
  199. if (sourceItem.NestedElements!=null)
  200. validator(sourceItem.NestedElements, targetItem.NestedElements);
  201. }
  202. };
  203. validator.Invoke(source.EntityArray, target.EntityArray);
  204. }
  205. [Test]
  206. public void ArrayComparisonTest()
  207. {
  208. var mapping = GetArrayContainerMapping();
  209. var source = GetSourceArrayContainer();
  210. var mapper = new DefaultMapper(mapping);
  211. var original = (ArrayContainerDto) mapper.Transform(source);
  212. var modified = Clone(original);
  213. var removedElement = original.EntityArray[1].NestedElements[0];
  214. var newArrayElementDto = new ArrayElementDto {
  215. Id = Guid.NewGuid(), Aux = "NewElement", NestedElements = new[] {
  216. new ArrayElementDto {Id = Guid.NewGuid(), Aux = "NewElement10"},
  217. new ArrayElementDto {Id = Guid.NewGuid(), Aux = "NewElement11"}
  218. }
  219. };
  220. modified.EntityArray[1].NestedElements[0] = newArrayElementDto;
  221. var operations = ((DefaultOperationLog) mapper.Compare(original, modified).Operations).ToList();
  222. Assert.AreEqual(11, operations.Count);
  223. ValidateObjectCreation(newArrayElementDto, operations[0]);
  224. ValidateObjectCreation(newArrayElementDto.NestedElements[0], operations[1]);
  225. ValidateObjectCreation(newArrayElementDto.NestedElements[1], operations[2]);
  226. ValidatePropertyOperation(newArrayElementDto, operations[3], e => e.Aux,
  227. newArrayElementDto.Aux, OperationType.SetProperty);
  228. var nestedElementsProperty = typeof (ArrayElementDto).GetProperty("NestedElements");
  229. ValidateItemAdditionOperation(newArrayElementDto, operations[4], nestedElementsProperty,
  230. newArrayElementDto.NestedElements[0]);
  231. ValidateItemAdditionOperation(newArrayElementDto, operations[5], nestedElementsProperty,
  232. newArrayElementDto.NestedElements[1]);
  233. ValidatePropertyOperation(newArrayElementDto.NestedElements[0], operations[6],
  234. e => e.Aux, newArrayElementDto.NestedElements[0].Aux, OperationType.SetProperty);
  235. ValidatePropertyOperation(newArrayElementDto.NestedElements[1], operations[7],
  236. e => e.Aux, newArrayElementDto.NestedElements[1].Aux, OperationType.SetProperty);
  237. ValidateItemAdditionOperation(original.EntityArray[1], operations[8], nestedElementsProperty,
  238. newArrayElementDto);
  239. ValidateItemRemovalOperation(original.EntityArray[1], operations[9], nestedElementsProperty,
  240. removedElement);
  241. ValidateObjectRemoval(removedElement, operations[10]);
  242. }
  243. private static DefaultMapper GetPersonStructureMapper()
  244. {
  245. var mapping = new MappingBuilder().MapType<Person, PersonDto, int>(p => p.Id, p => p.Id)
  246. .MapStructure<Structure, StructureDto>().Build();
  247. return new DefaultMapper(mapping);
  248. }
  249. private static DefaultMapper GetAccountMapper()
  250. {
  251. var mapping = new MappingBuilder()
  252. .MapType<Account, AccountDto, Guid>(a => a.Id, a => a.Id)
  253. .TrackChanges(a => a.AccessRights, false)
  254. .MapStructure<AccessRight, AccessRightDto>()
  255. .Build();
  256. return new DefaultMapper(mapping);
  257. }
  258. private static List<object> GetSourcePersonStructure(out Person person, out int intItem,
  259. out string stringItem, out Structure structureItem)
  260. {
  261. var source = new List<object>();
  262. person = new Person {BirthDate = DateTime.Now, FirstName = "Name"};
  263. source.Add(person);
  264. intItem = 5;
  265. source.Add(intItem);
  266. stringItem = "String";
  267. source.Add(stringItem);
  268. structureItem = new Structure {DateTime = DateTime.Now, Int = 3, String = "String"};
  269. source.Add(structureItem);
  270. return source;
  271. }
  272. private static MappingDescription GetArrayContainerMapping()
  273. {
  274. return new MappingBuilder()
  275. .MapType<ArrayContainer, ArrayContainerDto, Guid>(a => a.Id, a => a.Id)
  276. .MapType<ArrayElement, ArrayElementDto, Guid>(a => a.Id, a => a.Id)
  277. .Build();
  278. }
  279. private static Account GetSourceAccount()
  280. {
  281. return new Account {
  282. AccessRights = new List<AccessRight> {
  283. new AccessRight {Action = Action.Read, ObjectId = new[] {1L, 2, 3, 4, 5}},
  284. new AccessRight {Action = Action.Write, ObjectId = new[] {0L, 9, 8, 7, 6}}
  285. },
  286. PasswordHash = new byte[] {1, 8, 89, 29, 50, 77}
  287. };
  288. }
  289. private static ArrayContainer GetSourceArrayContainer()
  290. {
  291. return new ArrayContainer {IntArray = new[] {6, 8, 2, 9, 7}, EntityArray = new[] {
  292. new ArrayElement {
  293. Aux = "Element00", NestedElements = new[] {
  294. new ArrayElement {Aux = "Element10"}, new ArrayElement {Aux = "Element11"},
  295. new ArrayElement {Aux = "Element12"}
  296. }},
  297. new ArrayElement {Aux = "Element01", NestedElements = new[] {
  298. new ArrayElement {Aux = "Element13"}, new ArrayElement {Aux = "Element14"},
  299. new ArrayElement {Aux = "Element15"}
  300. }}
  301. }
  302. };
  303. }
  304. private static void ValidateCollectionComparison(DefaultMapper mapper, PetOwnerDto original,
  305. PetOwnerDto modified, AnimalDto newAnimal, AnimalDto removedAnimal0, AnimalDto removedAnimal1)
  306. {
  307. var itemRemovalPublished0 = false;
  308. var itemRemovalPublished1 = false;
  309. var creationPublished = false;
  310. var removalPublished0 = false;
  311. var removalPublished1 = false;
  312. var additionPublished = false;
  313. var petPropertyCounts = CreateCountsForMutableProperties(typeof (AnimalDto), mapper);
  314. const string petsName = "Pets";
  315. var eventRaisingCount = 0;
  316. Action<Operation> validator = descriptor => {
  317. eventRaisingCount++;
  318. switch (descriptor.Type) {
  319. case OperationType.AddItem:
  320. Assert.AreEqual(original, descriptor.Object);
  321. Assert.AreEqual(petsName, descriptor.PropertyPath[0].SystemProperty.Name);
  322. Assert.AreEqual(newAnimal, descriptor.Value);
  323. additionPublished = true;
  324. break;
  325. case OperationType.RemoveItem:
  326. if (ReferenceEquals(removedAnimal0, descriptor.Value))
  327. itemRemovalPublished0 = true;
  328. else if (ReferenceEquals(removedAnimal1, descriptor.Value))
  329. itemRemovalPublished1 = true;
  330. else
  331. Assert.Fail();
  332. Assert.AreEqual(petsName, descriptor.PropertyPath[0].SystemProperty.Name);
  333. Assert.AreEqual(original, descriptor.Object);
  334. break;
  335. case OperationType.CreateObject:
  336. creationPublished = true;
  337. Assert.AreEqual(newAnimal, descriptor.Object);
  338. Assert.IsNull(descriptor.PropertyPath);
  339. Assert.IsNull(descriptor.Value);
  340. break;
  341. case OperationType.RemoveObject:
  342. if (ReferenceEquals(removedAnimal0, descriptor.Object))
  343. removalPublished0 = true;
  344. else if (ReferenceEquals(removedAnimal1, descriptor.Object))
  345. removalPublished1 = true;
  346. else
  347. Assert.Fail();
  348. Assert.IsNull(descriptor.PropertyPath);
  349. Assert.IsNull(descriptor.Value);
  350. break;
  351. case OperationType.SetProperty:
  352. petPropertyCounts[descriptor.PropertyPath[0].SystemProperty.Name] += 1;
  353. Assert.AreSame(newAnimal, descriptor.Object);
  354. var expectedValue = descriptor.PropertyPath[0].SystemProperty.GetValue(newAnimal, null);
  355. Assert.AreEqual(expectedValue, descriptor.Value);
  356. break;
  357. default:
  358. Assert.Fail();
  359. break;
  360. }
  361. };
  362. ((DefaultOperationLog) mapper.Compare(original, modified).Operations).ForEach(validator);
  363. Assert.AreEqual(7, eventRaisingCount);
  364. Assert.IsTrue(itemRemovalPublished0);
  365. Assert.IsTrue(itemRemovalPublished1);
  366. Assert.IsTrue(removalPublished0);
  367. Assert.IsTrue(removalPublished1);
  368. Assert.IsTrue(creationPublished);
  369. Assert.IsTrue(additionPublished);
  370. }
  371. }
  372. }