public void TestSimpleUnchanged()
        {
            var w = Mutable.From(0);

            w.PropertyChanged += (s, e) => { throw new Exception("Shouldn't fire Changed event if value is unchanged"); };
            w.Value            = 0;
        }
        public void TestRecursion()
        {
            var w = Mutable.From(0);

            // Not okay to set it to a different value (hence expected exception)
            w.PropertyChanged += (s, e) => w.Value++;
            w.Value++;
        }
        public void TestReentrance()
        {
            var w = Mutable.From(0);

            // Okay to assign to writeable that just changed as long as it's the same (new) value
            w.PropertyChanged += (s, e) => w.Value = 1;
            w.Value++;
        }
        public void TestSimpleChanged()
        {
            var w       = Mutable.From(0);
            var changed = false;

            w.PropertyChanged += (s, e) => changed = true;
            w.Value            = 1;
            Assert.IsTrue(changed);
        }
        public void TestNotification()
        {
            var x = Mutable.From(1);
            var y = Mutable.From(2);
            var z = Computed.From(() => x.Value + y.Value);

            Assert.AreEqual(3, z.Value);
            Assert.AreEqual(false, z.IsActive);

            x.Value = 3;

            Assert.AreEqual(5, z.Value);
            Assert.AreEqual(false, z.IsActive);

            var p = Computed.From(() => z.Value * 2);

            Assert.AreEqual(10, p.Value);
            Assert.AreEqual(false, p.IsActive);
            Assert.AreEqual(false, z.IsActive);

            var notified = 0;

            PropertyChangedEventHandler changed = (s, e) => notified++;

            p.PropertyChanged += changed;

            Assert.AreEqual(true, p.IsActive);
            Assert.AreEqual(true, z.IsActive);
            Assert.AreEqual(0, notified);

            y.Value = 1;

            Assert.AreEqual(true, p.IsActive);
            Assert.AreEqual(true, z.IsActive);
            Assert.AreEqual(1, notified);
            Assert.AreEqual(8, p.Value);

            p.PropertyChanged -= changed;

            Assert.AreEqual(false, p.IsActive);
            Assert.AreEqual(false, z.IsActive);
            Assert.AreEqual(1, notified);
            Assert.AreEqual(8, p.Value);

            x.Value = 1;

            Assert.AreEqual(false, p.IsActive);
            Assert.AreEqual(false, z.IsActive);
            Assert.AreEqual(1, notified);
            Assert.AreEqual(4, p.Value);
        }
        public void TestCustomEquality()
        {
            // Default comparison uses equals method
            var changed = false;
            var w       = Mutable.From(new[] { 5, 20, 13 });

            w.PropertyChanged += (s, e) => changed = true;

            w.Value = new[] { 5, 20, 13 }; // even though contents are same, still counts as changed
            Assert.IsTrue(changed);
            changed = false;

            // Replace with order-agnostic sequence comparison
            w.EqualityComparer = (a, b) => a.OrderBy(i => i).SequenceEqual(b.OrderBy(i => i));

            // Same contents in different order, no Changed event
            w.Value = new[] { 5, 13, 20 };
            Assert.IsFalse(changed);

            // Change one value and it triggers Changed
            w.Value = new[] { 5, 3, 20 };
            Assert.IsTrue(changed);
        }