public static void OnRollback(bool overwrite)
            {
#if DEBUG
                Console.WriteLine("FileIsNew_OnRollback");
#endif
                var sourcePath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "copy-file-source.txt";

                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "copy-file-is-new-on-rollback.txt";

                // Add a manager voting to force a rollback.

                ConcreteFileManager forcingRollbackManager =
                    new ConcreteFileManager(
                        "Data" +
                        Path.DirectorySeparatorChar +
                        "copy-file-is-new-on-rollback-0.txt");

                var onPrepareException = new Exception("Voting for a rollback.");

                forcingRollbackManager.OnPrepareBody = (stream) =>
                {
                    throw onPrepareException;
                };

                List <FileManager> managers = new List <FileManager>
                {
                    forcingRollbackManager,

                    new CopyFileManager(
                        sourcePath,
                        managedPath, overwrite: overwrite)
                };

                void results()
                {
                    Assert.IsTrue(!File.Exists(managedPath));
                }

                void rolledBack(Exception e)
                {
                    ExceptionAssert.IsThrown(
                        () => { throw e; },
                        expectedType: typeof(TransactionAbortedException),
                        expectedMessage: "The transaction has aborted.",
                        expectedInnerType: onPrepareException.GetType(),
                        expectedInnerMessage: onPrepareException.Message);
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
            public static void OnPrepareFileIsNotLockable()
            {
#if DEBUG
                Console.WriteLine("FileAlreadyExists_FileIsNotLockable");
#endif
                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "create-file-already-exists-on-prepare-file-is-not-lockable.txt";

                // Create a stream so that the manager cannot
                // lock the existing file and hence will force
                // a rollback.
                FileStream existingStream = new FileStream(
                    managedPath,
                    FileMode.Open,
                    FileAccess.Read,
                    FileShare.None);

                List <FileManager> managers = new List <FileManager>
                {
                    new CreateNonEmptyFileManager(
                        managedPath, overwrite: true)
                };

                void results()
                {
                    Assert.IsTrue(File.Exists(managedPath));

                    // Dispose the existing stream in order to
                    // enable file access.
                    existingStream.Dispose();
                    using (Stream stream = File.OpenRead(managedPath))
                    {
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            var content = reader.ReadLine();
                            Assert.AreEqual("existing-file", content);
                        }
                    }
                }

                void rolledBack(Exception e)
                {
                    ExceptionAssert.IsThrown(
                        () => { throw e; },
                        expectedType: typeof(TransactionAbortedException),
                        expectedMessage: "The transaction has aborted.",
                        expectedInnerType: typeof(IOException),
                        expectedInnerMessage: "The process cannot access the file '" +
                        existingStream.Name +
                        "' because it is being used by another process.");
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
            public static void OnCommit()
            {
#if DEBUG
                Console.WriteLine("FileAlreadyExists_OnCommit");
#endif
                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "edit-file-already-exists-on-commit.txt";

                var manager = new EditExistingFileManager(
                    managedPath);

                List <FileManager> managers = new List <FileManager>
                {
                    manager
                };

                void results()
                {
                    Assert.IsTrue(File.Exists(managedPath));
                    // The manager wrote the NewContent string to the managed file using the
                    // BinaryWriter.Write Method (String), the writer being instantiated
                    // with the Encoding.UTF8 encoding.
                    // Since such method writes a length-prefixed string to the stream,
                    // the number of written bytes is equal to the String.Length of
                    // NewContent plus 1, the prefixed byte representing such length.
                    int numberOfExpectedBytes = manager.NewContent.Length + 1;
                    var expectedBytes         = new byte[numberOfExpectedBytes];

                    expectedBytes[0] = Convert.ToByte(numberOfExpectedBytes - 1);
                    var stringBytes = Encoding.UTF8.GetBytes(manager.NewContent);

                    stringBytes.CopyTo(expectedBytes, 1);
                    var actualBytes         = File.ReadAllBytes(managedPath);
                    int numberOfActualBytes = actualBytes.Length;

                    Assert.AreEqual(numberOfExpectedBytes, numberOfActualBytes);

                    for (int i = 0; i < expectedBytes.Length; i++)
                    {
                        Assert.AreEqual(expectedBytes[i], actualBytes[i]);
                    }
                }

                void rolledBack(Exception e)
                {
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
            public static void OnPrepareCannotOverwrite()
            {
#if DEBUG
                Console.WriteLine("FileAlreadyExists_CannotOverwrite");
#endif
                var sourcePath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "copy-file-source.txt";

                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "copy-file-already-exists-on-prepare-cannot-overwrite.txt";

                List <FileManager> managers = new List <FileManager>
                {
                    new CopyFileManager(
                        sourcePath,
                        managedPath, overwrite: false)
                };

                void results()
                {
                    Assert.IsTrue(File.Exists(managedPath));
                    using (Stream stream = File.OpenRead(managedPath))
                    {
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            var content = reader.ReadLine();
                            Assert.AreEqual("existing-file", content);
                        }
                    }
                }

                void rolledBack(Exception e)
                {
                    ExceptionAssert.IsThrown(
                        () => { throw e; },
                        typeof(TransactionAbortedException),
                        "The transaction has aborted.");
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
            public static void OnCommit(bool overwrite)
            {
#if DEBUG
                Console.WriteLine("FileIsNew_OnCommit");
#endif
                var sourcePath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "copy-file-source.txt";

                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "copy-file-is-new-on-commit.txt";

                var manager = new CopyFileManager(sourcePath,
                                                  managedPath, overwrite: overwrite);

                List <FileManager> managers = new List <FileManager>
                {
                    manager
                };

                void results()
                {
                    Assert.IsTrue(File.Exists(managedPath));
                    var sourceBytes = File.ReadAllBytes(sourcePath);
                    var destBytes   = File.ReadAllBytes(managedPath);

                    Assert.AreEqual(sourceBytes.Length, destBytes.Length);

                    for (int i = 0; i < sourceBytes.Length; i++)
                    {
                        Assert.AreEqual(sourceBytes[i], destBytes[i]);
                    }
                }

                void rolledBack(Exception e)
                {
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
        public static void DefaultOnCommit()
        {
#if DEBUG
            Console.WriteLine("DefaultOnCommit");
#endif
            var managedPath =
                "Data" +
                Path.DirectorySeparatorChar +
                "create-file-is-new-default-on-commit.txt";

            var createManager = new CreateFileManager(
                managedPath, overwrite: true);

            List <FileManager> managers = new List <FileManager>
            {
                createManager
            };

            void results()
            {
                // Dispose the manager, so that
                // the following call to File.Exists
                // has the required permissions
                // to investigate the managed file.
                createManager.Dispose();

                Assert.IsTrue(File.Exists(managedPath));
                using (Stream stream = File.OpenRead(managedPath))
                {
                    Assert.AreEqual(0, stream.Length);
                }
            }

            void rolledBack(Exception e)
            {
            }

            TransactionScopeHelper.Using(
                managers,
                results,
                rolledBack);
        }
            public static void OnCommit(bool overwrite)
            {
#if DEBUG
                Console.WriteLine("FileIsNew_OnCommit");
#endif
                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "create-file-is-new-on-commit.txt";

                var createManager = new CreateNonEmptyFileManager(
                    managedPath, overwrite: overwrite);

                List <FileManager> managers = new List <FileManager>
                {
                    createManager
                };

                void results()
                {
                    Assert.IsTrue(File.Exists(managedPath));
                    using (Stream stream = File.OpenRead(managedPath))
                    {
                        using (BinaryReader reader = new BinaryReader(stream))
                        {
                            var content = reader.ReadString();
                            Assert.AreEqual(createManager.ContentWrittenOnCreation, content);
                        }
                    }
                }

                void rolledBack(Exception e)
                {
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
            public static void OnCommit()
            {
#if DEBUG
                Console.WriteLine("FileAlreadyExists_OnCommit");
#endif
                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "delete-file-already-exists-on-commit.txt";

                var deleteManager = new DeleteFileManager(
                    managedPath);

                List <FileManager> managers = new List <FileManager>
                {
                    deleteManager
                };

                void results()
                {
                    // Dispose the manager, so that
                    // the following call to File.Exists
                    // has the required permissions
                    // to investigate the managed file.
                    deleteManager.Dispose();

                    Assert.IsTrue(!File.Exists(managedPath));
                }

                void rolledBack(Exception e)
                {
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }
            public static void OnRollback()
            {
#if DEBUG
                Console.WriteLine("FileAlreadyExists_OnRollback");
#endif
                var managedPath =
                    "Data" +
                    Path.DirectorySeparatorChar +
                    "create-file-already-exists-on-rollback.txt";

                // Add a manager voting to force a rollback.

                ConcreteFileManager forcingRollbackManager =
                    new ConcreteFileManager(
                        "Data" +
                        Path.DirectorySeparatorChar +
                        "create-file-already-exists-on-rollback-0.txt");

                var onPrepareException = new Exception("Voting for a rollback.");

                forcingRollbackManager.OnPrepareBody = (stream) =>
                {
                    throw onPrepareException;
                };

                List <FileManager> managers = new List <FileManager>
                {
                    forcingRollbackManager,

                    new CreateNonEmptyFileManager(
                        managedPath, overwrite: true)
                };

                void results()
                {
                    Assert.IsTrue(File.Exists(managedPath));
                    using (Stream stream = File.OpenRead(managedPath))
                    {
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            var content = reader.ReadLine();
                            Assert.AreEqual("existing-file", content);
                        }
                    }
                }

                void rolledBack(Exception e)
                {
                    ExceptionAssert.IsThrown(
                        () => { throw e; },
                        expectedType: typeof(TransactionAbortedException),
                        expectedMessage: "The transaction has aborted.",
                        expectedInnerType: onPrepareException.GetType(),
                        expectedInnerMessage: onPrepareException.Message);
                }

                TransactionScopeHelper.Using(
                    managers,
                    results,
                    rolledBack);
            }