public void TryWaitForDeleteAlwaysLogsFirstAndLastFailure()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            fileSystem.DeleteException = new IOException();

            MockTracer mockTracer = new MockTracer();
            int        maxRetries = 10;

            PhysicalFileSystemExtensions.TryWaitForDelete(fileSystem, mockTracer, path, retryDelayMs: 0, maxRetries: maxRetries, retryLoggingThreshold: 1000).ShouldBeFalse();
            fileSystem.DeleteFileCallCount.ShouldEqual(maxRetries + 1);

            mockTracer.RelatedWarningEvents.Count.ShouldEqual(2, "There should be two warning events, the first and last");
            mockTracer.RelatedWarningEvents[0].ShouldContain(
                new[]
            {
                "Failed to delete file, retrying ...",
                "\"failureCount\":1",
                "IOException"
            });
            mockTracer.RelatedWarningEvents[1].ShouldContain(
                new[]
            {
                "Failed to delete file.",
                "\"failureCount\":11",
                "IOException"
            });
        }
        public void TryDeleteFileDeletesFile()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path);
            fileSystem.ExistingFiles.ContainsKey(path).ShouldBeFalse("DeleteUtils failed to delete file");
        }
        public void TryDeleteFileDoesNotUpdateMetadataOnSuccess()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            EventMetadata metadata = new EventMetadata();

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path, "metadataKey", metadata).ShouldBeTrue("TryDeleteFile should succeed");
            metadata.ShouldBeEmpty("TryDeleteFile should not update metadata on success");
        }
        public void TryDeleteFileReturnsTrueWhenSetAttributesFailsToFindFile()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(
                Enumerable.Empty <KeyValuePair <string, FileAttributes> >(),
                allFilesExist: true,
                noOpDelete: false);

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path).ShouldEqual(true, "TryDeleteFile should return true when SetAttributes throws FileNotFoundException");
        }
        public void TryDeleteFileReturnsNullExceptionOnSuccess()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            Exception e = new Exception();

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path, out e);
            fileSystem.ExistingFiles.ContainsKey(path).ShouldBeFalse("DeleteUtils failed to delete file");
            e.ShouldBeNull("Exception should be null when TryDeleteFile succeeds");
        }
        public void TryDeleteFileSetsAttributesToNormalBeforeDeletingFile()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(
                new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) },
                allFilesExist: false,
                noOpDelete: true);

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path);
            fileSystem.ExistingFiles.ContainsKey(path).ShouldBeTrue("DeleteTestsFileSystem is configured as no-op delete, file should still be present");
            fileSystem.ExistingFiles[path].ShouldEqual(FileAttributes.Normal, "TryDeleteFile should set attributes to Normal before deleting");
        }
        public void TryDeleteFileUpdatesMetadataOnFailure()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            fileSystem.DeleteException = new IOException();

            EventMetadata metadata = new EventMetadata();

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path, "testKey", metadata).ShouldBeFalse("TryDeleteFile should fail when IOException is thrown");
            metadata.ContainsKey("testKey_DeleteFailed").ShouldBeTrue();
            metadata["testKey_DeleteFailed"].ShouldEqual("true");
            metadata.ContainsKey("testKey_DeleteException").ShouldBeTrue();
            metadata["testKey_DeleteException"].ShouldBeOfType <string>().ShouldContain("IOException");
        }
        public void TryWaitForDeleteSucceedsAfterFailures()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            fileSystem.DeleteException = new IOException();

            fileSystem.MaxDeleteFileExceptions = 5;
            PhysicalFileSystemExtensions.TryWaitForDelete(fileSystem, null, path, retryDelayMs: 0, maxRetries: 10, retryLoggingThreshold: 1).ShouldBeTrue();
            fileSystem.DeleteFileCallCount.ShouldEqual(fileSystem.MaxDeleteFileExceptions + 1);

            fileSystem.ExistingFiles.Add(path, FileAttributes.ReadOnly);
            fileSystem.DeleteFileCallCount     = 0;
            fileSystem.MaxDeleteFileExceptions = 9;
            PhysicalFileSystemExtensions.TryWaitForDelete(fileSystem, null, path, retryDelayMs: 0, maxRetries: 10, retryLoggingThreshold: 1).ShouldBeTrue();
            fileSystem.DeleteFileCallCount.ShouldEqual(fileSystem.MaxDeleteFileExceptions + 1);
        }
        public void TryDeleteFileReturnsThrownException()
        {
            string                path            = "mock:\\file.txt";
            Exception             deleteException = new IOException();
            DeleteTestsFileSystem fileSystem      = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            fileSystem.DeleteException = deleteException;

            Exception e;

            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path, out e).ShouldBeFalse("TryDeleteFile should fail on IOException");
            ReferenceEquals(e, deleteException).ShouldBeTrue("TryDeleteFile should return the thrown exception");

            deleteException            = new UnauthorizedAccessException();
            fileSystem.DeleteException = deleteException;
            PhysicalFileSystemExtensions.TryDeleteFile(fileSystem, path, out e).ShouldBeFalse("TryDeleteFile should fail on UnauthorizedAccessException");
            ReferenceEquals(e, deleteException).ShouldBeTrue("TryDeleteFile should return the thrown exception");
        }
        public void TryWaitForDeleteFailsAfterMaxRetries()
        {
            string path = "mock:\\file.txt";
            DeleteTestsFileSystem fileSystem = new DeleteTestsFileSystem(new[] { new KeyValuePair <string, FileAttributes>(path, FileAttributes.ReadOnly) });

            fileSystem.DeleteException = new IOException();

            int maxRetries = 10;

            PhysicalFileSystemExtensions.TryWaitForDelete(fileSystem, null, path, retryDelayMs: 0, maxRetries: maxRetries, retryLoggingThreshold: 1).ShouldBeFalse();
            fileSystem.DeleteFileCallCount.ShouldEqual(maxRetries + 1);

            fileSystem.DeleteFileCallCount = 0;
            PhysicalFileSystemExtensions.TryWaitForDelete(fileSystem, null, path, retryDelayMs: 1, maxRetries: maxRetries, retryLoggingThreshold: 1).ShouldBeFalse();
            fileSystem.DeleteFileCallCount.ShouldEqual(maxRetries + 1);

            fileSystem.DeleteFileCallCount = 0;
            PhysicalFileSystemExtensions.TryWaitForDelete(fileSystem, null, path, retryDelayMs: 1, maxRetries: 0, retryLoggingThreshold: 1).ShouldBeFalse();
            fileSystem.DeleteFileCallCount.ShouldEqual(1);
        }