diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2012-01-13 12:41:54 -0500 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2012-01-13 12:41:54 -0500 |
commit | b6a08ad007deb855ce4d428654279206853a3b99 (patch) | |
tree | 7ba73f3a79917ef28fd5cd6de1d346b28f0255fd /indra/test | |
parent | 39a86eda8d6d810bd7f4dd6b96f022548a496ba1 (diff) |
Extract APR and temp-fixture-file helper code to indra/test.
Specifically:
Introduce ManageAPR class in indra/test/manageapr.h. This is useful for a
simple test program without lots of static constructors.
Extract NamedTempFile from llsdserialize_test.cpp to indra/test/
namedtempfile.h. Refactor to use APR file operations rather than platform-
dependent APIs.
Use NamedTempFile for llprocesslauncher_test.cpp.
Diffstat (limited to 'indra/test')
-rw-r--r-- | indra/test/manageapr.h | 45 | ||||
-rw-r--r-- | indra/test/namedtempfile.h | 113 |
2 files changed, 158 insertions, 0 deletions
diff --git a/indra/test/manageapr.h b/indra/test/manageapr.h new file mode 100644 index 0000000000..0c1ca7b7be --- /dev/null +++ b/indra/test/manageapr.h @@ -0,0 +1,45 @@ +/** + * @file manageapr.h + * @author Nat Goodspeed + * @date 2012-01-13 + * @brief ManageAPR class for simple test programs + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_MANAGEAPR_H) +#define LL_MANAGEAPR_H + +#include "llapr.h" + +/** + * Declare a static instance of this class for dead-simple ll_init_apr() at + * program startup, ll_cleanup_apr() at termination. This is recommended for + * use only with simple test programs. Once you start introducing static + * instances of other classes that depend on APR already being initialized, + * the indeterminate static-constructor-order problem rears its ugly head. + */ +class ManageAPR +{ +public: + ManageAPR() + { + ll_init_apr(); + } + + ~ManageAPR() + { + ll_cleanup_apr(); + } + + static std::string strerror(apr_status_t rv) + { + char errbuf[256]; + apr_strerror(rv, errbuf, sizeof(errbuf)); + return errbuf; + } +}; + +#endif /* ! defined(LL_MANAGEAPR_H) */ diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h new file mode 100644 index 0000000000..9670d4db53 --- /dev/null +++ b/indra/test/namedtempfile.h @@ -0,0 +1,113 @@ +/** + * @file namedtempfile.h + * @author Nat Goodspeed + * @date 2012-01-13 + * @brief NamedTempFile class for tests that need disk files as fixtures. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Copyright (c) 2012, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_NAMEDTEMPFILE_H) +#define LL_NAMEDTEMPFILE_H + +#include "llapr.h" +#include "apr_file_io.h" +#include <string> +#include <boost/function.hpp> +#include "boost/lambda/lambda.hpp" +#include "boost/lambda/bind.hpp" +#include <iostream> +#include <sstream> + +/** + * Create a text file with specified content "somewhere in the + * filesystem," cleaning up when it goes out of scope. + */ +class NamedTempFile +{ +public: + NamedTempFile(const std::string& pfx, const std::string& content, apr_pool_t* pool=gAPRPoolp): + mPool(pool) + { + createFile(pfx, boost::lambda::_1 << content); + } + + // Disambiguate when passing string literal + NamedTempFile(const std::string& pfx, const char* content, apr_pool_t* pool=gAPRPoolp): + mPool(pool) + { + createFile(pfx, boost::lambda::_1 << content); + } + + // Function that accepts an ostream ref and (presumably) writes stuff to + // it, e.g.: + // (boost::lambda::_1 << "the value is " << 17 << '\n') + typedef boost::function<void(std::ostream&)> Streamer; + + NamedTempFile(const std::string& pfx, const Streamer& func, apr_pool_t* pool=gAPRPoolp): + mPool(pool) + { + createFile(pfx, func); + } + + ~NamedTempFile() + { + ll_apr_assert_status(apr_file_remove(mPath.c_str(), mPool)); + } + + std::string getName() const { return mPath; } + +private: + void createFile(const std::string& pfx, const Streamer& func) + { + // Create file in a temporary place. + const char* tempdir = NULL; + ll_apr_assert_status(apr_temp_dir_get(&tempdir, mPool)); + + // Construct a temp filename template in that directory. + char *tempname = NULL; + ll_apr_assert_status(apr_filepath_merge(&tempname, + tempdir, + (pfx + "XXXXXX").c_str(), + 0, + mPool)); + + // Create a temp file from that template. + apr_file_t* fp = NULL; + ll_apr_assert_status(apr_file_mktemp(&fp, + tempname, + APR_CREATE | APR_WRITE | APR_EXCL, + mPool)); + // apr_file_mktemp() alters tempname with the actual name. Not until + // now is it valid to capture as our mPath. + mPath = tempname; + + // Write desired content. + std::ostringstream out; + // Stream stuff to it. + func(out); + + std::string data(out.str()); + apr_size_t writelen(data.length()); + ll_apr_assert_status(apr_file_write(fp, data.c_str(), &writelen)); + ll_apr_assert_status(apr_file_close(fp)); + llassert_always(writelen == data.length()); + } + + void peep() + { + std::cout << "File '" << mPath << "' contains:\n"; + std::ifstream reader(mPath.c_str()); + std::string line; + while (std::getline(reader, line)) + std::cout << line << '\n'; + std::cout << "---\n"; + } + + std::string mPath; + apr_pool_t* mPool; +}; + +#endif /* ! defined(LL_NAMEDTEMPFILE_H) */ |