public void ShouldDetectBaseClassRemovalComplex() { var objPrev = DynamicClass.Create("B", DynamicClass.Create("W", DynamicClass.Create("Z", DynamicClass.Create("A", DynamicClass.Create("X", DynamicClass.Create("O")))))).Instantiate(); var objCurr = DynamicClass.Create("B", DynamicClass.Create("A")).Instantiate(); var stampPrev = new TypeStamp(objPrev.GetType()); var stampCurr = new TypeStamp(objCurr.GetType()); var compareResult = stampCurr.CompareWith(stampPrev); Assert.IsEmpty(compareResult.FieldsMoved); Assert.IsEmpty(compareResult.ClassesAdded); Assert.IsEmpty(compareResult.ClassesRenamed); Assert.IsEmpty(compareResult.FieldsRemoved); Assert.IsEmpty(compareResult.FieldsAdded); Assert.IsEmpty(compareResult.FieldsChanged); Assert.AreEqual(4, compareResult.ClassesRemoved.Count); Assert.IsTrue(compareResult.ClassesRemoved[0].StartsWith("O")); Assert.IsTrue(compareResult.ClassesRemoved[1].StartsWith("X")); Assert.IsTrue(compareResult.ClassesRemoved[2].StartsWith("Z")); Assert.IsTrue(compareResult.ClassesRemoved[3].StartsWith("W")); }
public void ShouldFindNoDifferences() { var obj = DynamicClass.Create("C", DynamicClass.Create("B", DynamicClass.Create("A"))).Instantiate(); var stamp = new TypeStamp(obj.GetType()); var compareResult = stamp.CompareWith(stamp); Assert.IsTrue(compareResult.Empty); }
public void ShouldNotDetectInsertionOfTransientField() { var objPrev = DynamicClass.Create("A").Instantiate(); var objCurr = DynamicClass.Create("A").WithTransientField("a", typeof(int)).Instantiate(); var stampPrev = new TypeStamp(objPrev.GetType()); var stampCurr = new TypeStamp(objCurr.GetType()); var compareResult = stampCurr.CompareWith(stampPrev); Assert.IsTrue(compareResult.Empty); }
public void ShouldDetectInsertionOfOverridingField() { var objPrev = DynamicClass.Create("A", DynamicClass.Create("Base").WithField("a", typeof(int))).Instantiate(); var objCurr = DynamicClass.Create("A", DynamicClass.Create("Base").WithField("a", typeof(int))).WithField("a", typeof(int)).Instantiate(); var stampPrev = new TypeStamp(objPrev.GetType()); var stampCurr = new TypeStamp(objCurr.GetType()); var compareResult = stampCurr.CompareWith(stampPrev); Assert.IsEmpty(compareResult.ClassesAdded); Assert.IsEmpty(compareResult.ClassesRemoved); Assert.IsEmpty(compareResult.ClassesRenamed); Assert.IsEmpty(compareResult.FieldsMoved); Assert.IsEmpty(compareResult.FieldsRemoved); Assert.IsEmpty(compareResult.FieldsChanged); Assert.AreEqual(1, compareResult.FieldsAdded.Count); Assert.AreEqual("a", compareResult.FieldsAdded[0].Name); }
public void ShouldDetectClassRenameSimple() { var objPrev = DynamicClass.Create("A").Instantiate(); var objCurr = DynamicClass.Create("B").Instantiate(); var stampPrev = new TypeStamp(objPrev.GetType()); var stampCurr = new TypeStamp(objCurr.GetType()); var compareResult = stampCurr.CompareWith(stampPrev); Assert.IsEmpty(compareResult.ClassesAdded); Assert.IsEmpty(compareResult.ClassesRemoved); Assert.IsEmpty(compareResult.FieldsMoved); Assert.IsEmpty(compareResult.FieldsRemoved); Assert.IsEmpty(compareResult.FieldsAdded); Assert.IsEmpty(compareResult.FieldsChanged); Assert.AreEqual(1, compareResult.ClassesRenamed.Count); Assert.IsTrue(compareResult.ClassesRenamed[0].Item1.StartsWith("A")); Assert.IsTrue(compareResult.ClassesRenamed[0].Item2.StartsWith("B")); }
public void ReadStamp(Type type, bool treatCollectionAsUserObject) { if (!StampHelpers.IsStampNeeded(type, treatCollectionAsUserObject)) { return; } if (stampCache.ContainsKey(type)) { return; } var streamTypeStamp = new TypeStamp(); streamTypeStamp.ReadFrom(reader); if (streamTypeStamp.ModuleGUID == type.Module.ModuleVersionId) { stampCache.Add(type, StampHelpers.GetFieldsInSerializationOrder(type, true).Select(x => new FieldInfoOrEntryToOmit(x)).ToList()); return; } if (versionToleranceLevel == VersionToleranceLevel.Guid) { throw new InvalidOperationException(string.Format("The class was serialized with different module version id {0}, current one is {1}.", streamTypeStamp.ModuleGUID, type.Module.ModuleVersionId)); } var result = new List <FieldInfoOrEntryToOmit>(); var assemblyTypeStamp = new TypeStamp(type, true); if (assemblyTypeStamp.Classes.Count != streamTypeStamp.Classes.Count && !versionToleranceLevel.HasFlag(VersionToleranceLevel.InheritanceChainChange)) { throw new InvalidOperationException(string.Format("Class hierarchy changed. Expected {0} classes in a chain, but found {1}.", assemblyTypeStamp.Classes.Count, streamTypeStamp.Classes.Count)); } var cmpResult = assemblyTypeStamp.CompareWith(streamTypeStamp); if (cmpResult.ClassesRenamed.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.TypeNameChanged)) { if (versionToleranceLevel.HasFlag(VersionToleranceLevel.AssemblyVersionChanged)) { foreach (var renamed in cmpResult.ClassesRenamed) { var beforeStrippedVersion = Regex.Replace(renamed.Item1, "Version=[0-9.]*", string.Empty); var afterStrippedVersion = Regex.Replace(renamed.Item2, "Version=[0-9.]*", string.Empty); if (beforeStrippedVersion != afterStrippedVersion) { throw new InvalidOperationException(string.Format("Class name changed from {0} to {1}", cmpResult.ClassesRenamed[0].Item1, cmpResult.ClassesRenamed[0].Item2)); } } } else { throw new InvalidOperationException(string.Format("Class name changed from {0} to {1}", cmpResult.ClassesRenamed[0].Item1, cmpResult.ClassesRenamed[0].Item2)); } } if (cmpResult.FieldsAdded.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.FieldAddition)) { throw new InvalidOperationException(string.Format("Field added: {0}.", cmpResult.FieldsAdded[0].Name)); } if (cmpResult.FieldsRemoved.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.FieldRemoval)) { throw new InvalidOperationException(string.Format("Field removed: {0}.", cmpResult.FieldsRemoved[0].Name)); } if (cmpResult.FieldsMoved.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.FieldMove)) { throw new InvalidOperationException(string.Format("Field moved: {0}.", cmpResult.FieldsMoved.ElementAt(0).Key.Name)); } foreach (var field in streamTypeStamp.GetFieldsInAlphabeticalOrder()) { if (cmpResult.FieldsRemoved.Contains(field)) { result.Add(new FieldInfoOrEntryToOmit(Type.GetType(field.TypeAQN))); } else if (cmpResult.FieldsMoved.ContainsKey(field)) { var moved = cmpResult.FieldsMoved[field]; var finfo = Type.GetType(moved.OwningTypeAQN).GetField(moved.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); result.Add(new FieldInfoOrEntryToOmit(finfo)); } else { var finfo = Type.GetType(field.OwningTypeAQN).GetField(field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); result.Add(new FieldInfoOrEntryToOmit(finfo)); } } foreach (var field in assemblyTypeStamp.GetFieldsInAlphabeticalOrder().Where(x => x.IsConstructor)) { var finfo = Type.GetType(field.OwningTypeAQN).GetField(field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); result.Add(new FieldInfoOrEntryToOmit(finfo)); } stampCache.Add(type, result); }