Skip to content

Commit

Permalink
Add functions and objects for Temporary Directories (#244)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Carroll <michael@openrobotics.org>

Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
  • Loading branch information
mjcarroll and ahcorde authored Sep 13, 2021
1 parent 9694f89 commit d06ed33
Show file tree
Hide file tree
Showing 8 changed files with 495 additions and 46 deletions.
110 changes: 110 additions & 0 deletions include/ignition/common/TempDirectory.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2021 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef IGNITION_COMMON_TEMPDIRECTORY_HH_
#define IGNITION_COMMON_TEMPDIRECTORY_HH_

#include <memory>
#include <string>

#include <ignition/common/Export.hh>
#include <ignition/common/Filesystem.hh>
#include <ignition/utils/ImplPtr.hh>

namespace ignition
{
namespace common
{
class TempDirectoryPrivate;

/// \brief Return the path to a directory suitable for temporary files.
///
/// Calls std::filesystem::temp_directory_path, refer to the standard
/// documentation for your platform for behaviors.
/// \return A directory suitable for temporary files.
std::string IGNITION_COMMON_VISIBLE tempDirectoryPath();

/// \brief Create a directory in the tempDirectoryPath by expanding
/// a name template
///
/// On execution, will create the directory:
/// "_parentPath"/"_baseName" + "XXXXXX", where XXXXXX will be filled
/// out by an OS-appropriate method (eg mkdtmp/_mktemp_s)
///
/// \param[in] _baseName String to be prepended to the expanded template
/// \param[in] _parentPath Location to create the directory
/// \param[in] _warningOp Allow or suppress filesystem warnings
/// \return Path to newly-created temporary directory
std::string IGNITION_COMMON_VISIBLE createTempDirectory(
const std::string &_baseName,
const std::string &_parentPath,
const FilesystemWarningOp _warningOp = FSWO_LOG_WARNINGS);

/// \class TempDirectory TempDirectory.hh ignitin/common/TempDirectory.hh
/// \brief Create a temporary directory in the OS temp location.
/// Upon construction, the current working directory will be set to this
/// new temporary directory.
/// Upon destruction, the current working directory will be restored to the
/// location when the TempDirectory object was constructed.
class IGNITION_COMMON_VISIBLE TempDirectory
{
/// \brief Create a directory in the tempDirectoryPath by expanding
/// a name template. This directory can also be automatically cleaned
/// up when the object goes out of scope.
///
/// The TempDirectory will have the form $TMPDIR/_subdir/_prefixXXXXX/
///
/// \param[in] _prefix String to be expanded for the template
/// \param[in] _subDir Subdirectory in OS $TMPDIR, if desired
/// \param[in] _cleanup True to indicate that the filesystem should
/// be cleaned as part of the destructor
public: TempDirectory(const std::string &_prefix = "temp_dir",
const std::string &_subDir = "ignition",
bool _cleanup = true);

/// \brief Destroy the temporary directory, removing from filesystem
/// if cleanup is true.
public: ~TempDirectory();

/// \brief Indicate if the TempDirectory object is in a valid state
/// and that the folder exists on the filesystem
/// \return true if the TempDirectory is valid
public: bool Valid() const;

/// \brief Set if the folder on disk should be cleaned.
///
/// This is useful if you wish to clean by default during a test, but
/// retain the contents of the TempDirectory if the test fails.
/// \param[in] _doCleanup True to indicate that the filesystem should
/// be cleaned as part of the destructor
public: void DoCleanup(bool _doCleanup);

/// \brief Retrieve the current cleanup flag state
/// \return true if filesystem cleanup will occur
public: bool DoCleanup() const;

/// \brief Retrieve the fully-expanded temporary directory path
/// \return the temporary directory path
public: std::string Path() const;

/// \brief Private data pointer.
IGN_UTILS_IMPL_PTR(dataPtr)
};
} // namespace common
} // namespace ignition
#endif // IGNITION_COMMON_TEMPDIRECTORY_HH_

3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME}
target_include_directories(${PROJECT_LIBRARY_TARGET_NAME} PRIVATE
${ignition-math${IGN_MATH_VER}_INCLUDE_DIRS})

target_include_directories(${PROJECT_LIBRARY_TARGET_NAME} PUBLIC
${ignition-utils${IGN_UTILS_VER}_INCLUDE_DIRS})

# Handle non-Windows configuration settings
if(NOT WIN32)
# Link the libraries that we don't expect to find on Windows
Expand Down
2 changes: 1 addition & 1 deletion src/Console.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ void FileLogger::Init(const std::string &_directory,
if (isDirectory(logPath))
this->logDirectory = logPath;
else
this->logDirectory = logPath.substr(0, logPath.rfind(separator("")));
this->logDirectory = common::parentPath(logPath);

this->initialized = true;

Expand Down
19 changes: 9 additions & 10 deletions src/Console_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,21 @@ const int g_messageRepeat = 4;
class Console_TEST : public ::testing::Test {
protected: virtual void SetUp()
{
// Set IGN_HOMEDIR and store it
common::testing::TestSetHomePath(this->logBasePath);
this->temp = std::make_unique<TempDirectory>(
"test", "ign_common", true);
ASSERT_TRUE(this->temp->Valid());
common::setenv(IGN_HOMEDIR, this->temp->Path());
}

/// \brief Clear out all the directories we produced during this test.
public: virtual ~Console_TEST()
public: virtual void TearDown()
{
ignLogClose();
EXPECT_TRUE(ignition::common::unsetenv(IGN_HOMEDIR));

if (ignition::common::isDirectory(this->logBasePath))
{
ignLogClose();
EXPECT_TRUE(ignition::common::removeAll(this->logBasePath));
}
}

private: std::string logBasePath;
/// \brief Temporary directory to run test in
private: std::unique_ptr<common::TempDirectory> temp;
};

std::string GetLogContent(const std::string &_filename)
Expand All @@ -58,6 +56,7 @@ std::string GetLogContent(const std::string &_filename)
std::string path;
EXPECT_TRUE(ignition::common::env(IGN_HOMEDIR, path));
path = ignition::common::joinPaths(path, _filename);
EXPECT_TRUE(ignition::common::exists(path));

// Open the log file, and read back the string
std::ifstream ifs(path.c_str(), std::ios::in);
Expand Down
16 changes: 16 additions & 0 deletions src/SystemPaths_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "ignition/common/Util.hh"
#include "ignition/common/StringUtils.hh"
#include "ignition/common/SystemPaths.hh"
#include "ignition/common/TempDirectory.hh"

#ifdef _WIN32
#define snprintf _snprintf
Expand All @@ -36,11 +37,22 @@ using namespace ignition;
const char kPluginPath[] = "IGN_PLUGIN_PATH";
const char kFilePath[] = "IGN_FILE_PATH";

class TestTempDirectory : public ignition::common::TempDirectory
{
public: TestTempDirectory():
ignition::common::TempDirectory("systempaths", "ign_common", true)
{
}
};

class SystemPathsFixture : public ::testing::Test
{
// Documentation inherited
public: virtual void SetUp()
{
this->temp = std::make_unique<TestTempDirectory>();
ASSERT_TRUE(this->temp->Valid());

common::env(kPluginPath, this->backupPluginPath);
common::unsetenv(kPluginPath);

Expand All @@ -59,6 +71,7 @@ class SystemPathsFixture : public ::testing::Test
{
common::setenv(kPluginPath, this->backupPluginPath);
common::setenv(kFilePath, this->backupFilePath);
this->temp.reset();
}

/// \brief Backup of plugin paths to be restored after the test
Expand All @@ -69,6 +82,9 @@ class SystemPathsFixture : public ::testing::Test

/// \brief Root of filesystem according to each platform
public: std::string filesystemRoot;

/// \brief Temporary directory to execute test in
public: std::unique_ptr<TestTempDirectory> temp;
};

std::string SystemPathsJoin(const std::vector<std::string> &_paths)
Expand Down
Loading

0 comments on commit d06ed33

Please sign in to comment.