I've created a small RAII class that creates a unique temporary directory and deletes it again upon destruction. On Linux, it uses mkdtemp()
to achieve this:
// temporaryDirectoryPath is an std::vector<char>
// containing u8"/tmp/nuclex-pixels-unittest-XXXXXX"
// Let mkdtemp() sort out a unique directory name for us (and create it!)
const char *directoryName = ::mkdtemp(&temporaryDirectoryPath[0]);
if(directoryName == nullptr) {
perror("mkdtemp() failed."); // DEBUGGING. REMOVE.
throw std::runtime_error("mkdtemp() failed.");
}
This works just fine when run on its own: runnable code on ideone.com
However, if I use that same code inside a GoogleTest 1.8.1 unit test declared like this:
TEST(MyTestFixture, CanFlumbleTempDirectory) {
TemporaryDirectoryScope temporaryDirectory;
// Could call temporaryDirectory.GetPath() here...
}
It fails:
Passing the following to mkdtemp(): /tmp/nuclex-pixels-unittest-XXXXXX
mkdtemp() failed.: Invalid argument
How can GoogleTest be interfering with mkdtemp()
?
The string you pass to mkdtemp
is not reliably null-terminated:
// Then append our directory name template to it
const char directoryNameTemplate[] = u8"nuclex-pixels-unittest-XXXXXX";
{
const char *iterator = directoryNameTemplate;
while(*iterator != 0) {
temporaryDirectoryPath.push_back(*iterator);
++iterator;
}
}
std::vector<char>
does not perform implicit null termination, unlike std::string
. This works by accident if there happens to be a null byte after the "XXXXXX"
suffix. Whether that this is the case depends on the execution environment.