105 lines
2.4 KiB
C++
105 lines
2.4 KiB
C++
/* unittest_util.h
|
|
* Copyright 2022 The ChromiumOS Authors
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
* Utility functions for unit tests.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <ftw.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include "util.h"
|
|
|
|
namespace {
|
|
|
|
constexpr bool is_android_constexpr() {
|
|
#if defined(__ANDROID__)
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
// Returns a template path that can be used as an argument to mkstemp / mkdtemp.
|
|
constexpr const char* temp_path_pattern() {
|
|
if (is_android_constexpr())
|
|
return "/data/local/tmp/minijail.tests.XXXXXX";
|
|
else
|
|
return "minijail.tests.XXXXXX";
|
|
}
|
|
|
|
// Recursively deletes the subtree rooted at |path|.
|
|
bool rmdir_recursive(const std::string& path) {
|
|
auto callback = [](const char* child, const struct stat*, int file_type,
|
|
struct FTW*) -> int {
|
|
if (file_type == FTW_DP) {
|
|
if (rmdir(child) == -1) {
|
|
fprintf(stderr, "rmdir(%s): %s\n", child, strerror(errno));
|
|
return -1;
|
|
}
|
|
} else if (file_type == FTW_F) {
|
|
if (unlink(child) == -1) {
|
|
fprintf(stderr, "unlink(%s): %s\n", child, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
return nftw(path.c_str(), callback, 128, FTW_DEPTH) == 0;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// Creates a temporary directory that will be cleaned up upon leaving scope.
|
|
class TemporaryDir {
|
|
public:
|
|
TemporaryDir() : path(temp_path_pattern()) {
|
|
if (mkdtemp(const_cast<char*>(path.c_str())) == nullptr)
|
|
path.clear();
|
|
}
|
|
~TemporaryDir() {
|
|
if (!is_valid())
|
|
return;
|
|
rmdir_recursive(path.c_str());
|
|
}
|
|
|
|
bool is_valid() const { return !path.empty(); }
|
|
|
|
std::string path;
|
|
|
|
private:
|
|
TemporaryDir(const TemporaryDir&) = delete;
|
|
TemporaryDir& operator=(const TemporaryDir&) = delete;
|
|
};
|
|
|
|
// Creates a named temporary file that will be cleaned up upon leaving scope.
|
|
class TemporaryFile {
|
|
public:
|
|
TemporaryFile() : path(temp_path_pattern()) {
|
|
int fd = mkstemp(const_cast<char*>(path.c_str()));
|
|
if (fd == -1) {
|
|
path.clear();
|
|
return;
|
|
}
|
|
close(fd);
|
|
}
|
|
~TemporaryFile() {
|
|
if (!is_valid())
|
|
return;
|
|
unlink(path.c_str());
|
|
}
|
|
|
|
bool is_valid() const { return !path.empty(); }
|
|
|
|
std::string path;
|
|
|
|
private:
|
|
TemporaryFile(const TemporaryFile&) = delete;
|
|
TemporaryFile& operator=(const TemporaryFile&) = delete;
|
|
};
|