2 // MemoryMappedFileTest.cs
5 // Zoltan Varga (vargaz@gmail.com)
7 // (C) 2009 Novell, Inc. (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.IO.MemoryMappedFiles;
35 using NUnit.Framework;
37 namespace MonoTests.System.IO.MemoryMappedFiles {
40 public class MemoryMappedFileTest {
42 void AssertThrows<ExType> (Action del) where ExType : Exception {
50 Assert.IsTrue (thrown);
53 static int named_index;
54 static String MkNamedMapping ()
56 return "test-" + named_index++;
60 static string tempDir = Path.Combine (Path.GetTempPath (), typeof (MemoryMappedFileTest).FullName);
65 protected void SetUp () {
66 if (Directory.Exists (tempDir))
67 Directory.Delete (tempDir, true);
69 Directory.CreateDirectory (tempDir);
71 fname = Path.Combine (tempDir, "basic.txt");
73 using (StreamWriter sw = new StreamWriter (fname)) {
74 sw.WriteLine ("Hello!");
75 sw.WriteLine ("World!");
80 protected void TearDown () {
81 if (Directory.Exists (tempDir))
82 Directory.Delete (tempDir, true);
86 public void Basic () {
87 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
89 using (var stream = file.CreateViewStream ()) {
90 TextReader r = new StreamReader (stream);
95 Assert.AreEqual ("Hello!", s);
97 Assert.AreEqual ("World!", s);
102 public void CreateNew ()
105 MemoryMappedFile.CreateNew (Path.Combine (tempDir, "createNew.test"), 8192);
109 [ExpectedException (typeof (IOException))]
110 public void CreateNew_OnExistingFile ()
113 MemoryMappedFile.CreateNew (Path.Combine (tempDir, "createNew.test"), 8192);
115 // This should fail, the file exists
116 MemoryMappedFile.CreateNew (Path.Combine (tempDir, "createNew.test"), 8192);
119 // Call this twice, it should always work
121 public void CreateOrOpen_Multiple ()
123 MemoryMappedFile.CreateOrOpen (Path.Combine (tempDir, "createOrOpen.test"), 8192);
124 MemoryMappedFile.CreateOrOpen (Path.Combine (tempDir, "createOrOpen.test"), 8192);
128 [ExpectedException(typeof(ArgumentOutOfRangeException))]
129 public void CreateFromFileWithSmallerCapacityThanFile ()
131 var f = Path.Combine (tempDir, "8192-file");
132 File.WriteAllBytes (f, new byte [8192]);
134 // We are requesting fewer bytes to map.
135 MemoryMappedFile.CreateFromFile (f, FileMode.Open, "myMap", 4192);
139 public void CreateFromFile_Null () {
140 AssertThrows<ArgumentNullException> (delegate () {
141 MemoryMappedFile.CreateFromFile (null);
146 public void CreateViewStream_Offsets () {
147 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
149 using (var stream = file.CreateViewStream (2, 3)) {
150 byte[] arr = new byte [128];
152 int len = stream.Read (arr, 0, 128);
154 Assert.AreEqual (3, len);
156 Assert.AreEqual ('l', (char)arr [0]);
157 Assert.AreEqual ('l', (char)arr [1]);
158 Assert.AreEqual ('o', (char)arr [2]);
163 public void CreateViewStream_Rights () {
164 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
166 using (var stream = file.CreateViewStream (0, 0, MemoryMappedFileAccess.Read)) {
167 AssertThrows<NotSupportedException> (delegate () {
168 stream.WriteByte (0);
172 using (var stream = file.CreateViewStream (0, 0, MemoryMappedFileAccess.Write)) {
173 AssertThrows<NotSupportedException> (delegate () {
180 public unsafe void CreateViewBasic () {
181 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
183 using (var v = file.CreateViewAccessor ()) {
187 var handle = v.SafeMemoryMappedViewHandle;
191 handle.AcquirePointer (ref b);
193 for (int i = 0; i < 5; ++i)
196 handle.ReleasePointer ();
199 Assert.AreEqual ("Hello", s);
204 public unsafe void ViewReadArray () {
205 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
207 using (var v = file.CreateViewAccessor ()) {
208 var a = new byte [5];
209 var n = v.ReadArray (0, a, 0, 5);
210 Assert.AreEqual (5, n);
211 var s = new string (Array.ConvertAll (a, b => (char)b));
212 Assert.AreEqual ("Hello", s);
217 public unsafe void ViewAccessorReadArrayWithOffset () {
218 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
220 var expected = "lo!";
222 using (var v = file.CreateViewAccessor (offset, expected.Length)) {
223 // PointerOffset Mono implementation is always 0.
224 // Assert.AreEqual (offset, v.PointerOffset);
226 var a = new byte [expected.Length];
227 var n = v.ReadArray (0, a, 0, expected.Length);
228 Assert.AreEqual (expected.Length, n);
229 var s = new string (Array.ConvertAll (a, b => (char)b));
230 Assert.AreEqual (expected, s);
235 public unsafe void ViewStreamReadWithOffset () {
236 var file = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
238 var expected = "lo!";
240 using (var v = file.CreateViewStream (offset, expected.Length)) {
241 // PointerOffset Mono implementation is always 0.
242 // Assert.AreEqual (offset, v.PointerOffset);
244 var a = new byte [expected.Length];
245 var n = v.Read (a, 0, expected.Length);
246 Assert.AreEqual (expected.Length, n);
247 var s = new string (Array.ConvertAll (a, b => (char)b));
248 Assert.AreEqual (expected, s);
253 public void NamedMappingToInvalidFile ()
255 var fileName = Path.Combine (tempDir, "temp_file_123");
256 if (File.Exists (fileName))
257 File.Delete (fileName);
258 var memoryMappedFile90 = MemoryMappedFile.CreateNew (fileName, 4194304, MemoryMappedFileAccess.ReadWrite);
259 memoryMappedFile90.CreateViewStream (4186112, 3222, MemoryMappedFileAccess.Write);
263 public void CreateTheSameAreaTwiceShouldFail ()
265 var name = MkNamedMapping ();
266 using (var m0 = MemoryMappedFile.CreateNew(name, 4096, MemoryMappedFileAccess.ReadWrite)) {
268 using (var m1 = MemoryMappedFile.CreateNew (name, 4096, MemoryMappedFileAccess.ReadWrite)) {
269 Assert.Fail ("Must fail");
271 } catch (IOException) {}
276 public void MapAFileToAMemoryAreaShouldFail ()
278 var name = MkNamedMapping ();
279 using (var m0 = MemoryMappedFile.CreateNew(name, 4096, MemoryMappedFileAccess.ReadWrite)) {
281 using (var m1 = MemoryMappedFile.CreateFromFile (fname, FileMode.OpenOrCreate, name)) {
282 Assert.Fail ("Must fail");
284 } catch (IOException) {}
289 public void NamedMappingsShareMemoryArea ()
291 var name = MkNamedMapping ();
292 using (var m0 = MemoryMappedFile.CreateNew(name, 4096, MemoryMappedFileAccess.ReadWrite)) {
293 using (var m1 = MemoryMappedFile.CreateOrOpen (name, 4096, MemoryMappedFileAccess.ReadWrite)) {
294 using (MemoryMappedViewAccessor v0 = m0.CreateViewAccessor (), v1 = m1.CreateViewAccessor ()) {
295 v0.Write (10, 0x12345);
296 Assert.AreEqual (0x12345, v1.ReadInt32 (10));
303 public void NamedFileCanBeOpen ()
305 var name = MkNamedMapping ();
306 using (var sw = new FileStream (fname, FileMode.Open)) {
307 byte[] b = new byte[20];
308 for (int i = 0; i < 20; ++i)
313 using (var m0 = MemoryMappedFile.CreateFromFile (fname, FileMode.Open, name)) {
314 using (var m1 = MemoryMappedFile.CreateOrOpen (name, 4096)) {
315 using (MemoryMappedViewAccessor v0 = m0.CreateViewAccessor (), v1 = m1.CreateViewAccessor ()) {
316 v0.Write (10, 0x11223344);
317 Assert.AreEqual (0x11223344, v1.ReadInt32 (10));
324 public void MapAtEdgeOfPage ()
326 using (var f = new FileStream (fname, FileMode.Open)) {
327 var b = new byte [4096];
328 for (int i = 0; i < 4096; ++i)
330 for (int i = 0; i < 2; ++i)
331 f.Write (b, 0, 4096);
333 var m0 = MemoryMappedFile.CreateFromFile (fname, FileMode.Open);
334 var v0 = m0.CreateViewAccessor (500, 4096);
335 var v1 = m0.CreateViewAccessor (0, 4096 * 2);
336 for (int i = 0; i < 4096; ++i) {
337 Assert.AreEqual (0xAA, v1.ReadByte (i + 500));
338 v0.Write (i, (byte)0xFF);
339 Assert.AreEqual (0xFF, v1.ReadByte (i + 500));
344 public void DoubleAccountingInOffsetCalculation ()
346 var memoryMappedFile90 = MemoryMappedFile.CreateNew (MkNamedMapping (), 4194304, MemoryMappedFileAccess.ReadWrite);
347 var stream = memoryMappedFile90.CreateViewStream (4186112, 3222, MemoryMappedFileAccess.Write);
348 using (var tw = new StreamWriter(stream))
350 tw.WriteLine ("Hello World!");
355 [ExpectedException(typeof(IOException))]
356 public void CreateViewStreamWithOffsetPastFileEnd ()
358 string f = Path.Combine (tempDir, "8192-file");
359 File.WriteAllBytes (f, new byte [8192]);
361 MemoryMappedFile mappedFile = MemoryMappedFile.CreateFromFile (f, FileMode.Open, "myMap", 8192);
363 /* Should throw exception when trying to map past end of file */
364 MemoryMappedViewStream stream = mappedFile.CreateViewStream (8200, 10, MemoryMappedFileAccess.ReadWrite);
368 [ExpectedException(typeof(IOException))]
369 public void CreateViewStreamWithOffsetPastFileEnd2 ()
371 string f = Path.Combine (tempDir, "8192-file");
372 File.WriteAllBytes (f, new byte [8192]);
374 MemoryMappedFile mappedFile = MemoryMappedFile.CreateFromFile (f, FileMode.Open);
376 MemoryMappedViewStream stream = mappedFile.CreateViewStream (8191, 8191, MemoryMappedFileAccess.ReadWrite);
380 public void CreateViewStreamAlignToPageSize ()
383 // iOS bugs on ARM64 - bnc #27667 - apple #
384 int pageSize = (IntPtr.Size == 4) ? Environment.SystemPageSize : 4096;
386 int pageSize = Environment.SystemPageSize;
388 string f = Path.Combine (tempDir, "p-file");
389 File.WriteAllBytes (f, new byte [pageSize * 2 + 1]);
391 MemoryMappedFile mappedFile = MemoryMappedFile.CreateFromFile (f, FileMode.Open);
393 MemoryMappedViewStream stream = mappedFile.CreateViewStream (pageSize * 2, 0, MemoryMappedFileAccess.ReadWrite);
395 Assert.AreEqual (stream.Capacity, Environment.SystemPageSize);
397 stream.Write (new byte [pageSize], 0, pageSize);
400 [Test] // #30741 #30825
401 public void CreateFromFileNullMapName ()
404 string f = Path.Combine (tempDir, "null-map-name-file");
405 File.WriteAllBytes (f, new byte [size]);
407 FileStream file = File.OpenRead (f);
408 MemoryMappedFile.CreateFromFile (file, null, size, MemoryMappedFileAccess.ReadExecute, null, 0, false);