Skip to content

Commit b67e2d7

Browse files
Replace try-finally cleanup with IDisposable temp directories
Use xUnit's IDisposable pattern for test cleanup instead of manual try-finally blocks. Each nested test class that generates temp files now creates a per-instance temp directory in a field initializer and cleans it up in Dispose(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e21942b commit b67e2d7

File tree

3 files changed

+131
-143
lines changed

3 files changed

+131
-143
lines changed

tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/FixtureTestBase.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,16 @@ protected static JavaPeerInfo FindFixtureByJavaName (string javaName)
3333
return peer;
3434
}
3535

36-
protected static void CleanUpDir (string path)
36+
protected static string CreateTempDir ()
3737
{
38-
var dir = Path.GetDirectoryName (path);
39-
if (dir != null && Directory.Exists (dir))
38+
var dir = Path.Combine (Path.GetTempPath (), $"typemap-test-{Guid.NewGuid ():N}");
39+
Directory.CreateDirectory (dir);
40+
return dir;
41+
}
42+
43+
protected static void DeleteTempDir (string dir)
44+
{
45+
if (Directory.Exists (dir))
4046
try { Directory.Delete (dir, true); } catch { }
4147
}
4248

tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/JcwJavaSourceGeneratorTests.cs

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,20 @@ public void JniTypeToJava_ConvertsCorrectly (string jniType, string expected)
6262

6363
}
6464

65-
public class Filtering
65+
public class Filtering : IDisposable
6666
{
67+
readonly string _outputDir = CreateTempDir ();
68+
public void Dispose () => DeleteTempDir (_outputDir);
6769

6870
[Fact]
6971
public void Generate_SkipsMcwTypes ()
7072
{
7173
var peers = ScanFixtures ();
7274
var generator = new JcwJavaSourceGenerator ();
73-
var outputDir = Path.Combine (Path.GetTempPath (), $"jcw-test-{Guid.NewGuid ():N}");
74-
try {
75-
var files = generator.Generate (peers, outputDir);
76-
Assert.DoesNotContain (files, f => f.EndsWith ("java/lang/Object.java"));
77-
Assert.DoesNotContain (files, f => f.EndsWith ("android/app/Activity.java"));
78-
Assert.Contains (files, f => f.Replace ('\\', '/').Contains ("my/app/MainActivity.java"));
79-
} finally {
80-
if (Directory.Exists (outputDir)) {
81-
Directory.Delete (outputDir, true);
82-
}
83-
}
75+
var files = generator.Generate (peers, _outputDir);
76+
Assert.DoesNotContain (files, f => f.EndsWith ("java/lang/Object.java"));
77+
Assert.DoesNotContain (files, f => f.EndsWith ("android/app/Activity.java"));
78+
Assert.Contains (files, f => f.Replace ('\\', '/').Contains ("my/app/MainActivity.java"));
8479
}
8580

8681
}
@@ -247,28 +242,23 @@ public void Generate_NestedType_HasCorrectPackageAndClassName ()
247242

248243
}
249244

250-
public class OutputFilePath
245+
public class OutputFilePath : IDisposable
251246
{
247+
readonly string _outputDir = CreateTempDir ();
248+
public void Dispose () => DeleteTempDir (_outputDir);
252249

253250
[Fact]
254251
public void Generate_CreatesCorrectFileStructure ()
255252
{
256253
var peers = ScanFixtures ();
257254
var generator = new JcwJavaSourceGenerator ();
258-
var outputDir = Path.Combine (Path.GetTempPath (), $"jcw-test-{Guid.NewGuid ():N}");
259-
try {
260-
var files = generator.Generate (peers, outputDir);
261-
Assert.NotEmpty (files);
262-
263-
foreach (var file in files) {
264-
Assert.StartsWith (outputDir, file);
265-
Assert.True (File.Exists (file), $"Generated file should exist: {file}");
266-
Assert.EndsWith (".java", file);
267-
}
268-
} finally {
269-
if (Directory.Exists (outputDir)) {
270-
Directory.Delete (outputDir, true);
271-
}
255+
var files = generator.Generate (peers, _outputDir);
256+
Assert.NotEmpty (files);
257+
258+
foreach (var file in files) {
259+
Assert.StartsWith (_outputDir, file);
260+
Assert.True (File.Exists (file), $"Generated file should exist: {file}");
261+
Assert.EndsWith (".java", file);
272262
}
273263
}
274264

@@ -287,8 +277,7 @@ public void Generate_InvalidJniName_Throws (string badJniName)
287277
{
288278
var peer = MakeAcwPeer (badJniName, "Test.Bad", "TestApp");
289279
var generator = new JcwJavaSourceGenerator ();
290-
var outputDir = Path.Combine (Path.GetTempPath (), $"jcw-test-{Guid.NewGuid ():N}");
291-
Assert.Throws<ArgumentException> (() => generator.Generate (new [] { peer }, outputDir));
280+
Assert.Throws<ArgumentException> (() => generator.Generate (new [] { peer }, _outputDir));
292281
}
293282

294283
[Theory]
@@ -301,14 +290,7 @@ public void Generate_ValidJniName_DoesNotThrow (string validJniName)
301290
{
302291
var peer = MakeAcwPeer (validJniName, "Test.Valid", "TestApp");
303292
var generator = new JcwJavaSourceGenerator ();
304-
var outputDir = Path.Combine (Path.GetTempPath (), $"jcw-test-{Guid.NewGuid ():N}");
305-
try {
306-
generator.Generate (new [] { peer }, outputDir);
307-
} finally {
308-
if (Directory.Exists (outputDir)) {
309-
Directory.Delete (outputDir, true);
310-
}
311-
}
293+
generator.Generate (new [] { peer }, _outputDir);
312294
}
313295

314296
}

tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TypeMapAssemblyGeneratorTests.cs

Lines changed: 103 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -127,59 +127,59 @@ public void Generate_ProxyType_HasCtorAndCreateInstance ()
127127

128128
}
129129

130-
public class AcwProxy : IDisposable
131-
{
132-
readonly string _outputDir = CreateTempDir ();
133-
public void Dispose () => DeleteTempDir (_outputDir);
130+
public class AcwProxy : IDisposable
131+
{
132+
readonly string _outputDir = CreateTempDir ();
133+
public void Dispose () => DeleteTempDir (_outputDir);
134134

135-
[Fact]
136-
public void Generate_AcwProxy_HasRegisterNativesAndUcoMethods ()
137-
{
138-
var peers = ScanFixtures ();
139-
var acwPeer = peers.First (p => p.JavaName == "my/app/TouchHandler");
140-
var path = GenerateAssembly (new [] { acwPeer }, _outputDir, "AcwTest");
141-
var (pe, reader) = OpenAssembly (path);
142-
using (pe) {
143-
var proxy = reader.TypeDefinitions
144-
.Select (h => reader.GetTypeDefinition (h))
145-
.First (t => reader.GetString (t.Name) == "MyApp_TouchHandler_Proxy");
146-
147-
var methods = proxy.GetMethods ()
148-
.Select (h => reader.GetMethodDefinition (h))
149-
.Select (m => reader.GetString (m.Name))
150-
.ToList ();
151-
152-
Assert.Contains ("RegisterNatives", methods);
153-
Assert.Contains (methods, m => m.StartsWith ("n_") && m.EndsWith ("_uco_0"));
154-
}
155-
}
156-
157-
[Fact]
158-
public void Generate_AcwProxy_HasUnmanagedCallersOnlyAttribute ()
159-
{
160-
var peers = ScanFixtures ();
161-
var acwPeer = peers.First (p => p.JavaName == "my/app/TouchHandler");
162-
var path = GenerateAssembly (new [] { acwPeer }, _outputDir, "UcoTest");
163-
var (pe, reader) = OpenAssembly (path);
164-
using (pe) {
165-
var proxy = reader.TypeDefinitions
166-
.Select (h => reader.GetTypeDefinition (h))
167-
.First (t => reader.GetString (t.Name) == "MyApp_TouchHandler_Proxy");
168-
169-
var ucoMethod = proxy.GetMethods ()
170-
.Select (h => reader.GetMethodDefinition (h))
171-
.First (m => reader.GetString (m.Name).Contains ("_uco_"));
172-
173-
var attrs = ucoMethod.GetCustomAttributes ()
174-
.Select (h => reader.GetCustomAttribute (h))
175-
.ToList ();
176-
Assert.NotEmpty (attrs);
177-
}
178-
}
179-
180-
}
181-
182-
public class IgnoresAccessChecksTo : IDisposable
135+
[Fact]
136+
public void Generate_AcwProxy_HasRegisterNativesAndUcoMethods ()
137+
{
138+
var peers = ScanFixtures ();
139+
var acwPeer = peers.First (p => p.JavaName == "my/app/TouchHandler");
140+
var path = GenerateAssembly (new [] { acwPeer }, _outputDir, "AcwTest");
141+
var (pe, reader) = OpenAssembly (path);
142+
using (pe) {
143+
var proxy = reader.TypeDefinitions
144+
.Select (h => reader.GetTypeDefinition (h))
145+
.First (t => reader.GetString (t.Name) == "MyApp_TouchHandler_Proxy");
146+
147+
var methods = proxy.GetMethods ()
148+
.Select (h => reader.GetMethodDefinition (h))
149+
.Select (m => reader.GetString (m.Name))
150+
.ToList ();
151+
152+
Assert.Contains ("RegisterNatives", methods);
153+
Assert.Contains (methods, m => m.StartsWith ("n_") && m.EndsWith ("_uco_0"));
154+
}
155+
}
156+
157+
[Fact]
158+
public void Generate_AcwProxy_HasUnmanagedCallersOnlyAttribute ()
159+
{
160+
var peers = ScanFixtures ();
161+
var acwPeer = peers.First (p => p.JavaName == "my/app/TouchHandler");
162+
var path = GenerateAssembly (new [] { acwPeer }, _outputDir, "UcoTest");
163+
var (pe, reader) = OpenAssembly (path);
164+
using (pe) {
165+
var proxy = reader.TypeDefinitions
166+
.Select (h => reader.GetTypeDefinition (h))
167+
.First (t => reader.GetString (t.Name) == "MyApp_TouchHandler_Proxy");
168+
169+
var ucoMethod = proxy.GetMethods ()
170+
.Select (h => reader.GetMethodDefinition (h))
171+
.First (m => reader.GetString (m.Name).Contains ("_uco_"));
172+
173+
var attrs = ucoMethod.GetCustomAttributes ()
174+
.Select (h => reader.GetCustomAttribute (h))
175+
.ToList ();
176+
Assert.NotEmpty (attrs);
177+
}
178+
}
179+
180+
}
181+
182+
public class IgnoresAccessChecksTo : IDisposable
183183
{
184184
readonly string _outputDir = CreateTempDir ();
185185
public void Dispose () => DeleteTempDir (_outputDir);
@@ -280,63 +280,63 @@ public void Generate_EmptyPeerList_ProducesValidAssembly ()
280280

281281
}
282282

283-
public class JniSignatureHelperTests
284-
{
283+
public class JniSignatureHelperTests
284+
{
285285

286-
[Theory]
287-
[InlineData ("()V", 0)]
288-
[InlineData ("(I)V", 1)]
289-
[InlineData ("(Landroid/os/Bundle;)V", 1)]
290-
[InlineData ("(IFJ)V", 3)]
291-
[InlineData ("(ZLandroid/view/View;I)Z", 3)]
292-
[InlineData ("([Ljava/lang/String;)V", 1)]
293-
public void ParseParameterTypes_ParsesCorrectCount (string signature, int expectedCount)
294-
{
295-
var actual = JniSignatureHelper.ParseParameterTypes (signature);
296-
Assert.Equal (expectedCount, actual.Count);
297-
}
298-
299-
[Theory]
300-
[InlineData ("(Z)V", JniParamKind.Boolean)]
301-
[InlineData ("(Ljava/lang/String;)V", JniParamKind.Object)]
302-
public void ParseParameterTypes_SingleParam_MapsToCorrectKind (string signature, JniParamKind expectedKind)
303-
{
304-
var types = JniSignatureHelper.ParseParameterTypes (signature);
305-
Assert.Single (types);
306-
Assert.Equal (expectedKind, types [0]);
307-
}
308-
309-
[Theory]
310-
[InlineData ("()V", JniParamKind.Void)]
311-
[InlineData ("()I", JniParamKind.Int)]
312-
[InlineData ("()Z", JniParamKind.Boolean)]
313-
[InlineData ("()Ljava/lang/String;", JniParamKind.Object)]
314-
public void ParseReturnType_MapsToCorrectKind (string signature, JniParamKind expectedKind)
315-
{
316-
Assert.Equal (expectedKind, JniSignatureHelper.ParseReturnType (signature));
317-
}
286+
[Theory]
287+
[InlineData ("()V", 0)]
288+
[InlineData ("(I)V", 1)]
289+
[InlineData ("(Landroid/os/Bundle;)V", 1)]
290+
[InlineData ("(IFJ)V", 3)]
291+
[InlineData ("(ZLandroid/view/View;I)Z", 3)]
292+
[InlineData ("([Ljava/lang/String;)V", 1)]
293+
public void ParseParameterTypes_ParsesCorrectCount (string signature, int expectedCount)
294+
{
295+
var actual = JniSignatureHelper.ParseParameterTypes (signature);
296+
Assert.Equal (expectedCount, actual.Count);
297+
}
318298

319-
}
299+
[Theory]
300+
[InlineData ("(Z)V", JniParamKind.Boolean)]
301+
[InlineData ("(Ljava/lang/String;)V", JniParamKind.Object)]
302+
public void ParseParameterTypes_SingleParam_MapsToCorrectKind (string signature, JniParamKind expectedKind)
303+
{
304+
var types = JniSignatureHelper.ParseParameterTypes (signature);
305+
Assert.Single (types);
306+
Assert.Equal (expectedKind, types [0]);
307+
}
320308

321-
public class NegativeEdgeCase
322-
{
309+
[Theory]
310+
[InlineData ("()V", JniParamKind.Void)]
311+
[InlineData ("()I", JniParamKind.Int)]
312+
[InlineData ("()Z", JniParamKind.Boolean)]
313+
[InlineData ("()Ljava/lang/String;", JniParamKind.Object)]
314+
public void ParseReturnType_MapsToCorrectKind (string signature, JniParamKind expectedKind)
315+
{
316+
Assert.Equal (expectedKind, JniSignatureHelper.ParseReturnType (signature));
317+
}
323318

324-
[Theory]
325-
[InlineData ("")]
326-
[InlineData ("not-a-sig")]
327-
[InlineData ("(")]
328-
public void ParseParameterTypes_InvalidSignature_ThrowsOrReturnsEmpty (string signature)
329-
{
330-
try {
331-
var result = JniSignatureHelper.ParseParameterTypes (signature);
332-
Assert.NotNull (result);
333-
} catch (Exception ex) when (ex is ArgumentException || ex is IndexOutOfRangeException || ex is FormatException) {
334-
}
335-
}
319+
}
336320

337-
}
321+
public class NegativeEdgeCase
322+
{
323+
324+
[Theory]
325+
[InlineData ("")]
326+
[InlineData ("not-a-sig")]
327+
[InlineData ("(")]
328+
public void ParseParameterTypes_InvalidSignature_ThrowsOrReturnsEmpty (string signature)
329+
{
330+
try {
331+
var result = JniSignatureHelper.ParseParameterTypes (signature);
332+
Assert.NotNull (result);
333+
} catch (Exception ex) when (ex is ArgumentException || ex is IndexOutOfRangeException || ex is FormatException) {
334+
}
335+
}
336+
337+
}
338338

339-
public class CreateInstancePaths : IDisposable
339+
public class CreateInstancePaths : IDisposable
340340
{
341341
readonly string _outputDir = CreateTempDir ();
342342
public void Dispose () => DeleteTempDir (_outputDir);

0 commit comments

Comments
 (0)