8000 Add temp tests reference by https://github.com/pythonnet/pythonnet/pu… · amos402/pythonnet@9d57a82 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9d57a82

Browse files
committed
Add temp tests reference by pythonnet#1074 (comment)
1 parent 183f9d8 commit 9d57a82

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

src/embed_tests/TestDomainReload.cs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics;
33
using System.Reflection;
4+
using System.Runtime.InteropServices;
45
using NUnit.Framework;
56
using Python.Runtime;
67

@@ -115,6 +116,71 @@ public static void CrossDomainObject()
115116
}
116117
}
117118

119+
120+
#region Tempary tests
121+
// https://github.com/pythonnet/pythonnet/pull/1074#issuecomment-596139665
122+
[Test]
123+
public void CrossReleaseBuiltinType()
124+
{
125+
try
126+
{
127+
var numRef = CreateNumReference();
128+
GC.Collect();
129+
GC.WaitForPendingFinalizers(); // <- this will put former `num` into Finalizer queue
130+
Finalizer.Instance.Collect(forceDispose: true);
131+
// ^- this will call PyObject.Dispose, which will call XDecref on `num.Handle`,
132+
// but Python interpreter from "run" 1 is long gone, so it will corrupt memory instead.
133+
Assert.False(numRef.IsAlive);
134+
}
135+
finally
136+
{
137+
PythonEngine.Shutdown();
138+
}
139+
}
140+
141+
[Test]
142+
public void CrossReleaseCustomType()
143+
{
144+
try
145+
{
146+
var objRef = CreateConcreateObject();
147+
GC.Collect();
148+
GC.WaitForPendingFinalizers();
149+
Finalizer.Instance.Collect(forceDispose: true);
150+
Assert.False(objRef.IsAlive);
151+
}
152+
finally
153+
{
154+
PythonEngine.Shutdown();
155+
}
156+
}
157+
158+
private static WeakReference CreateNumReference()
159+
{
160+
PythonEngine.Initialize();
161+
var num = 3216757418.ToPython();
162+
Assert.AreEqual(num.Refcount, 1);
163+
WeakReference numRef = new WeakReference(num, false);
164+
PythonEngine.Shutdown(); // <- "run" 1 ends
165+
PythonEngine.Initialize(); // <- "run" 2 starts
166+
num = null;
167+
return numRef;
168+
}
169+
170+
private static WeakReference CreateConcreateObject()
171+
{
172+
PythonEngine.Initialize();
173+
var obj = new Domain.MyClass().ToPython();
174+
Assert.AreEqual(obj.Refcount, 1);
175+
WeakReference numRef = new WeakReference(obj, false);
176+
PythonEngine.Shutdown();
177+
PythonEngine.Initialize();
178+
obj = null;
179+
return numRef;
180+
}
181+
182+
#endregion Tempary tests
183+
118184
/// <summary>
119185
/// This is a magic incantation required to run code in an application
120186
/// domain other than the current one.
@@ -305,6 +371,8 @@ from Python.EmbeddingTest.Domain import MyClass
305371
obj = MyClass()
306372
obj.Method()
307373
obj.StaticMethod()
374+
obj.Property = 1
375+
obj.Field = 10
308376
", Assembly.GetExecutingAssembly().FullName);
309377

310378
using (Py.GIL())
@@ -333,11 +401,27 @@ public static void RunTestObject(IntPtr handle)
333401
{
334402
using (Py.GIL())
335403
{
404+
IntPtr tp = Runtime.Runtime.PyObject_TYPE(handle);
405+
IntPtr tp_clear = Marshal.ReadIntPtr(tp, TypeOffset.tp_clear);
336406

337407
using (PyObject obj = new PyObject(handle))
338408
{
339409
obj.InvokeMethod("Method");
340410
obj.InvokeMethod("StaticMethod");
411+
412+
using (var scope = Py.CreateScope())
413+
{
414+
scope.Set("obj", obj);
415+
scope.Exec(@"
416+
obj.Method()
417+
obj.StaticMethod()
418+
obj.Property += 1
419+
obj.Field += 10
420+
");
421+
}
422+
var clrObj = obj.As<Domain.MyClass>();
423+
Assert.AreEqual(clrObj.Property, 2);
424+
Assert.AreEqual(clrObj.Field, 20);
341425
}
342426
}
343427
}
@@ -370,6 +454,8 @@ namespace Python.EmbeddingTest.Domain
370454
[Serializable]
371455
public class MyClass
372456
{
457+
public int Property { get; set; }
458+
public int Field;
373459
public void Method() { }
374460
public static void StaticMethod() { }
375461
}

0 commit comments

Comments
 (0)
0