Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/moses-smt/mosesdecoder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorJeroen Vermeulen <jtv@precisiontranslationtools.com>2015-04-17 18:57:55 +0300
committerJeroen Vermeulen <jtv@precisiontranslationtools.com>2015-04-17 18:57:55 +0300
commitd56f317f2ee844beffc7f83e3e6ae2aeb80add61 (patch)
tree7719c4cc3ea2648c423ec80630342c21f76d5477 /util
parentc5e9a58ae2acb70d05a59722989b526fcce31e9f (diff)
New helper classes: temp_dir & temp_file.
I'm adding these because boost::filesystem::unique_path introduces encoding issues: on Windows the path is in wchar_t, breaking use of those strings in various places! Encoding the strings is just too much work. It's still possible that the current temp_file implementation won't build on Windows (it uses POSIX mkstemp() and close()) but that can be fixed underneath the API.
Diffstat (limited to 'util')
-rw-r--r--util/Jamfile2
-rw-r--r--util/tempfile.hh79
-rw-r--r--util/tempfile_test.cc119
3 files changed, 199 insertions, 1 deletions
diff --git a/util/Jamfile b/util/Jamfile
index 18b20a33a..a82a5e23d 100644
--- a/util/Jamfile
+++ b/util/Jamfile
@@ -32,5 +32,5 @@ import testing ;
run file_piece_test.o kenutil /top//boost_unit_test_framework : : file_piece.cc ;
for local t in [ glob *_test.cc : file_piece_test.cc read_compressed_test.cc ] {
local name = [ MATCH "(.*)\.cc" : $(t) ] ;
- unit-test $(name) : $(t) kenutil /top//boost_unit_test_framework /top//boost_system ;
+ unit-test $(name) : $(t) kenutil /top//boost_unit_test_framework /top//boost_filesystem /top//boost_system ;
}
diff --git a/util/tempfile.hh b/util/tempfile.hh
new file mode 100644
index 000000000..228238823
--- /dev/null
+++ b/util/tempfile.hh
@@ -0,0 +1,79 @@
+#ifndef UTIL_TEMPFILE_H
+#define UTIL_TEMPFILE_H
+
+// Utilities for creating temporary files and directories.
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include <boost/filesystem.hpp>
+#include <boost/noncopyable.hpp>
+
+#include "util/exception.hh"
+
+namespace util
+{
+
+/** Temporary directory.
+ *
+ * Automatically creates, and on destruction deletes, a temporary directory.
+ * The actual directory in the filesystem will only exist while the temp_dir
+ * object exists.
+ *
+ * If the directory no longer exists by the time the temp_dir is destroyed,
+ * no cleanup happens.
+ */
+class temp_dir : boost::noncopyable
+{
+public:
+ temp_dir()
+ {
+ char buf[] = "tmpdir.XXXXXX";
+ m_path = std::string(mkdtemp(buf));
+ }
+
+ ~temp_dir()
+ {
+ boost::filesystem::remove_all(path());
+ }
+
+ /// Return the temporary directory's full path.
+ const std::string &path() const { return m_path; }
+
+private:
+ std::string m_path;
+};
+
+
+/** Temporary file.
+ *
+ * Automatically creates, and on destruction deletes, a temporary file.
+ */
+class temp_file : boost::noncopyable
+{
+public:
+ temp_file()
+ {
+ char buf[] = "tmp.XXXXXX";
+ const int fd = mkstemp(buf);
+ if (fd == -1) throw ErrnoException();
+ close(fd);
+ m_path = buf;
+ }
+
+ ~temp_file()
+ {
+ boost::filesystem::remove(path());
+ }
+
+ /// Return the temporary file's full path.
+ const std::string &path() const { return m_path; }
+
+private:
+ std::string m_path;
+};
+
+} // namespace util
+
+#endif
diff --git a/util/tempfile_test.cc b/util/tempfile_test.cc
new file mode 100644
index 000000000..49736fe0c
--- /dev/null
+++ b/util/tempfile_test.cc
@@ -0,0 +1,119 @@
+#include "util/tempfile.hh"
+
+#include <fstream>
+
+#include <boost/filesystem.hpp>
+
+#define BOOST_TEST_MODULE TempFileTest
+#include <boost/test/unit_test.hpp>
+
+namespace util
+{
+namespace
+{
+
+BOOST_AUTO_TEST_CASE(temp_dir_has_path)
+{
+ BOOST_CHECK(temp_dir().path().size() > 0);
+}
+
+BOOST_AUTO_TEST_CASE(temp_dir_creates_temp_directory)
+{
+ const temp_dir t;
+ BOOST_CHECK(boost::filesystem::exists(t.path()));
+ BOOST_CHECK(boost::filesystem::is_directory(t.path()));
+}
+
+BOOST_AUTO_TEST_CASE(temp_dir_creates_unique_directory)
+{
+ BOOST_CHECK(temp_dir().path() != temp_dir().path());
+}
+
+BOOST_AUTO_TEST_CASE(temp_dir_cleans_up_directory)
+{
+ std::string path;
+ {
+ const temp_dir t;
+ path = t.path();
+ }
+ BOOST_CHECK(!boost::filesystem::exists(path));
+}
+
+BOOST_AUTO_TEST_CASE(temp_dir_cleanup_succeeds_if_directory_contains_file)
+{
+ std::string path;
+ {
+ const temp_dir t;
+ path = t.path();
+ boost::filesystem::create_directory(path + "/directory");
+ std::ofstream file((path + "/file").c_str());
+ file << "Text";
+ file.flush();
+ }
+ BOOST_CHECK(!boost::filesystem::exists(path));
+}
+
+BOOST_AUTO_TEST_CASE(temp_dir_cleanup_succeeds_if_directory_is_gone)
+{
+ std::string path;
+ {
+ const temp_dir t;
+ path = t.path();
+ boost::filesystem::remove_all(path);
+ }
+ BOOST_CHECK(!boost::filesystem::exists(path));
+}
+
+BOOST_AUTO_TEST_CASE(temp_file_has_path)
+{
+ BOOST_CHECK(temp_file().path().size() > 0);
+}
+
+BOOST_AUTO_TEST_CASE(temp_file_creates_temp_file)
+{
+ const temp_file f;
+ BOOST_CHECK(boost::filesystem::exists(f.path()));
+ BOOST_CHECK(boost::filesystem::is_regular_file(f.path()));
+}
+
+BOOST_AUTO_TEST_CASE(temp_file_creates_unique_file)
+{
+ BOOST_CHECK(temp_file().path() != temp_file().path());
+}
+
+BOOST_AUTO_TEST_CASE(temp_file_creates_writable_file)
+{
+ const std::string data = "Test-data-goes-here";
+ const temp_file f;
+ std::ofstream outfile(f.path().c_str());
+ outfile << data;
+ outfile.flush();
+ std::string read_data;
+ std::ifstream infile(f.path().c_str());
+ infile >> read_data;
+ BOOST_CHECK_EQUAL(data, read_data);
+}
+
+BOOST_AUTO_TEST_CASE(temp_file_cleans_up_file)
+{
+ std::string path;
+ {
+ const temp_file f;
+ path = f.path();
+ }
+ BOOST_CHECK(!boost::filesystem::exists(path));
+}
+
+BOOST_AUTO_TEST_CASE(temp_file_cleanup_succeeds_if_file_is_gone)
+{
+ std::string path;
+ {
+ const temp_file t;
+ path = t.path();
+ boost::filesystem::remove(path);
+ }
+ BOOST_CHECK(!boost::filesystem::exists(path));
+}
+
+} // namespace anonymous
+} // namespace util