[loader] Init MonoClass:sizes.element_size lazily (Fixes #43563) (#5559)
[mono.git] / mono / tests / sgen-toggleref.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Threading;
5 using System.Runtime.InteropServices;
6 using System.Runtime.CompilerServices;
7 using MonoTests.Helpers;
8
9 public class Toggleref {
10         public int __test;
11         public string id;
12         public List<object> link = new List<object> ();
13         public const int DROP = 0;
14         public const int STRONG = 1;
15         public const int WEAK = 2;
16         
17         ~Toggleref () {
18
19         }
20 }
21
22 [StructLayout (LayoutKind.Explicit)]
23 public struct Helper {
24         [FieldOffset(0)]
25         IntPtr ptr;
26         [FieldOffset(0)]
27         object obj;
28         public static IntPtr ObjToPtr (object obj)
29         {
30                 Helper h = default (Helper);
31                 h.obj = obj;
32                 return h.ptr;
33         }
34 }
35
36 class Driver {
37         static WeakReference<Toggleref> root, child;
38
39         [DllImport ("__Internal", EntryPoint="mono_gc_toggleref_add")]
40         static extern int mono_gc_toggleref_add (IntPtr ptr, bool strong_ref);
41
42         static void Register (object obj)
43         {
44                 mono_gc_toggleref_add (Helper.ObjToPtr (obj), true);
45         }
46
47         static Toggleref a, b;
48
49         static void SetupLinks () {
50                 var r = new Toggleref () { id = "root" };
51                 var c = new Toggleref () { id = "child" };
52                 r.link.Add (c);
53                 r.__test = Toggleref.STRONG;
54                 c.__test = Toggleref.WEAK;
55                 Register (r);
56                 Register (c);
57                 root = new WeakReference<Toggleref> (r, false);
58                 child = new WeakReference<Toggleref> (c, false);
59         }
60
61         static int test_0_root_keeps_child ()
62         {
63                 Console.WriteLine ("test_0_root_keeps_child");
64                 FinalizerHelpers.PerformNoPinAction (SetupLinks);
65                 
66                 GC.Collect ();
67                 GC.WaitForPendingFinalizers ();
68
69                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
70                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
71                 Console.WriteLine ("a is null {0}", a == null);
72                 Console.WriteLine ("b is null {0}", b == null);
73                 if (a == null || b == null)
74                         return 1;
75                 Console.WriteLine ("a test {0}", a.__test);
76                 Console.WriteLine ("b test {0}", b.__test);
77
78                 //now we break the link and switch b to strong
79                 a.link.Clear ();
80                 b.__test = Toggleref.STRONG;
81                 a = b = null;
82
83                 GC.Collect ();
84                 GC.WaitForPendingFinalizers ();
85
86                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
87                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
88                 Console.WriteLine ("a is null {0}", a == null);
89                 Console.WriteLine ("b is null {0}", b == null);
90                 if (a == null || b == null)
91                         return 2;
92                 Console.WriteLine ("a test {0}", a.__test);
93                 Console.WriteLine ("b test {0}", b.__test);
94
95
96                 return 0;
97         }
98
99         static void SetupLinks2 () {
100                 var r = new Toggleref () { id = "root" };
101                 var c = new Toggleref () { id = "child" };
102
103                 r.__test = Toggleref.STRONG;
104                 c.__test = Toggleref.WEAK;
105                 Register (r);
106                 Register (c);
107                 root = new WeakReference<Toggleref> (r, false);
108                 child = new WeakReference<Toggleref> (c, false);
109         }
110
111         static int test_0_child_goes_away ()
112         {
113                 Console.WriteLine ("test_0_child_goes_away");
114
115                 FinalizerHelpers.PerformNoPinAction (SetupLinks2);
116
117                 GC.Collect ();
118                 GC.WaitForPendingFinalizers ();
119
120                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
121                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
122                 Console.WriteLine ("a is null {0}", a == null);
123                 Console.WriteLine ("b is null {0}", b == null);
124                 if (a == null || b != null)
125                         return 1;
126                 Console.WriteLine ("a test {0}", a.__test);
127
128                 return 0;
129         }
130
131         static ConditionalWeakTable<Toggleref, object> cwt = new ConditionalWeakTable<Toggleref, object> ();
132         static WeakReference<object> root_value, child_value;
133         static object a_val, b_val;
134
135
136         static void SetupLinks3 () {
137                 var r = new Toggleref () { id = "root" };
138                 var c = new Toggleref () { id = "child" };
139
140                 r.__test = Toggleref.STRONG;
141                 c.__test = Toggleref.WEAK;
142                 Register (r);
143                 Register (c);
144                 root = new WeakReference<Toggleref> (r, false);
145                 child = new WeakReference<Toggleref> (c, false);
146
147                 var root_val = new object ();
148                 var child_val = new object ();
149
150                 cwt.Add (r, root_val);
151                 cwt.Add (c, child_val);
152
153                 root_value = new WeakReference<object> (root_val, false);
154                 child_value = new WeakReference<object> (child_val, false);
155         }
156
157         static int test_0_CWT_keep_child_alive ()
158         {
159                 Console.WriteLine ("test_0_CWT_keep_child_alive");
160
161                 FinalizerHelpers.PerformNoPinAction (SetupLinks3);
162
163                 GC.Collect ();
164                 GC.WaitForPendingFinalizers ();
165
166                 Console.WriteLine ("try get A {0}", root.TryGetTarget (out a));
167                 Console.WriteLine ("try get B {0}", child.TryGetTarget (out b));
168                 Console.WriteLine ("a is null {0}", a == null);
169                 Console.WriteLine ("b is null {0}", b == null);
170                 if (a == null || b != null)
171                         return 1;
172                 Console.WriteLine ("a test {0}", a.__test);
173
174                 Console.WriteLine ("try get a_val {0}", root_value.TryGetTarget (out a_val));
175                 Console.WriteLine ("try get v_val {0}", child_value.TryGetTarget (out b_val));
176
177                 //the strong toggleref must keep the CWT value to remains alive
178                 if (a_val == null)
179                         return 2;
180
181                 //the weak toggleref should allow the CWT value to go away
182                 if (b_val != null)
183                         return 3;
184
185                 object res_value = null;
186                 bool res = cwt.TryGetValue (a, out res_value);
187                 Console.WriteLine ("CWT result {0} -> {1}", res, res_value == a_val);
188
189                 //the strong val is not on the CWT
190                 if (!res)
191                         return 4;
192
193                 //for some reason the value is not the right one
194                 if (res_value != a_val)
195                         return 5;
196
197                 return 0;
198         }
199
200         static int Main (string[] args)
201         {
202                 return TestDriver.RunTests (typeof (Driver), args);
203         }
204
205 }