Пример #1
0
        public async Task LinkCanBeDeletedWhileOpenStreamHasAnotherLinkOpen()
        {
            using (var directory = new DisposableDirectory(FileSystem))
            {
                var context = new Context(Logger);
                await TestStore(context, _clock, async store =>
                {
                    // Put some content.
                    var r1 = await store.PutRandomAsync(context, 10);
                    ResultTestExtensions.ShouldBeSuccess((BoolResult)r1);

                    // Hardlink it somewhere outside the cache.
                    var path = directory.CreateRandomFileName();
                    var r2   = await store.PlaceFileAsync(
                        context,
                        r1.ContentHash,
                        path,
                        FileAccessMode.ReadOnly,
                        FileReplacementMode.FailIfExists,
                        FileRealizationMode.HardLink,
                        null);
                    r2.IsPlaced().Should().BeTrue();

                    // Open a stream to the cache link.
                    var r3 = await store.OpenStreamAsync(context, r1.ContentHash, null);
                    r3.ShouldBeSuccess();

                    using (r3.Stream)
                    {
                        // Verify the external link can be deleted
                        FileSystem.DeleteFile(path);
                    }
                });
            }
        }
        public Task PutContentSucceedsAfterFullnessReleased()
        {
            var contentSize = ContentSizeToStartHardPurging(3);

            return(TestStore(Context, Clock, async store =>
            {
                var triggeredEviction = false;
                store.OnLruEnumerationWithTime = hashes =>
                {
                    triggeredEviction = true;
                    return Task.FromResult(hashes);
                };

                using (var pinContext = store.CreatePinContext())
                {
                    await PutRandomAndPinAsync(store, contentSize, pinContext);
                    await PutRandomAndPinAsync(store, contentSize, pinContext);

                    PutResult putResult = await store.PutRandomAsync(Context, contentSize);
                    putResult.ShouldBeError();
                    triggeredEviction.Should().BeTrue();
                    triggeredEviction = false;

                    await pinContext.DisposeAsync();
                }

                PutResult putAfterReleaseResult = await store.PutRandomAsync(Context, contentSize);
                ResultTestExtensions.ShouldBeSuccess((BoolResult)putAfterReleaseResult);
                triggeredEviction.Should().BeTrue();
            }));
        }
Пример #3
0
        public Task PutStreamFullPinnedCacheThrows()
        {
            return(TestStore(Context, Clock, async store =>
            {
                using (var pinContext = store.CreatePinContext())
                {
                    var pinRequest = new PinRequest(pinContext);
                    var r = await store.PutRandomAsync(Context, MaxSizeHard / 3);
                    ResultTestExtensions.ShouldBeSuccess((BoolResult)r);
                    Clock.Increment();
                    Assert.True(await store.ContainsAsync(Context, r.ContentHash, pinRequest));
                    Clock.Increment();

                    r = await store.PutRandomAsync(Context, MaxSizeHard / 3);
                    Clock.Increment();
                    Assert.True(await store.ContainsAsync(Context, r.ContentHash, pinRequest));
                    Clock.Increment();

                    var data = ThreadSafeRandom.GetBytes(MaxSizeHard / 2);
                    using (var dataStream = new MemoryStream(data))
                    {
                        var result = await store.PutStreamAsync(Context, dataStream, ContentHashType, null);
                        Assert.False(result.Succeeded);
                    }

                    await store.SyncAsync(Context);
                }
            }));
        }
Пример #4
0
        private async Task PlaceFileAcrossDrivesAsync(
            FileRealizationMode allowedFileRealizationMode, Func <PlaceFileResult, bool> checkResult)
        {
            // This only works when we have multiple drives.
            if (FileSystem is MemoryFileSystem)
            {
                return;
            }

            using (var testDirectory = new DisposableDirectory(FileSystem))
            {
                var context = new Context(Logger);

                using (var store = Create(testDirectory.Path, _clock))
                {
                    var startupResult = await store.StartupAsync(context);

                    startupResult.ShouldBeSuccess();
                    try
                    {
                        byte[] bytes = ThreadSafeRandom.GetBytes(ValueSize);

                        AbsolutePath pathToContent = testDirectory.CreateRandomFileName();
                        FileSystem.WriteAllBytes(pathToContent, bytes);

                        // Put the content into the store via copy
                        var putResult = await store.PutFileAsync(
                            context, pathToContent, FileRealizationMode.Copy, ContentHashType, null);

                        ResultTestExtensions.ShouldBeSuccess((BoolResult)putResult);

                        var pathToPlaceDifferentVolume = new AbsolutePath(PathGeneratorUtilities.GetAbsolutePath("D", "foo.txt"));

                        try
                        {
                            var result = await store.PlaceFileAsync(
                                context,
                                putResult.ContentHash,
                                pathToPlaceDifferentVolume,
                                FileAccessMode.ReadOnly,
                                FileReplacementMode.FailIfExists,
                                allowedFileRealizationMode,
                                null);

                            Assert.True(checkResult(result), result.ToString());
                        }
                        finally
                        {
                            FileSystem.DeleteFile(pathToPlaceDifferentVolume);
                        }
                    }
                    finally
                    {
                        await store.ShutdownAsync(context).ShouldBeSuccess();
                    }
                }
            }
        }
        public async Task PlaceMultipleFilesFromMultipleSessions()
        {
            using (var placeDirectory = new DisposableDirectory(FileSystem))
            {
                var pathFromStream      = placeDirectory.Path / "file-stream.dat";
                var pathFromPath        = placeDirectory.Path / "file-path.dat";
                var pathFromNonexistent = placeDirectory.Path / "file-nonexistent.dat";

                await RunTestAsync(ImplicitPin.None, null, async (context, session) =>
                {
                    var putStreamResult = await session.PutRandomAsync(
                        context, ContentHashType, false, ContentByteCount, Token);
                    ResultTestExtensions.ShouldBeSuccess((BoolResult)putStreamResult);

                    var putFileResult = await session.PutRandomFileAsync(
                        context, FileSystem, ContentHashType, false, ContentByteCount, Token);
                    ResultTestExtensions.ShouldBeSuccess((BoolResult)putFileResult);

                    var hashesWithPaths = new[]
                    {
                        new ContentHashWithPath(putStreamResult.ContentHash, pathFromStream),
                        new ContentHashWithPath(ContentHash.Random(), pathFromNonexistent),
                        new ContentHashWithPath(putFileResult.ContentHash, pathFromPath),
                    };

                    var results = await session.PlaceFileAsync(
                        context,
                        hashesWithPaths,
                        FileAccessMode.ReadOnly,
                        FileReplacementMode.ReplaceExisting,
                        FileRealizationMode.Any,
                        Token);

                    foreach (var result in results)
                    {
                        var r = await result;
                        switch (r.Index)
                        {
                        case 0:
                            Assert.True(r.Item.Succeeded);
                            break;

                        case 1:
                            Assert.Equal(PlaceFileResult.ResultCode.NotPlacedContentNotFound, r.Item.Code);
                            break;

                        case 2:
                            Assert.True(r.Item.Succeeded);
                            break;

                        default:
                            Assert.False(true);
                            break;
                        }
                    }
                });
            }
        }
Пример #6
0
        public async Task PlaceFileRequiringNewReplicaCloseToHardLimitDoesNotHang()
        {
            var context = new Context(Logger);

            using (DisposableDirectory testDirectory = new DisposableDirectory(FileSystem))
            {
#pragma warning disable AsyncFixer04 // A disposable object used in a fire & forget async call
                Task testTask = TestStore(context, Clock, testDirectory, async store =>
#pragma warning restore AsyncFixer04 // A disposable object used in a fire & forget async call
                {
                    // Make a file which will overflow the cache size with just 2 copies.
                    PutResult putResult = await store.PutRandomAsync(context, ContentSizeToStartHardPurging(2));
                    ResultTestExtensions.ShouldBeSuccess((BoolResult)putResult);
                    ContentHash hash = putResult.ContentHash;

                    // Hardlink the file out 1024 times. Since the limit is 1024 total, and we already have 1 in the CAS,
                    // this will overflow the links and cause the CAS to create a new replica for it. This will cause
                    // the purger to consider that hash for eviction *while making room for that hash*, which is the
                    // trigger for the previous deadlock that this test will now guard against.
                    for (int i = 0; i < 1024; i++)
                    {
                        PlaceFileResult placeResult = await store.PlaceFileAsync(
                            context,
                            hash,
                            testDirectory.Path / $"hardlink{i}.txt",
                            FileAccessMode.ReadOnly,
                            FileReplacementMode.FailIfExists,
                            FileRealizationMode.HardLink,
                            null);

                        // The checks below are just to make sure that the calls completed as expected.
                        // The most important part is that they complete *at all*, which is enforced by
                        // racing against the Task.Delay in the outer scope.
                        if (i < 1023 || SucceedsEvenIfFull)
                        {
                            // The first 1023 links should succeed (bringing it up to the limit of 1024)
                            // And *all* of the calls should succeed if the cache takes new content even when overflowed.
                            Assert.True(placeResult.Succeeded);
                        }
                        else
                        {
                            // If the implementation rejects overflowing content, then the last call should fail.
                            Assert.False(placeResult.Succeeded);
                            Assert.Contains("Failed to reserve space", placeResult.ErrorMessage);
                        }
                    }
                });

                // Race between the test and a 2-minute timer. This can be increased if the test ends up flaky.
                Task firstCompletedTask = await Task.WhenAny(testTask, Task.Delay(TimeSpan.FromMinutes(2)));

                // The test should finish first, long before a minute passes, but it won't if it deadlocks.
                Assert.True(firstCompletedTask == testTask);
                await firstCompletedTask;
            }
        }
        public Task PinExistingInStreamSession()
        {
            return(RunTestAsync(ImplicitPin.None, null, async(context, session) =>
            {
                var putResult = await session.PutRandomAsync(context, ContentHashType, false, ContentByteCount, Token);
                ResultTestExtensions.ShouldBeSuccess((BoolResult)putResult);

                var result = await session.PinAsync(context, putResult.ContentHash, Token);
                result.ShouldBeSuccess();
            }));
        }
        public Task OpenStreamExistingFromPathSession()
        {
            return(RunTestAsync(ImplicitPin.None, null, async(context, session) =>
            {
                var putResult = await session.PutRandomFileAsync(
                    context, FileSystem, ContentHashType, false, ContentByteCount, Token);
                ResultTestExtensions.ShouldBeSuccess((BoolResult)putResult);

                var result = await session.OpenStreamAsync(context, putResult.ContentHash, Token);
                result.ShouldBeSuccess();
                Assert.NotNull(result.Stream);
                Assert.Equal(ContentByteCount, result.Stream.Length);
                result.Stream.Dispose();
            }));
        }
        public Task PinMultipleContentsFromMultipleSessions()
        {
            return(RunTestAsync(ImplicitPin.None, null, async(context, session) =>
            {
                var putStreamResult = await session.PutRandomAsync(
                    context, ContentHashType, false, ContentByteCount, Token);
                ResultTestExtensions.ShouldBeSuccess((BoolResult)putStreamResult);

                var putFileResult =
                    await
                    session.PutRandomFileAsync(context, FileSystem, ContentHashType, false, ContentByteCount, Token);
                ResultTestExtensions.ShouldBeSuccess((BoolResult)putFileResult);

                var results = await session.PinAsync(context, new[] { putStreamResult.ContentHash, ContentHash.Random(), putFileResult.ContentHash }, Token);

                foreach (var result in results)
                {
                    var r = await result;
                    switch (r.Index)
                    {
                    case 0:
                        r.Item.ShouldBeSuccess();
                        break;

                    case 1:
                        Assert.Equal(PinResult.ResultCode.ContentNotFound, r.Item.Code);
                        break;

                    case 2:
                        r.Item.ShouldBeSuccess();
                        break;

                    default:
                        Assert.False(true);
                        break;
                    }
                }
            }));
        }
        public async Task PlaceFileExistingFromPathSession()
        {
            using (var placeDirectory = new DisposableDirectory(FileSystem))
            {
                var path = placeDirectory.Path / "file.dat";
                await RunTestAsync(ImplicitPin.None, null, async (context, session) =>
                {
                    var putResult = await session.PutRandomFileAsync(
                        context, FileSystem, ContentHashType, false, ContentByteCount, Token);
                    ResultTestExtensions.ShouldBeSuccess((BoolResult)putResult);

                    var result = await session.PlaceFileAsync(
                        context,
                        putResult.ContentHash,
                        path,
                        FileAccessMode.ReadOnly,
                        FileReplacementMode.ReplaceExisting,
                        FileRealizationMode.Any,
                        Token);
                    Assert.True(result.IsPlaced());
                });
            }
        }
 public void ImplicitFailureCastFromResultFailure()
 => ResultTestExtensions
 .AssertFailure <int, string>(Result.Failure("One"))
 .Should()
 .Be("One");
 public void ImplicitSuccessCastFromResultSuccess()
 => ResultTestExtensions
 .AssertSuccess <int, string>(Result.Success(1))
 .Should()
 .Be(1);