示例#1
0
            public void WithIllegal()
            {
                var expected = // "Track.Changes(x, y) failed for item: ObservableCollection<ComplexType>[0].Illegal.\r\n" +
                               "Track.Changes(x, y) failed.\r\n" +
                               "The type IllegalType does not notify changes.\r\n" +
                               "The property WithIllegal.Illegal of type IllegalType is not supported.\r\n" +
                               "Solve the problem by any of:\r\n" +
                               "* Implement INotifyPropertyChanged for IllegalType or use a type that does.\r\n" +
                               "* Make IllegalType immutable or use an immutable type.\r\n" +
                               "  - For immutable types the following must hold:\r\n" +
                               "    - Must be a sealed class or a struct.\r\n" +
                               "    - All fields and properties must be readonly.\r\n" +
                               "    - All field and property types must be immutable.\r\n" +
                               "    - All indexers must be readonly.\r\n" +
                               "    - Event fields are ignored.\r\n" +
                               "* Use PropertiesSettings and specify how change tracking is performed:\r\n" +
                               "  - ReferenceHandling.Structural means that a the entire graph is tracked.\r\n" +
                               "  - ReferenceHandling.References means that only the root level changes are tracked.\r\n" +
                               "  - Exclude a combination of the following:\r\n" +
                               "    - The property WithIllegal.Illegal.\r\n" +
                               "    - The type IllegalType.\r\n";

                var item      = new WithIllegal();
                var settings  = PropertiesSettings.GetOrCreate();
                var exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item, settings));

                Assert.AreEqual(expected, exception.Message);

                exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item));
                Assert.AreEqual(expected, exception.Message);
            }
示例#2
0
        public void IsImmutable(Type type, bool expected)
        {
            var settings    = PropertiesSettings.GetOrCreate();
            var isImmutable = settings.IsImmutable(type);

            Assert.AreEqual(expected, isImmutable);
        }
示例#3
0
            public void WithComplexProperty()
            {
                var x = new WithComplexProperty {
                    ComplexType = new ComplexType("a", 1)
                };
                var y = new WithComplexProperty {
                    ComplexType = new ComplexType("a", 1)
                };
                var changes  = new List <string>();
                var settings = PropertiesSettings.GetOrCreate();

                using (var tracker = Track.IsDirty(x, y, settings))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                }

                x.ComplexType = new ComplexType("b", 2);
                CollectionAssert.IsEmpty(changes);

                var wrx  = new System.WeakReference(x);
                var wrxc = new System.WeakReference(x.ComplexType);
                var wry  = new System.WeakReference(y);
                var wryc = new System.WeakReference(y.ComplexType);

                x = null;
                y = null;
                System.GC.Collect();
                Assert.AreEqual(false, wrx.IsAlive);
                Assert.AreEqual(false, wrxc.IsAlive);
                Assert.AreEqual(false, wry.IsAlive);
                Assert.AreEqual(false, wryc.IsAlive);
            }
示例#4
0
            public void CheckReferenceHandlingWhenRootError(bool requiresRef)
            {
                var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Throw);
                var type     = typeof(List <ComplexType>);
                var errors   = ErrorBuilder.Start()
                               .CheckRequiresReferenceHandling(type, settings, _ => requiresRef)
                               .Finnish();

                if (requiresRef)
                {
                    var error    = RequiresReferenceHandling.Enumerable;
                    var expected = new[] { error };
                    CollectionAssert.AreEqual(expected, errors.Errors);
                    var stringBuilder = new StringBuilder();
                    var message       = stringBuilder.AppendNotSupported(errors)
                                        .ToString();
                    var expectedMessage = "";
                    Assert.AreEqual(expectedMessage, message);

                    stringBuilder = new StringBuilder();
                    message       = stringBuilder.AppendSuggestExclude(errors)
                                    .ToString();
                    expectedMessage = "";
                    Assert.AreEqual(expectedMessage, message);
                }
                else
                {
                    Assert.AreEqual(null, errors);
                }
            }
            public void CheckIndexersWhenError()
            {
                var settings = PropertiesSettings.GetOrCreate();
                var type     = typeof(ErrorTypes.WithIndexer);
                var errors   = ErrorBuilder.Start()
                               .CheckIndexers(type, settings)
                               .Finnish();
                var indexer  = type.GetProperties().Single();
                var error    = UnsupportedIndexer.GetOrCreate(indexer);
                var expected = new[] { error };

                CollectionAssert.AreEqual(expected, errors.Errors);
                var stringBuilder = new StringBuilder();
                var message       = stringBuilder.AppendNotSupported(errors)
                                    .ToString();
                var expectedMessage = "Indexers are not supported.\r\n" +
                                      "  - The property WithIndexer.Item is an indexer and not supported.\r\n";

                Assert.AreEqual(expectedMessage, message);

                stringBuilder = new StringBuilder();
                message       = stringBuilder.AppendSuggestExclude(errors)
                                .ToString();
                expectedMessage = "  - Exclude a combination of the following:\r\n" +
                                  "    - The indexer property WithIndexer.Item.\r\n";
                Assert.AreEqual(expectedMessage, message);
            }
        public void GetRecursive()
        {
            var x        = new object();
            var y        = new object();
            var settings = PropertiesSettings.GetOrCreate();
            var rec      = TrackerCache.GetOrAdd(x, y, settings, p => new Recursive(p, settings));

            Assert.AreSame(rec, rec.Value.Next);
        }
示例#7
0
            public void CheckReferenceHandlingWhenValid(Type type)
            {
                var settings = PropertiesSettings.GetOrCreate();
                var errors   = ErrorBuilder.Start()
                               .CheckRequiresReferenceHandling(type, settings, _ => false)
                               .Finnish();

                Assert.IsNull(errors);
            }
示例#8
0
            public void CheckNotifiesWhenValid(Type type)
            {
                var settings = PropertiesSettings.GetOrCreate();
                var errors   = ErrorBuilder.Start()
                               .CheckNotifies(type, settings)
                               .Finnish();

                Assert.IsNull(errors);
            }
        public void ReturnsDifferentForDifferentSettings()
        {
            var x  = new ComplexType();
            var y  = new ComplexType();
            var t1 = DiffBuilder.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.Structural));
            var t2 = DiffBuilder.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.Throw));

            Assert.AreNotSame(t1, t2);
        }
        public void Equals(string xs, string ys, bool expected)
        {
            var x        = xs.Split(',').Select(int.Parse);
            var y        = ys.Split(',').Select(int.Parse);
            var comparer = EnumerableEqualByComparer <int> .Default;
            var settings = PropertiesSettings.GetOrCreate();

            Assert.AreEqual(expected, comparer.Equals(x, y, settings, null));
        }
示例#11
0
        public void Caches(BindingFlags bindingFlags, ReferenceHandling referenceHandling)
        {
            var settings = PropertiesSettings.GetOrCreate(referenceHandling, bindingFlags);

            Assert.AreEqual(bindingFlags, settings.BindingFlags);
            Assert.AreEqual(referenceHandling, settings.ReferenceHandling);
            var second = PropertiesSettings.GetOrCreate(referenceHandling, BindingFlags.Public);

            Assert.AreSame(settings, second);
        }
示例#12
0
            public void CheckReferenceHandlingWhenPropertyError()
            {
                var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Throw);
                var type     = typeof(With <List <int> >);
                var errors   = ErrorBuilder.Start()
                               .CheckRequiresReferenceHandling(type, settings, _ => true)
                               .Finnish();
                var expected = new[] { RequiresReferenceHandling.ComplexType };

                CollectionAssert.AreEqual(expected, errors.Errors);
            }
            public void ReturnsDifferentForDifferentSettings()
            {
                var x = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var y = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var t1 = DirtyTrackerNode.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.Structural), true);
                var t2 = DirtyTrackerNode.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.References), true);

                Assert.AreNotSame(t1, t2);
            }
示例#14
0
        public void ReturnsDifferentForDifferentPairs()
        {
            var x = new ComplexType();
            var y = new ComplexType();
            var structuralSettings = PropertiesSettings.GetOrCreate(ReferenceHandling.Structural);

            using (var t1 = DiffBuilder.GetOrCreate(x, y, structuralSettings))
            {
                using (var t2 = DiffBuilder.GetOrCreate(y, x, structuralSettings))
                {
                    Assert.AreNotSame(t1, t2);
                }
            }
        }
示例#15
0
        public void IgnoresCollectionProperties(Type type)
        {
            var settings      = PropertiesSettings.GetOrCreate();
            var propertyInfos = type.GetProperties(Constants.DefaultFieldBindingFlags);

            if (type != typeof(int[]))
            {
                CollectionAssert.IsNotEmpty(propertyInfos);
            }

            foreach (var propertyInfo in propertyInfos)
            {
                Assert.AreEqual(true, settings.IsIgnoringProperty(propertyInfo));
            }
        }
示例#16
0
        public void ReturnsSameWhileAlive()
        {
            var x = new ComplexType();
            var y = new ComplexType();
            var structuralSettings = PropertiesSettings.GetOrCreate(ReferenceHandling.Structural);
            var t1 = DiffBuilder.GetOrCreate(x, y, structuralSettings);
            var t2 = DiffBuilder.GetOrCreate(x, y, structuralSettings);

            Assert.AreSame(t1, t2);
            t1.Dispose();
            t2.Dispose();

            var t4 = DiffBuilder.GetOrCreate(x, y, structuralSettings);

            Assert.AreNotSame(t1, t4);
        }
            public void ReturnsDifferentForDifferentPairs()
            {
                var x = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var y = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Structural);

                using (var t1 = DirtyTrackerNode.GetOrCreate(x, y, settings, isRoot: true))
                {
                    using (var t2 = DirtyTrackerNode.GetOrCreate(y, x, settings, isRoot: true))
                    {
                        Assert.AreNotSame(t1, t2);
                    }
                }
            }
            public void ReturnsSameWhileAlive()
            {
                var x        = new WithSimpleProperties();
                var y        = new WithSimpleProperties();
                var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Structural);
                var t1       = DirtyTrackerNode.GetOrCreate(x, y, settings, true);
                var t2       = DirtyTrackerNode.GetOrCreate(x, y, settings, true);

                Assert.AreSame(t1, t2);
                t1.Dispose();
                var t3 = DirtyTrackerNode.GetOrCreate(x, y, settings, true);

                Assert.AreSame(t1, t3);
                t2.Dispose();
                t3.Dispose();

                var t4 = DirtyTrackerNode.GetOrCreate(x, y, settings, true);

                Assert.AreNotSame(t1, t4);
            }
示例#19
0
        public void GetOrAddUsingReferencePair()
        {
            var x    = new object();
            var y    = new object();
            var pair = ReferencePair.GetOrCreate(x, y);

            Assert.AreEqual(pair.Count, 1);
            var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Structural);

            using (var created = TrackerCache.GetOrAdd(x, y, settings, p => p))
            {
                Assert.AreSame(pair, created.Value);
                Assert.AreEqual(pair.Count, 2);
            }

            Assert.AreEqual(1, pair.Count);

            pair.Dispose();
            Assert.AreEqual(0, pair.Count);
        }
示例#20
0
            public void CheckNotifiesWithInt()
            {
                var settings = PropertiesSettings.GetOrCreate();
                var type     = typeof(ErrorTypes.With <int>);
                var errors   = ErrorBuilder.Start().CheckNotifies(type, settings).Finnish();
                var expected = new[] { TypeMustNotifyError.GetOrCreate(type) };

                CollectionAssert.AreEqual(expected, errors.Errors);
                var stringBuilder = new StringBuilder();
                var message       = stringBuilder.AppendNotSupported(errors)
                                    .ToString();
                var expectedMessage = "The type With<int> does not notify changes.\r\n";

                Assert.AreEqual(expectedMessage, message);

                stringBuilder = new StringBuilder();
                message       = stringBuilder.AppendSuggestExclude(errors)
                                .ToString();
                expectedMessage = string.Empty;
                Assert.AreEqual(expectedMessage, message);
            }
示例#21
0
            public void CreateAndDisposeStopsListeningToSubProperties()
            {
                var x = new WithComplexProperty {
                    ComplexType = new ComplexType("a", 1)
                };
                var y = new WithComplexProperty {
                    ComplexType = new ComplexType("a", 1)
                };
                var changes  = new List <string>();
                var settings = PropertiesSettings.GetOrCreate();

                using (var tracker = Track.IsDirty(x, y, settings))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                }

                x.ComplexType.Value++;
                CollectionAssert.IsEmpty(changes);
            }
            public void CreateAndDisposeExplicitSetting(ReferenceHandling referenceHandling)
            {
                var x = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var y = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var propertyChanges = new List <string>();
                var expectedChanges = new List <string>();

                using (var tracker = Track.IsDirty(x, y, PropertiesSettings.GetOrCreate(referenceHandling)))
                {
                    tracker.PropertyChanged += (_, e) => propertyChanges.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(propertyChanges);

                    x.Value++;
                    Assert.AreEqual(true, tracker.IsDirty);
                    Assert.AreEqual("WithSimpleProperties Value x: 2 y: 1", tracker.Diff.ToString("", " "));
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, propertyChanges);
                }

                x.Value++;
                CollectionAssert.AreEqual(expectedChanges, propertyChanges);

#if (!DEBUG) // debug build keeps instances alive longer for nicer debugging experience
                var wrx = new System.WeakReference(x);
                var wry = new System.WeakReference(y);
                x = null;
                y = null;
                System.GC.Collect();
                Assert.AreEqual(false, wrx.IsAlive);
                Assert.AreEqual(false, wry.IsAlive);
#endif
            }
示例#23
0
            public void TracksNestedWithExplicitSetting()
            {
                var x               = new WithComplexProperty();
                var y               = new WithComplexProperty();
                var changes         = new List <string>();
                var expectedChanges = new List <string>();

                using (var tracker = Track.IsDirty(x, y, PropertiesSettings.GetOrCreate()))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(changes);

                    x.Name = "newName1";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty Name x: newName1 y: null", tracker.Diff.ToString(string.Empty, " "));

                    y.Name = "newName1";
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType x: Gu.State.Tests.DirtyTrackerTypes+ComplexType y: null", tracker.Diff.ToString(string.Empty, " "));

                    y.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType.Name = "newName2";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Name x: newName2 y: a", tracker.Diff.ToString(string.Empty, " "));

                    x.ComplexType.Value++;
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.Add("Diff");
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Name x: newName2 y: a Value x: 2 y: 1", tracker.Diff.ToString(string.Empty, " "));

                    y.ComplexType.Name = "newName2";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.Add("Diff");
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Value x: 2 y: 1", tracker.Diff.ToString(string.Empty, " "));

                    y.ComplexType.Value++;
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);
                }
            }
示例#24
0
            public void WithListOfInts()
            {
                var expected = "Track.Changes(x, y) failed.\r\n" +
                               "The collection type List<int> does not notify changes.\r\n" +
                               "The property With<List<int>>.Value of type List<int> is not supported.\r\n" +
                               "Solve the problem by any of:\r\n" +
                               "* Use a type that implements INotifyCollectionChanged instead of List<int>.\r\n" +
                               "* Use an immutable type instead of List<int>.\r\n" +
                               "  - For immutable types the following must hold:\r\n" +
                               "    - Must be a sealed class or a struct.\r\n" +
                               "    - All fields and properties must be readonly.\r\n" +
                               "    - All field and property types must be immutable.\r\n" +
                               "    - All indexers must be readonly.\r\n" +
                               "    - Event fields are ignored.\r\n" +
                               "* Use PropertiesSettings and specify how change tracking is performed:\r\n" +
                               "  - ReferenceHandling.Structural means that a the entire graph is tracked.\r\n" +
                               "  - ReferenceHandling.References means that only the root level changes are tracked.\r\n" +
                               "  - Exclude a combination of the following:\r\n" +
                               "    - The property With<List<int>>.Value.\r\n" +
                               "    - The type List<int>.\r\n";
                var item      = new With <List <int> >();
                var exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item));

                Assert.AreEqual(expected, exception.Message);
                exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item, PropertiesSettings.GetOrCreate()));
                Assert.AreEqual(expected, exception.Message);
            }
示例#25
0
            public void IllegalEnumerable()
            {
                var expected = "Track.Changes(x, y) failed.\r\n" +
                               "The collection type IllegalEnumerable does not notify changes.\r\n" +
                               "Solve the problem by any of:\r\n" +
                               "* Implement INotifyCollectionChanged for IllegalEnumerable or use a type that does.\r\n" +
                               "* Use PropertiesSettings and specify how change tracking is performed:\r\n" +
                               "  - ReferenceHandling.Structural means that a the entire graph is tracked.\r\n" +
                               "  - ReferenceHandling.References means that only the root level changes are tracked.\r\n";

                var item      = new IllegalEnumerable();
                var exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item));

                Assert.AreEqual(expected, exception.Message);

                exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item, PropertiesSettings.GetOrCreate()));
                Assert.AreEqual(expected, exception.Message);
            }
示例#26
0
        public void IgnoresNull()
        {
            var settings = PropertiesSettings.GetOrCreate();

            Assert.AreEqual(true, settings.IsIgnoringProperty(null));
        }
示例#27
0
            public void WithComplexProperty()
            {
                var expected = "Track.VerifyCanTrackIsDirty(x, y) failed.\r\n" +
                               "The property WithComplexProperty.ComplexType of type ComplexType is not supported.\r\n" +
                               "Solve the problem by any of:\r\n" +
                               "* Implement IEquatable<WithComplexProperty> for WithComplexProperty or use a type that does.\r\n" +
                               "* Implement IEquatable<ComplexType> for ComplexType or use a type that does.\r\n" +
                               "* Use PropertiesSettings and specify how comparing is performed:\r\n" +
                               "  - ReferenceHandling.Structural means that a deep equals is performed.\r\n" +
                               "  - ReferenceHandling.References means that reference equality is used.\r\n" +
                               "  - Exclude a combination of the following:\r\n" +
                               "    - The property WithComplexProperty.ComplexType.\r\n" +
                               "    - The type ComplexType.\r\n";

                var exception = Assert.Throws <NotSupportedException>(() => Track.VerifyCanTrackIsDirty <WithComplexProperty>(ReferenceHandling.Throw));

                Assert.AreEqual(expected, exception.Message);
                exception = Assert.Throws <NotSupportedException>(() => Track.VerifyCanTrackIsDirty(typeof(WithComplexProperty), PropertiesSettings.GetOrCreate(ReferenceHandling.Throw)));
                Assert.AreEqual(expected, exception.Message);

                Assert.DoesNotThrow(() => Track.VerifyCanTrackIsDirty <WithComplexProperty>(ReferenceHandling.Structural));
                Assert.DoesNotThrow(() => Track.VerifyCanTrackIsDirty <WithComplexProperty>(ReferenceHandling.References));
            }
示例#28
0
 public void WithSimpleProperties(ReferenceHandling referenceHandling)
 {
     Synchronize.VerifyCanSynchronize <WithSimpleProperties>(referenceHandling);
     Synchronize.VerifyCanSynchronize <WithSimpleProperties>(PropertiesSettings.GetOrCreate(referenceHandling));
     Synchronize.VerifyCanSynchronize(typeof(WithSimpleProperties), PropertiesSettings.GetOrCreate(referenceHandling));
 }
示例#29
0
 public void WithSimpleProperties(ReferenceHandling referenceHandling)
 {
     Track.VerifyCanTrackChanges <WithSimpleProperties>(referenceHandling);
     Track.VerifyCanTrackChanges <WithSimpleProperties>(PropertiesSettings.GetOrCreate(referenceHandling));
     Track.VerifyCanTrackChanges(typeof(WithSimpleProperties), PropertiesSettings.GetOrCreate(referenceHandling));
 }