aboutsummaryrefslogtreecommitdiffstats
path: root/tests/Test_Utils/Test_LazyFactory.Set.cs
blob: ee49c22e30d498bc28d93b9986433db5924c8510 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/***************************************************************************************************
 Copyright (C) 2025 The Qt Company Ltd.
 SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
***************************************************************************************************/

using Qt.DotNet.Utils;

namespace Test_Utils
{
    public partial class Test_LazyFactory
    {
        // 1. Simple Set stores value for later Get
        [TestMethod]
        public void Set_InstanceProperty_StoresValue_ForSubsequentGet()
        {
            var factory = new LazyFactory();
            var foo = new Dummy();

            factory.Set(() => foo.Prop, 99);
            Assert.AreEqual(99, factory.Get(() => foo.Prop));
        }

        // 2. Set overwrites any previous lazy or explicit value
        [TestMethod]
        public void Set_OverridesPriorValue_LazyOrExplicit()
        {
            var factory = new LazyFactory();
            var foo = new Dummy();

            // first via initFunc
            Assert.AreEqual(1, factory.Get(() => foo.Prop, () => 1));
            // now override
            factory.Set(() => foo.Prop, 42);
            Assert.AreEqual(42, factory.Get(() => foo.Prop));
        }

        // 3. Distinct owners remain isolated after Set
        [TestMethod]
        public void Set_DistinctOwners_DoNotAffectEachOther()
        {
            var factory = new LazyFactory();
            var a = new Dummy();
            var b = new Dummy();

            factory.Set(() => a.Prop, 5);
            factory.Set(() => b.Prop, 10);

            Assert.AreEqual(5, factory.Get(() => a.Prop));
            Assert.AreEqual(10, factory.Get(() => b.Prop));
        }

        // 4. Set raises PropertyChanged on the factory with owner as sender
        [TestMethod]
        public void Set_RaisesPropertyChanged_OnFactory_WithOwnerAsSender()
        {
            var factory = new LazyFactory();
            var foo = new NotifyingDummy();
            var fired = false;

            factory.PropertyChanged += (sender, args) =>
            {
                fired = true;
                // the sender should be the owner instance
                Assert.AreSame(foo, sender);
                Assert.AreEqual(nameof(NotifyingDummy.Prop), args.PropertyName);
            };

            factory.Set(() => foo.Prop, 123);

            Assert.IsTrue(fired);
        }

        // 5. Set on static property still stores & Get retrieves
        [TestMethod]
        public void Set_StaticProperty_StoresAndRetrievesValue()
        {
            var factory = new LazyFactory();

            factory.Set(() => AppSettings.Threshold, 0.9);
            Assert.AreEqual(0.9, factory.Get(() => AppSettings.Threshold));
        }

        // 6. Set does not raise PropertyChanged for static props
        [TestMethod]
        public void Set_StaticProperty_DoesNotRaisePropertyChanged()
        {
            var factory = new LazyFactory();
            var fired = false;

            factory.PropertyChanged += (_, _) => fired = true;

            factory.Set(() => AppSettings.IsFeatureEnabled, true);
            Assert.IsTrue(fired, "Static owner (Type) does not implement INotifyPropertyChanged, "
               + "though PropertyChanged needs to be raised anyway.");
        }

        // 7. Concurrent Set + Get: Set shall win, and subsequent Gets see latest
        [TestMethod]
        public void ConcurrentSetAndGet_UpdatesAtomically()
        {
            var factory = new LazyFactory();
            var foo = new Dummy();

            // Start a Set in background, sleep then assign
            var setter = Task.Run(() =>
            {
                Thread.Sleep(50);
                factory.Set(() => foo.Prop, 77);
            });

            // Multiple Gets will spin until they see the update:
            int observed;
            do {
                observed = factory.Get(() => foo.Prop);
            } while (observed == 0);

            setter.Wait();
            Assert.AreEqual(77, observed);
        }

        // 8. Setting to default(T) shall write into cache
        [TestMethod]
        public void Set_ToDefaultValue_IsStoredAndReturned()
        {
            var factory = new LazyFactory();
            var foo = new Dummy { Prop = 5 };

            // override back to default( int ) == 0
            factory.Set(() => foo.Prop, 0);
            Assert.AreEqual(0, factory.Get(() => foo.Prop));
        }

        // 9. Set after exception‑throwing initFunc still persists
        [TestMethod]
        public void Set_AfterFailedInit_PersistsNewValue()
        {
            var factory = new LazyFactory();
            var foo = new Dummy();
            Func<int> badInit = () => throw new InvalidOperationException();

            // fail first
            Assert.ThrowsExactly<InvalidOperationException>(() => factory.Get(() => foo.Prop, badInit));

            // now Set explicitly
            factory.Set(() => foo.Prop, 55);
            Assert.AreEqual(55, factory.Get(() => foo.Prop));
        }
    }
}