fd/fmt: Add storage consistent formatted output
This makes it trivial for a caller to write to files piecewise while
still guaranteeing that the output is always consistent. It performs
buffered writes to a tmpfile and only once successful does it swap out
for the resulting file.
Change-Id: I7e733a283ee60a47ddc6923cd9579fa49a7c5434
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/fd/fmt.cpp b/test/fd/fmt.cpp
index 726b5e5..fe1fed4 100644
--- a/test/fd/fmt.cpp
+++ b/test/fd/fmt.cpp
@@ -1,7 +1,10 @@
#include <gtest/gtest.h>
+#include <filesystem>
+#include <memory>
#include <stdplus/fd/fmt.hpp>
#include <stdplus/fd/managed.hpp>
+#include <stdplus/gtest/tmp.hpp>
#include <stdplus/util/cexec.hpp>
#include <sys/mman.h>
@@ -31,5 +34,42 @@
EXPECT_EQ(4106, fd.lseek(0, Whence::Cur));
}
+class FormatToFileTest : public gtest::TestWithTmp
+{
+ protected:
+ std::string tmpname;
+ std::unique_ptr<FormatToFile> file;
+
+ FormatToFileTest() :
+ tmpname(fmt::format("{}/tmp.XXXXXX", CaseTmpDir())),
+ file(std::make_unique<FormatToFile>(tmpname))
+ {
+ tmpname = file->getTmpname();
+ EXPECT_TRUE(std::filesystem::exists(tmpname));
+ }
+
+ ~FormatToFileTest() noexcept(true)
+ {
+ file.reset();
+ EXPECT_FALSE(std::filesystem::exists(tmpname));
+ }
+};
+
+TEST_F(FormatToFileTest, NoCommit)
+{
+ file->append("hi\n");
+ EXPECT_EQ(0, std::filesystem::file_size(tmpname));
+}
+
+TEST_F(FormatToFileTest, Basic)
+{
+ file->append("hi\n");
+ EXPECT_EQ(0, std::filesystem::file_size(tmpname));
+ auto filename = fmt::format("{}/out", CaseTmpDir());
+ file->commit(filename);
+ EXPECT_FALSE(std::filesystem::exists(tmpname));
+ EXPECT_EQ(3, std::filesystem::file_size(filename));
+}
+
} // namespace fd
} // namespace stdplus