Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit fc96be9

Browse files
committed
Merge pull request #2334 from stephentoub/mmf_tests
Rewrite MemoryMappedFiles tests
2 parents 43a1fc3 + e51fd7e commit fc96be9

File tree

56 files changed

+3273
-9961
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3273
-9961
lines changed

src/Common/src/Interop/Interop.PlatformDetection.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ internal enum OperatingSystem
1313
{
1414
Windows,
1515
Linux,
16-
OSX
16+
OSX,
17+
FreeBSD
1718
}
1819

1920
internal static bool IsWindows
@@ -31,6 +32,11 @@ internal static bool IsOSX
3132
get { return OperatingSystem.OSX == PlatformDetection.OperatingSystem; }
3233
}
3334

35+
internal static bool IsFreeBSD
36+
{
37+
get { return OperatingSystem.FreeBSD == PlatformDetection.OperatingSystem; }
38+
}
39+
3440
internal static class PlatformDetection
3541
{
3642
internal static OperatingSystem OperatingSystem { get { return s_os.Value; } }
@@ -48,6 +54,8 @@ internal static class PlatformDetection
4854
{
4955
case "Darwin":
5056
return OperatingSystem.OSX;
57+
case "FreeBSD":
58+
return OperatingSystem.FreeBSD;
5159
default:
5260
return OperatingSystem.Linux;
5361
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Runtime.CompilerServices;
5+
6+
namespace System.IO
7+
{
8+
/// <summary>Base class for test classes the use temporary files that need to be cleaned up.</summary>
9+
public abstract class TemporaryFilesCleanupTestBase : IDisposable
10+
{
11+
/// <summary>Initialize the test class base.</summary>
12+
protected TemporaryFilesCleanupTestBase()
13+
{
14+
// Use a unique test directory per test class
15+
TestDirectory = Path.Combine(Path.GetTempPath(), GetType().Name + "_" + Guid.NewGuid().ToString("N"));
16+
try
17+
{
18+
Directory.CreateDirectory(TestDirectory);
19+
}
20+
catch
21+
{
22+
// Don't throw exceptions during test class construction. Attempts to use paths
23+
// under this directory will instead appropriately fail later.
24+
}
25+
}
26+
27+
~TemporaryFilesCleanupTestBase()
28+
{
29+
Dispose(false);
30+
}
31+
32+
public void Dispose()
33+
{
34+
Dispose(true);
35+
GC.SuppressFinalize(this);
36+
}
37+
38+
protected void Dispose(bool disposing)
39+
{
40+
// No managed resources to clean up.
41+
42+
try { Directory.Delete(TestDirectory, recursive: true); }
43+
catch { } // avoid exceptions from Dispose
44+
}
45+
46+
/// <summary>Gets the test directory into which all files and directories created by tests should be stored.</summary>
47+
protected string TestDirectory { get; private set; }
48+
49+
/// <summary>Generates a test file full path that is unique to the call site.</summary>
50+
protected string GetTestFilePath([CallerMemberName]string fileName = null, [CallerLineNumber] int lineNumber = 0)
51+
{
52+
return Path.Combine(TestDirectory, GetTestFileName(fileName, lineNumber));
53+
}
54+
55+
/// <summary>Generates a test file name that is unique to the call site.</summary>
56+
protected string GetTestFileName([CallerMemberName]string fileName = null, [CallerLineNumber] int lineNumber = 0)
57+
{
58+
return string.Format("{0}_{1}", fileName ?? "TestBase", lineNumber);
59+
}
60+
}
61+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace System.IO
5+
{
6+
/// <summary>
7+
/// Represents a temporary file. Creating an instance creates a file at the specified path,
8+
/// and disposing the instance deletes the file.
9+
/// </summary>
10+
public sealed class TempFile : IDisposable
11+
{
12+
/// <summary>Gets the created file's path.</summary>
13+
public string Path { get; private set; }
14+
15+
public TempFile(string path, long length = 0)
16+
{
17+
Path = path;
18+
using (FileStream fs = File.Create(path))
19+
{
20+
if (length > 0)
21+
{
22+
// Fill with zeros up to the desired length.
23+
fs.Write(new byte[length], 0, (int)length);
24+
}
25+
}
26+
}
27+
28+
~TempFile() { DeleteFile(); }
29+
30+
public void Dispose()
31+
{
32+
GC.SuppressFinalize(this);
33+
DeleteFile();
34+
}
35+
36+
private void DeleteFile()
37+
{
38+
try { File.Delete(Path); }
39+
catch { /* Ignore exceptions on disposal paths */ }
40+
}
41+
}
42+
}

src/System.IO.MemoryMappedFiles/System.IO.MemoryMappedFiles.sln

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@ VisualStudioVersion = 12.0.30723.0
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.MemoryMappedFiles", "src\System.IO.MemoryMappedFiles.csproj", "{16EE5522-F387-4C9E-9EF2-B5134B043F37}"
77
EndProject
8-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{10E9121A-7350-4AB7-BB05-A543BE1EB19B}"
9-
EndProject
10-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.MemoryMappedFiles.Tests", "tests\MemoryMappedFile\System.IO.MemoryMappedFiles.Tests.csproj", "{9D6F6254-B5A3-40FF-8925-68AA8D1CE933}"
11-
EndProject
12-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.MemoryMappedViewAccessor.Tests", "tests\MemoryMappedViewAccessor\System.IO.MemoryMappedViewAccessor.Tests.csproj", "{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}"
13-
EndProject
14-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.MemoryMappedViewStream.Tests", "tests\MemoryMappedViewStream\System.IO.MemoryMappedViewStream.Tests.csproj", "{688496E1-A7B3-41AE-9E32-C6F1A1127F91}"
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.MemoryMappedFiles.Tests", "tests\System.IO.MemoryMappedFiles.Tests.csproj", "{9D6F6254-B5A3-40FF-8925-68AA8D1CE933}"
159
EndProject
1610
Global
1711
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -47,30 +41,6 @@ Global
4741
{9D6F6254-B5A3-40FF-8925-68AA8D1CE933}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
4842
{9D6F6254-B5A3-40FF-8925-68AA8D1CE933}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
4943
{9D6F6254-B5A3-40FF-8925-68AA8D1CE933}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
50-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Linux_Debug|Any CPU.ActiveCfg = Debug|Any CPU
51-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Linux_Debug|Any CPU.Build.0 = Debug|Any CPU
52-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Linux_Release|Any CPU.ActiveCfg = Release|Any CPU
53-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Linux_Release|Any CPU.Build.0 = Release|Any CPU
54-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.OSX_Debug|Any CPU.ActiveCfg = Debug|Any CPU
55-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.OSX_Debug|Any CPU.Build.0 = Debug|Any CPU
56-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.OSX_Release|Any CPU.ActiveCfg = Release|Any CPU
57-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.OSX_Release|Any CPU.Build.0 = Release|Any CPU
58-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
59-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
60-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
61-
{F26FBD53-C04A-4FFC-90C9-AA804285A7AD}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
62-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Linux_Debug|Any CPU.ActiveCfg = Debug|Any CPU
63-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Linux_Debug|Any CPU.Build.0 = Debug|Any CPU
64-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Linux_Release|Any CPU.ActiveCfg = Release|Any CPU
65-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Linux_Release|Any CPU.Build.0 = Release|Any CPU
66-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.OSX_Debug|Any CPU.ActiveCfg = Debug|Any CPU
67-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.OSX_Debug|Any CPU.Build.0 = Debug|Any CPU
68-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.OSX_Release|Any CPU.ActiveCfg = Release|Any CPU
69-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.OSX_Release|Any CPU.Build.0 = Release|Any CPU
70-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Windows_Debug|Any CPU.ActiveCfg = Debug|Any CPU
71-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Windows_Debug|Any CPU.Build.0 = Debug|Any CPU
72-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Windows_Release|Any CPU.ActiveCfg = Release|Any CPU
73-
{688496E1-A7B3-41AE-9E32-C6F1A1127F91}.Windows_Release|Any CPU.Build.0 = Release|Any CPU
7444
EndGlobalSection
7545
GlobalSection(SolutionProperties) = preSolution
7646
HideSolutionNode = FALSE

src/System.IO.MemoryMappedFiles/src/Microsoft/Win32/SafeMemoryMappedFileHandle.Windows.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@ internal SafeMemoryMappedFileHandle()
1414
{
1515
}
1616

17-
internal SafeMemoryMappedFileHandle(IntPtr handle, bool ownsHandle)
18-
: base(IntPtr.Zero, ownsHandle)
19-
{
20-
SetHandle(handle);
21-
}
22-
2317
protected override bool ReleaseHandle()
2418
{
2519
return Interop.mincore.CloseHandle(handle);

src/System.IO.MemoryMappedFiles/src/Microsoft/Win32/SafeMemoryMappedViewHandle.Unix.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ namespace Microsoft.Win32.SafeHandles
77
{
88
public sealed partial class SafeMemoryMappedViewHandle
99
{
10+
internal SafeMemoryMappedViewHandle(IntPtr handle, bool ownsHandle)
11+
: base(ownsHandle)
12+
{
13+
base.SetHandle(handle);
14+
}
15+
1016
protected override bool ReleaseHandle()
1117
{
1218
IntPtr addr = handle;

src/System.IO.MemoryMappedFiles/src/Microsoft/Win32/SafeMemoryMappedViewHandle.Windows.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,9 @@ public sealed partial class SafeMemoryMappedViewHandle
1010
{
1111
protected override bool ReleaseHandle()
1212
{
13-
if (Interop.mincore.UnmapViewOfFile(handle) != 0)
14-
{
15-
handle = IntPtr.Zero;
16-
return true;
17-
}
18-
return false;
13+
IntPtr h = handle;
14+
handle = IntPtr.Zero;
15+
return Interop.mincore.UnmapViewOfFile(h) != 0;
1916
}
2017
}
2118
}

src/System.IO.MemoryMappedFiles/src/Microsoft/Win32/SafeMemoryMappedViewHandle.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,5 @@ internal SafeMemoryMappedViewHandle()
1616
: base(true)
1717
{
1818
}
19-
20-
internal SafeMemoryMappedViewHandle(IntPtr handle, bool ownsHandle)
21-
: base(ownsHandle)
22-
{
23-
base.SetHandle(handle);
24-
}
2519
}
2620
}

src/System.IO.MemoryMappedFiles/src/Resources/Strings.resx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,12 @@
132132
<data name="IO_FileExists_Name" xml:space="preserve">
133133
<value>The file '{0}' already exists.</value>
134134
</data>
135-
<data name="IO_NoPermissionToDirectoryName" xml:space="preserve">
136-
<value>&lt;Path discovery permission to the specified directory was denied.&gt;</value>
137-
</data>
138135
<data name="IO_SharingViolation_File" xml:space="preserve">
139136
<value>The process cannot access the file '{0}' because it is being used by another process.</value>
140137
</data>
141138
<data name="IO_SharingViolation_NoFileName" xml:space="preserve">
142139
<value>The process cannot access the file because it is being used by another process.</value>
143140
</data>
144-
<data name="IO_DriveNotFound_Drive" xml:space="preserve">
145-
<value>Could not find the drive '{0}'. The drive might not be ready or might not be mapped.</value>
146-
</data>
147141
<data name="IO_PathNotFound_Path" xml:space="preserve">
148142
<value>Could not find a part of the path '{0}'.</value>
149143
</data>
@@ -204,9 +198,6 @@
204198
<data name="InvalidOperation_CantCreateFileMapping" xml:space="preserve">
205199
<value>Cannot create file mapping.</value>
206200
</data>
207-
<data name="InvalidOperation_ViewIsNull" xml:space="preserve">
208-
<value>The underlying MemoryMappedView object is null.</value>
209-
</data>
210201
<data name="NotSupported_MMViewStreamsFixedLength" xml:space="preserve">
211202
<value>MemoryMappedViewStreams are fixed length.</value>
212203
</data>
@@ -222,9 +213,6 @@
222213
<data name="ObjectDisposed_StreamIsClosed" xml:space="preserve">
223214
<value>Cannot access a closed Stream.</value>
224215
</data>
225-
<data name="UnknownError_Num" xml:space="preserve">
226-
<value>Unknown error '{0}'.</value>
227-
</data>
228216
<data name="PlatformNotSupported_NamedMaps" xml:space="preserve">
229217
<value>Named maps are not supported.</value>
230218
</data>

src/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.BackingObject_File.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,16 @@ private static FileStream CreateSharedBackingObject(Interop.libc.MemoryMappedPro
2020
// Then enlarge it to the requested capacity.
2121
const int DefaultBufferSize = 0x1000;
2222
var fs = new FileStream(path, FileMode.CreateNew, TranslateProtectionsToFileAccess(protections), FileShare.ReadWrite, DefaultBufferSize);
23-
Interop.CheckIo(Interop.libc.unlink(path));
24-
fs.SetLength(capacity);
23+
try
24+
{
25+
Interop.CheckIo(Interop.libc.unlink(path));
26+
fs.SetLength(capacity);
27+
}
28+
catch
29+
{
30+
fs.Dispose();
31+
throw;
32+
}
2533
return fs;
2634
}
2735

0 commit comments

Comments
 (0)