Exemple #1
0
        public async Task WritesBytesFromGivenBufferToGivenFileAtGivenOffsetAsync()
        {
            const int fileSize = 4_001;
            string    filePath = GetTestFilePath();

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous))
            {
                int total   = 0;
                int current = 0;

                while (total != fileSize)
                {
                    Memory <byte> buffer = content.AsMemory(total, Math.Min(content.Length - total, fileSize / 4));

                    current = await RandomAccess.WriteAsync(handle, buffer, fileOffset : total);

                    Assert.InRange(current, 0, buffer.Length);

                    total += current;
                }
            }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #2
0
        public async Task WriteAsyncUsingMultipleBuffers(bool async)
        {
            string filePath   = GetTestFilePath();
            int    bufferSize = Environment.SystemPageSize;
            int    fileSize   = bufferSize * 10;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer_1 = SectorAlignedMemory <byte> .Allocate(bufferSize))
                    using (SectorAlignedMemory <byte> buffer_2 = SectorAlignedMemory <byte> .Allocate(bufferSize))
                    {
                        long total = 0;

                        IReadOnlyList <ReadOnlyMemory <byte> > buffers = new ReadOnlyMemory <byte>[]
                        {
                            buffer_1.Memory,
                            buffer_2.Memory,
                        };

                        while (total != fileSize)
                        {
                            content.AsSpan((int)total, bufferSize).CopyTo(buffer_1.GetSpan());
                            content.AsSpan((int)total + bufferSize, bufferSize).CopyTo(buffer_2.GetSpan());

                            total += async
                        ? await RandomAccess.WriteAsync(handle, buffers, fileOffset : total)
                        : RandomAccess.Write(handle, buffers, fileOffset: total);
                        }
                    }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #3
0
 public async Task WriteUsingEmptyBufferReturnsZeroAsync()
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: FileOptions.Asynchronous))
     {
         Assert.Equal(0, await RandomAccess.WriteAsync(handle, Array.Empty <byte>(), fileOffset: 0));
     }
 }
Exemple #4
0
            static async Task Validate(SafeFileHandle handle, FileOptions options, bool[] syncWrites, bool[] syncReads)
            {
                byte[] writeBuffer = new byte[1];
                byte[] readBuffer  = new byte[2];
                long   fileOffset  = 0;

                foreach (bool syncWrite in syncWrites)
                {
                    foreach (bool syncRead in syncReads)
                    {
                        writeBuffer[0] = (byte)fileOffset;

                        if (syncWrite)
                        {
                            RandomAccess.Write(handle, writeBuffer, fileOffset);
                        }
                        else
                        {
                            await RandomAccess.WriteAsync(handle, writeBuffer, fileOffset);
                        }

                        Assert.Equal(writeBuffer.Length, syncRead ? RandomAccess.Read(handle, readBuffer, fileOffset) : await RandomAccess.ReadAsync(handle, readBuffer, fileOffset));

                        Assert.Equal(writeBuffer[0], readBuffer[0]);

                        fileOffset += 1;
                    }
                }
            }
Exemple #5
0
        public async Task WritesBytesFromGivenBufferToGivenFileAtGivenOffsetAsync(FileOptions options)
        {
            const int fileSize = 4_001;
            string    filePath = GetTestFilePath();

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, options))
            {
                long total = 0;

                while (total != fileSize)
                {
                    int           firstBufferLength = (int)Math.Min(content.Length - total, fileSize / 4);
                    Memory <byte> buffer_1          = content.AsMemory((int)total, firstBufferLength);
                    Memory <byte> buffer_2          = content.AsMemory((int)total + firstBufferLength);

                    await RandomAccess.WriteAsync(
                        handle,
                        new ReadOnlyMemory <byte>[]
                    {
                        buffer_1,
                        Array.Empty <byte>(),
                        buffer_2
                    },
                        fileOffset : total);

                    total += buffer_1.Length + buffer_2.Length;
                }
            }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #6
0
        public async Task ReadWriteAsyncUsingNonPageSizedMultipleBuffers()
        {
            string filePath = GetTestFilePath();
            // The Windows scatter/gather APIs accept segments that are exactly one page long.
            // Combined with the FILE_FLAG_NO_BUFFERING's requirements, the segments must also
            // be aligned at page size boundaries and have a size of a multiple of the page size.
            // Using segments with a length of twice the page size adheres to the second requirement
            // but not the first. The RandomAccess implementation will see it and issue sequential
            // read/write syscalls per segment, instead of one scatter/gather syscall.
            // This test verifies that fallback behavior.
            int bufferSize = Environment.SystemPageSize * 2;
            int fileSize   = bufferSize * 2;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(fileSize))
                {
                    Memory <byte> firstHalf  = buffer.Memory.Slice(0, bufferSize);
                    Memory <byte> secondHalf = buffer.Memory.Slice(bufferSize);

                    content.AsSpan().CopyTo(buffer.GetSpan());
                    await RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { firstHalf, secondHalf }, 0);

                    buffer.GetSpan().Clear();
                    await RandomAccess.ReadAsync(handle, new Memory <byte>[] { firstHalf, secondHalf }, 0);
                }

            Assert.Equal(content, await File.ReadAllBytesAsync(filePath));
        }
 public async Task WriteUsingEmptyBufferReturnsZeroAsync(FileOptions options)
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: options))
     {
         Assert.Equal(0, await RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { Array.Empty <byte>() }, fileOffset: 0));
     }
 }
Exemple #8
0
        public async Task WriteUsingSingleBuffer(bool asyncOperation, bool asyncHandle)
        {
            string filePath   = GetTestFilePath();
            int    bufferSize = Environment.SystemPageSize;
            int    fileSize   = bufferSize * 10;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, GetFileOptions(asyncHandle)))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(bufferSize))
                {
                    int total = 0;

                    while (total != fileSize)
                    {
                        int take = Math.Min(content.Length - total, bufferSize);
                        content.AsSpan(total, take).CopyTo(buffer.GetSpan());

                        if (asyncOperation)
                        {
                            await RandomAccess.WriteAsync(handle, buffer.Memory, fileOffset : total);
                        }
                        else
                        {
                            RandomAccess.Write(handle, buffer.GetSpan(), fileOffset: total);
                        }

                        total += buffer.Memory.Length;
                    }
                }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #9
0
        public async Task ReadWriteAsyncUsingMultipleBuffers(bool memoryPageSized)
        {
            string filePath = GetTestFilePath();
            // We test with buffers both one and two memory pages long. In the former case,
            // the I/O operations will issue one scatter/gather API call, and in the latter
            // case they will issue multiple calls; one per buffer. The buffers must still
            // be aligned to comply with FILE_FLAG_NO_BUFFERING's requirements.
            int bufferSize = Environment.SystemPageSize * (memoryPageSized ? 1 : 2);
            int fileSize   = bufferSize * 2;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(fileSize))
                {
                    Memory <byte> firstHalf  = buffer.Memory.Slice(0, bufferSize);
                    Memory <byte> secondHalf = buffer.Memory.Slice(bufferSize);

                    content.AsSpan().CopyTo(buffer.GetSpan());
                    await RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { firstHalf, secondHalf }, 0);

                    buffer.GetSpan().Clear();
                    long nRead = await RandomAccess.ReadAsync(handle, new Memory <byte>[] { firstHalf, secondHalf }, 0);

                    Assert.Equal(buffer.GetSpan().Length, nRead);
                    AssertExtensions.SequenceEqual(buffer.GetSpan(), content.AsSpan());
                }
        }
 public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options)
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write, FileShare.None, options))
     {
         AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.WriteAsync(handle, buffers: null, 0));
     }
 }
Exemple #11
0
 public async Task WriteUsingEmptyBufferReturnsAsync(FileOptions options)
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: options))
     {
         await RandomAccess.WriteAsync(handle, Array.Empty <byte>(), fileOffset : 0);
     }
 }
        /// <summary>
        /// Writes the bucket to <paramref name="stream"/> and then closes <paramref name="bucket"/>
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bucket"></param>
        /// <param name="cancellationToken">Token for <see cref="Stream.WriteAsync(byte[], int, int, CancellationToken)"/></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static async ValueTask WriteToAsync(this Bucket bucket, Stream stream, CancellationToken cancellationToken = default)
        {
            if (bucket is null)
            {
                throw new ArgumentNullException(nameof(bucket));
            }
            else if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            using (bucket)
            {
#if NET6_0_OR_GREATER
                if (stream is FileStream fs && fs.CanSeek && bucket is IBucketReadBuffers rb)
                {
                    var  handle = fs.SafeFileHandle;
                    long pos    = fs.Position;
                    while (true)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var(buffers, done) = await bucket.ReadBuffersAsync().ConfigureAwait(false);

                        if (buffers.Length > 0)
                        {
                            var len = buffers.Sum(x => (long)x.Length);

                            await RandomAccess.WriteAsync(handle, buffers, pos, cancellationToken).ConfigureAwait(false);

                            pos += len;
                        }

                        if (done)
                        {
                            fs.Position = pos;
                            return;
                        }
                    }
                }
#endif
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var bb = await bucket.ReadAsync().ConfigureAwait(false);

                    if (bb.IsEof)
                    {
                        break;
                    }

                    await stream.WriteAsync(bb, cancellationToken).ConfigureAwait(false);
                }
            }
        }
Exemple #13
0
        public async Task ReadWriteAsyncUsingEmptyBuffers()
        {
            string filePath = GetTestFilePath();

            using SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering);

            long nRead = await RandomAccess.ReadAsync(handle, Array.Empty <Memory <byte> >(), 0);

            Assert.Equal(0, nRead);
            await RandomAccess.WriteAsync(handle, Array.Empty <ReadOnlyMemory <byte> >(), 0);
        }
        public async Task TaskAlreadyCanceledAsync(FileOptions options)
        {
            using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.ReadWrite, options: options))
            {
                CancellationTokenSource cts   = GetCancelledTokenSource();
                CancellationToken       token = cts.Token;

                Assert.True(RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { new byte[1] }, 0, token).IsCanceled);

                TaskCanceledException ex = await Assert.ThrowsAsync <TaskCanceledException>(() => RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { new byte[1] }, 0, token).AsTask());

                Assert.Equal(token, ex.CancellationToken);
            }
        }
Exemple #15
0
        public async Task WriteBeyondEndOfFileExtendsTheFileAsync(FileOptions options)
        {
            string filePath = GetTestFilePath();

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, options: options))
            {
                Assert.Equal(0, RandomAccess.GetLength(handle));
                await RandomAccess.WriteAsync(handle, new byte[1] {
                    1
                }, fileOffset : 1);

                Assert.Equal(2, RandomAccess.GetLength(handle));
            }

            Assert.Equal(new byte[] { 0, 1 }, await File.ReadAllBytesAsync(filePath));
        }
        public async Task DuplicatedBufferDuplicatesContentAsync(FileOptions options)
        {
            const byte            value       = 1;
            const int             repeatCount = 2;
            string                filePath    = GetTestFilePath();
            ReadOnlyMemory <byte> buffer      = new byte[1] {
                value
            };
            List <ReadOnlyMemory <byte> > buffers = Enumerable.Repeat(buffer, repeatCount).ToList();

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Create, FileAccess.Write, options: options))
            {
                Assert.Equal(repeatCount, await RandomAccess.WriteAsync(handle, buffers, fileOffset: 0));
            }

            byte[] actualContent = File.ReadAllBytes(filePath);
            Assert.Equal(repeatCount, actualContent.Length);
            Assert.All(actualContent, actual => Assert.Equal(value, actual));
        }
 public async Task ThrowsOnReadAccess(FileOptions options)
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options))
     {
         await Assert.ThrowsAsync <UnauthorizedAccessException>(async() => await RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { new byte[1] }, 0));
     }
 }
 protected override ValueTask <long> MethodUnderTest(SafeFileHandle handle, byte[] bytes, long fileOffset)
 => RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { bytes }, fileOffset);
Exemple #19
0
 public async Task ThrowsOnReadAccess()
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read))
     {
         await Assert.ThrowsAsync <UnauthorizedAccessException>(async() => await RandomAccess.WriteAsync(handle, new byte[1], 0));
     }
 }
Exemple #20
0
 protected override ValueTask MethodUnderTest(SafeFileHandle handle, byte[] bytes, long fileOffset)
 => RandomAccess.WriteAsync(handle, bytes, fileOffset);