Skip to content

Commit ba0a61f

Browse files
authored
Add test for marshal methods hang (#9352)
Context: #9343 Context: #8253 (comment) Test is based on the original repro from https://github.com/filipnavara/mm-deadlock-repro/
1 parent 0fa951b commit ba0a61f

File tree

2 files changed

+115
-5
lines changed

2 files changed

+115
-5
lines changed

tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ public void Teardown ()
3030
[Test]
3131
public void NativeAssemblyCacheWithSatelliteAssemblies ([Values (true, false)] bool enableMarshalMethods)
3232
{
33-
// TODO: enable when marshal methods are fixed
34-
if (enableMarshalMethods) {
35-
Assert.Ignore ("Test is skipped when marshal methods are enabled, pending fixes to MM for .NET9");
36-
}
37-
3833
var path = Path.Combine ("temp", TestName);
3934
var lib = new XamarinAndroidLibraryProject {
4035
ProjectName = "Localization",
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System;
2+
using NUnit.Framework;
3+
using Xamarin.ProjectTools;
4+
using System.IO;
5+
using System.Linq;
6+
using Microsoft.Build.Framework;
7+
using System.Text;
8+
using System.Xml.Linq;
9+
using System.Collections.Generic;
10+
11+
namespace Xamarin.Android.Build.Tests;
12+
13+
[TestFixture]
14+
[Category ("UsesDevice")]
15+
[Category ("MayHang")]
16+
public class MarshalMethodsGCHangTests : DeviceTest
17+
{
18+
static readonly string MarshalMethodsAppRuns_PermissionManifest = @"<?xml version=""1.0"" encoding=""utf-8""?>
19+
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{0}"">
20+
<uses-sdk />
21+
<application android:label=""{0}"">
22+
</application>
23+
<uses-permission android:name=""android.permission.INTERNET"" />
24+
</manifest>";
25+
26+
static readonly string MarshalMethodsAppRuns_MainActivity = @"using Android.Media;
27+
28+
namespace marshal2;
29+
30+
[Activity (Label = ""@string/app_name"", MainLauncher = true)]
31+
public class MainActivity : Activity
32+
{
33+
protected override void OnCreate (Bundle? savedInstanceState)
34+
{
35+
base.OnCreate (savedInstanceState);
36+
SetContentView (Resource.Layout.Main);
37+
}
38+
39+
protected override void OnStart ()
40+
{
41+
base.OnStart ();
42+
43+
try {
44+
var mp = new MediaPlayer ();
45+
mp.SetDataSource (new StreamMediaDataSource (new MemoryStream (new byte[65536])));
46+
mp.Prepare ();
47+
} catch (Java.IO.IOException) {
48+
GC.Collect ();
49+
}
50+
}
51+
52+
class StreamMediaDataSource (System.IO.Stream data) : MediaDataSource
53+
{
54+
public override long Size => data.Length;
55+
56+
public override int ReadAt (long position, byte[]? buffer, int offset, int size)
57+
{
58+
try {
59+
Console.WriteLine ($""XXX:START StreamMediaDataSource.ReadAt {position} {buffer} {buffer?.Length ?? 0} {offset} {size}"");
60+
61+
// Allocate enough to trigger GC
62+
for (int i = 0; i < 1000; i++) {
63+
_ = new byte[8192];
64+
}
65+
66+
if (data.CanSeek) {
67+
data.Seek (position, SeekOrigin.Begin);
68+
}
69+
return data.Read (buffer ?? [], offset, size);
70+
} finally {
71+
Console.WriteLine ($""XXX:END //StreamMediaDataSource.ReadAt {position} {buffer} {buffer?.Length ?? 0} {offset} {size}"");
72+
}
73+
}
74+
75+
public override void Close ()
76+
{
77+
data.Dispose ();
78+
data = System.IO.Stream.Null;
79+
}
80+
}
81+
}
82+
";
83+
84+
// All Tests here require the emulator to be started with -writable-system
85+
[Test]
86+
public void MarshalMethodsAppRuns ()
87+
{
88+
var proj = new XamarinAndroidApplicationProject (packageName: "marshal2") {
89+
IsRelease = true,
90+
EnableMarshalMethods = true,
91+
TargetFramework = "net9.0-android",
92+
SupportedOSPlatformVersion = "23",
93+
TrimModeRelease = TrimMode.Full,
94+
ProjectName = "marshal2",
95+
};
96+
97+
proj.SetAndroidSupportedAbis (DeviceAbi);
98+
proj.AndroidManifest = String.Format (MarshalMethodsAppRuns_PermissionManifest, proj.PackageName);
99+
proj.MainActivity = MarshalMethodsAppRuns_MainActivity;
100+
proj.SetDefaultTargetDevice ();
101+
102+
using var apkBuilder = CreateApkBuilder (Path.Combine ("temp", TestName));
103+
Assert.True (apkBuilder.Install (proj), "Project should have installed.");
104+
RunProjectAndAssert (proj, apkBuilder);
105+
106+
const string expectedLogcatOutput = "XXX:END //StreamMediaDataSource.ReadAt";
107+
Assert.IsTrue (
108+
MonitorAdbLogcat (
109+
InstallAndRunTests.CreateLineChecker (expectedLogcatOutput),
110+
logcatFilePath: Path.Combine (Root, apkBuilder.ProjectDirectory, "startup-logcat.log"), timeout: 60
111+
),
112+
$"Output did not contain {expectedLogcatOutput}!"
113+
);
114+
}
115+
}

0 commit comments

Comments
 (0)