fxing temp dir on windows

This commit is contained in:
matlabbe
2026-05-29 10:15:33 -07:00
parent d9ef6ad231
commit bcd39ab2e9
11 changed files with 78 additions and 62 deletions
+48
View File
@@ -0,0 +1,48 @@
#ifndef RTABMAP_CORELIB_TEST_TESTUTILS_H_
#define RTABMAP_CORELIB_TEST_TESTUTILS_H_
#include <cstdlib>
#include <string>
#ifdef _WIN32
#include <process.h>
#else
#include <unistd.h>
#endif
namespace rtabmap {
namespace test {
// Portable PID. MSVC has _getpid() in <process.h>; POSIX has getpid() in
// <unistd.h>. Tests typically use this to disambiguate temp file names
// across parallel runs.
inline int getPid()
{
#ifdef _WIN32
return _getpid();
#else
return ::getpid();
#endif
}
// Portable replacement for hardcoded "/tmp/<name>". /tmp doesn't exist on
// Windows so any test that wrote there failed to open the file. This honors
// TEMP/TMP on Windows and TMPDIR on POSIX, with an OS-appropriate fallback.
// Forward slash is accepted by Win32 APIs so we don't bother converting.
inline std::string tempPath(const std::string & name)
{
#ifdef _WIN32
const char * dir = std::getenv("TEMP");
if(!dir) dir = std::getenv("TMP");
if(!dir) dir = "C:/Temp";
#else
const char * dir = std::getenv("TMPDIR");
if(!dir) dir = "/tmp";
#endif
return std::string(dir) + "/" + name;
}
} // namespace test
} // namespace rtabmap
#endif // RTABMAP_CORELIB_TEST_TESTUTILS_H_
+2 -1
View File
@@ -14,6 +14,7 @@
#include <rtabmap/core/Parameters.h> #include <rtabmap/core/Parameters.h>
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include "TestUtils.h"
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp>
#include <chrono> #include <chrono>
@@ -35,7 +36,7 @@ namespace {
std::string uniqueDbPath() std::string uniqueDbPath()
{ {
static int counter = 0; static int counter = 0;
return uFormat("/tmp/rtabmap_dbdriver_test_%d_%d.db", getpid(), ++counter); return test::tempPath(uFormat("rtabmap_dbdriver_test_%d_%d.db", test::getPid(), ++counter));
} }
class DbDriverFixture : public ::testing::Test class DbDriverFixture : public ::testing::Test
+2 -1
View File
@@ -5,6 +5,7 @@
#include <rtabmap/core/Parameters.h> #include <rtabmap/core/Parameters.h>
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include "TestUtils.h"
using namespace rtabmap; using namespace rtabmap;
@@ -13,7 +14,7 @@ namespace {
std::string uniqueDbPath() std::string uniqueDbPath()
{ {
static int counter = 0; static int counter = 0;
return uFormat("/tmp/rtabmap_dbdriversqlite3_test_%d_%d.db", getpid(), ++counter); return test::tempPath(uFormat("rtabmap_dbdriversqlite3_test_%d_%d.db", test::getPid(), ++counter));
} }
class DBDriverSqlite3Fixture : public ::testing::Test class DBDriverSqlite3Fixture : public ::testing::Test
+3 -8
View File
@@ -8,14 +8,9 @@
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UMutex.h> #include <rtabmap/utilite/UMutex.h>
#include <rtabmap/utilite/UTimer.h> #include <rtabmap/utilite/UTimer.h>
#include "TestUtils.h"
#include <fstream> #include <fstream>
#include <cmath> #include <cmath>
#ifdef _WIN32
#include <process.h>
#define getpid _getpid
#else
#include <unistd.h>
#endif
#include <vector> #include <vector>
using namespace rtabmap; using namespace rtabmap;
@@ -26,7 +21,7 @@ static int g_fileCounter = 0;
static std::string tempImuCsvPath() static std::string tempImuCsvPath()
{ {
return uFormat("/tmp/rtabmap_imuthread_test_%d_%d.csv", getpid(), ++g_fileCounter); return test::tempPath(uFormat("rtabmap_imuthread_test_%d_%d.csv", test::getPid(), ++g_fileCounter));
} }
static bool writeImuCsv(const std::string & path, const std::vector<std::string> & rows) static bool writeImuCsv(const std::string & path, const std::vector<std::string> & rows)
@@ -174,7 +169,7 @@ static std::vector<IMUEventCollector::Sample> runThread(
TEST(IMUThreadTest, InitFailsOnMissingFile) TEST(IMUThreadTest, InitFailsOnMissingFile)
{ {
IMUThread thread(0, Transform::getIdentity()); IMUThread thread(0, Transform::getIdentity());
EXPECT_FALSE(thread.init("/tmp/rtabmap_imuthread_missing_file.csv")); EXPECT_FALSE(thread.init(test::tempPath("rtabmap_imuthread_missing_file.csv")));
} }
TEST(IMUThreadTest, InitFailsOnHeaderOnly) TEST(IMUThreadTest, InitFailsOnHeaderOnly)
+2 -7
View File
@@ -2,13 +2,8 @@
#include <rtabmap/core/Version.h> #include <rtabmap/core/Version.h>
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include "TestUtils.h"
#include <fstream> #include <fstream>
#ifdef _WIN32
#include <process.h>
#define getpid _getpid
#else
#include <unistd.h>
#endif
#ifdef RTABMAP_LIBLAS #ifdef RTABMAP_LIBLAS
#include <rtabmap/core/LASWriter.h> #include <rtabmap/core/LASWriter.h>
@@ -23,7 +18,7 @@ static int g_fileCounter = 0;
static std::string tempLasPath(const std::string & extension) static std::string tempLasPath(const std::string & extension)
{ {
return uFormat("/tmp/rtabmap_laswriter_test_%d_%d.%s", getpid(), ++g_fileCounter, extension.c_str()); return test::tempPath(uFormat("rtabmap_laswriter_test_%d_%d.%s", test::getPid(), ++g_fileCounter, extension.c_str()));
} }
#ifdef RTABMAP_LIBLAS #ifdef RTABMAP_LIBLAS
+2 -1
View File
@@ -13,6 +13,7 @@
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
#include "TestUtils.h"
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -38,7 +39,7 @@ ParametersMap defaultMemoryParams(int stmSize = 5)
std::string uniqueDbPath() std::string uniqueDbPath()
{ {
static int counter = 0; static int counter = 0;
return uFormat("/tmp/rtabmap_memory_test_%d_%d.db", getpid(), ++counter); return test::tempPath(uFormat("rtabmap_memory_test_%d_%d.db", test::getPid(), ++counter));
} }
class MemoryFixture : public ::testing::Test class MemoryFixture : public ::testing::Test
+3 -10
View File
@@ -22,15 +22,10 @@
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include "TestUtils.h"
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <string> #include <string>
#ifdef _WIN32
#include <process.h>
#define getpid _getpid
#else
#include <unistd.h>
#endif
using namespace rtabmap; using namespace rtabmap;
@@ -48,8 +43,7 @@ namespace {
// reloads fresh content on each TEST(). // reloads fresh content on each TEST().
std::string writeStubScript(int tag) std::string writeStubScript(int tag)
{ {
const std::string path = uFormat( const std::string path = test::tempPath(uFormat("rtabmap_test_pydescriptor_%d_%d.py", test::getPid(), tag));
"/tmp/rtabmap_test_pydescriptor_%d_%d.py", getpid(), tag);
std::ofstream out(path); std::ofstream out(path);
out << out <<
"import numpy as np\n" "import numpy as np\n"
@@ -173,8 +167,7 @@ TEST(PyDescriptor, EmptyPathReturnsEmpty)
// an empty descriptor. // an empty descriptor.
TEST(PyDescriptor, MissingPathReturnsEmpty) TEST(PyDescriptor, MissingPathReturnsEmpty)
{ {
const std::string scriptPath = uFormat( const std::string scriptPath = test::tempPath(uFormat("rtabmap_test_pydescriptor_does_not_exist_%d.py", test::getPid()));
"/tmp/rtabmap_test_pydescriptor_does_not_exist_%d.py", getpid());
std::unique_ptr<GlobalDescriptorExtractor> extractor( std::unique_ptr<GlobalDescriptorExtractor> extractor(
GlobalDescriptorExtractor::create( GlobalDescriptorExtractor::create(
GlobalDescriptorExtractor::kPyDescriptor, GlobalDescriptorExtractor::kPyDescriptor,
+3 -10
View File
@@ -20,15 +20,10 @@
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include "TestUtils.h"
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <string> #include <string>
#ifdef _WIN32
#include <process.h>
#define getpid _getpid
#else
#include <unistd.h>
#endif
using namespace rtabmap; using namespace rtabmap;
@@ -46,8 +41,7 @@ namespace {
// reloads fresh content on each TEST(). // reloads fresh content on each TEST().
std::string writeStubScript(int tag) std::string writeStubScript(int tag)
{ {
const std::string path = uFormat( const std::string path = test::tempPath(uFormat("rtabmap_test_pydetector_%d_%d.py", test::getPid(), tag));
"/tmp/rtabmap_test_pydetector_%d_%d.py", getpid(), tag);
std::ofstream out(path); std::ofstream out(path);
out << out <<
"import numpy as np\n" "import numpy as np\n"
@@ -135,8 +129,7 @@ TEST(PyDetector, BasicDetection)
// contract so callers can safely construct without pre-checking the path. // contract so callers can safely construct without pre-checking the path.
TEST(PyDetector, MissingPathReturnsEmpty) TEST(PyDetector, MissingPathReturnsEmpty)
{ {
const std::string scriptPath = uFormat( const std::string scriptPath = test::tempPath(uFormat("rtabmap_test_pydetector_does_not_exist_%d.py", test::getPid()));
"/tmp/rtabmap_test_pydetector_does_not_exist_%d.py", getpid());
std::unique_ptr<Feature2D> detector(Feature2D::create( std::unique_ptr<Feature2D> detector(Feature2D::create(
Feature2D::kFeaturePyDetector, baseParams(scriptPath))); Feature2D::kFeaturePyDetector, baseParams(scriptPath)));
ASSERT_NE(detector.get(), nullptr); ASSERT_NE(detector.get(), nullptr);
+3 -10
View File
@@ -17,18 +17,13 @@
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include "TestUtils.h"
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <string> #include <string>
#ifdef _WIN32
#include <process.h>
#define getpid _getpid
#else
#include <unistd.h>
#endif
using namespace rtabmap; using namespace rtabmap;
@@ -49,8 +44,7 @@ namespace {
// reloads fresh content on each TEST(). // reloads fresh content on each TEST().
std::string writeStubScript(int tag) std::string writeStubScript(int tag)
{ {
const std::string path = uFormat( const std::string path = test::tempPath(uFormat("rtabmap_test_pymatcher_%d_%d.py", test::getPid(), tag));
"/tmp/rtabmap_test_pymatcher_%d_%d.py", getpid(), tag);
std::ofstream out(path); std::ofstream out(path);
out << out <<
"import numpy as np\n" "import numpy as np\n"
@@ -168,8 +162,7 @@ TEST(PyMatcher, AsymmetricCounts)
// then short-circuits because pModule_ is null. // then short-circuits because pModule_ is null.
TEST(PyMatcher, MissingPathReturnsEmpty) TEST(PyMatcher, MissingPathReturnsEmpty)
{ {
const std::string scriptPath = uFormat( const std::string scriptPath = test::tempPath(uFormat("rtabmap_test_pymatcher_does_not_exist_%d.py", test::getPid()));
"/tmp/rtabmap_test_pymatcher_does_not_exist_%d.py", getpid());
PyMatcher matcher(scriptPath, 0.2f, 20, false, "indoor"); PyMatcher matcher(scriptPath, 0.2f, 20, false, "indoor");
cv::Mat descFrom = makeDescriptors(2, 8); cv::Mat descFrom = makeDescriptors(2, 8);
+6 -11
View File
@@ -22,12 +22,7 @@
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <string> #include <string>
#ifdef _WIN32 #include "TestUtils.h"
#include <process.h>
#define getpid _getpid
#else
#include <unistd.h>
#endif
#include <vector> #include <vector>
using namespace rtabmap; using namespace rtabmap;
@@ -55,7 +50,7 @@ ParametersMap defaultRtabmapParams(bool rgbdMode = true)
std::string uniqueDbPath() std::string uniqueDbPath()
{ {
static int counter = 0; static int counter = 0;
return uFormat("/tmp/rtabmap_test_%d_%d.db", getpid(), ++counter); return test::tempPath(uFormat("rtabmap_test_%d_%d.db", test::getPid(), ++counter));
} }
class RtabmapFixture : public ::testing::Test class RtabmapFixture : public ::testing::Test
@@ -2642,7 +2637,7 @@ TEST_F(RtabmapFixture, GenerateDOTGraphWritesDotFile)
{ {
for(int i = 0; i < 4; ++i) process(); for(int i = 0; i < 4; ++i) process();
const std::string dotPath = uFormat("/tmp/rtabmap_test_dot_%d.dot", getpid()); const std::string dotPath = test::tempPath(uFormat("rtabmap_test_dot_%d.dot", test::getPid()));
UFile::erase(dotPath.c_str()); UFile::erase(dotPath.c_str());
rtabmap_->generateDOTGraph(dotPath, /*id=*/0, /*margin=*/5); rtabmap_->generateDOTGraph(dotPath, /*id=*/0, /*margin=*/5);
@@ -2667,7 +2662,7 @@ TEST_F(RtabmapFixture, ExportPosesRawFormatRoundTripsViaImport)
// poses back. This covers the local/optimized export path. // poses back. This covers the local/optimized export path.
for(int i = 0; i < 4; ++i) process(); for(int i = 0; i < 4; ++i) process();
const std::string outPath = uFormat("/tmp/rtabmap_test_poses_raw_%d.txt", getpid()); const std::string outPath = test::tempPath(uFormat("rtabmap_test_poses_raw_%d.txt", test::getPid()));
UFile::erase(outPath.c_str()); UFile::erase(outPath.c_str());
rtabmap_->exportPoses(outPath, /*optimized=*/true, /*global=*/false, /*format=*/0); rtabmap_->exportPoses(outPath, /*optimized=*/true, /*global=*/false, /*format=*/0);
ASSERT_TRUE(UFile::exists(outPath)); ASSERT_TRUE(UFile::exists(outPath));
@@ -2690,7 +2685,7 @@ TEST_F(RtabmapFixture, ExportPosesRawFormatRoundTripsViaImport)
TEST_F(RtabmapFixture, ExportPosesKittiFormatWritesOneMatrixPerLine) TEST_F(RtabmapFixture, ExportPosesKittiFormatWritesOneMatrixPerLine)
{ {
for(int i = 0; i < 3; ++i) process(); for(int i = 0; i < 3; ++i) process();
const std::string outPath = uFormat("/tmp/rtabmap_test_poses_kitti_%d.txt", getpid()); const std::string outPath = test::tempPath(uFormat("rtabmap_test_poses_kitti_%d.txt", test::getPid()));
UFile::erase(outPath.c_str()); UFile::erase(outPath.c_str());
rtabmap_->exportPoses(outPath, /*optimized=*/true, /*global=*/false, /*format=*/2); rtabmap_->exportPoses(outPath, /*optimized=*/true, /*global=*/false, /*format=*/2);
ASSERT_TRUE(UFile::exists(outPath)); ASSERT_TRUE(UFile::exists(outPath));
@@ -3041,7 +3036,7 @@ TEST(RtabmapTest, GlobalBundleAdjustmentRefinesPosesOnSynthScene)
TEST_F(RtabmapFixture, ExportPosesTumFormatIncludesStampPerLine) TEST_F(RtabmapFixture, ExportPosesTumFormatIncludesStampPerLine)
{ {
for(int i = 0; i < 3; ++i) process(); for(int i = 0; i < 3; ++i) process();
const std::string outPath = uFormat("/tmp/rtabmap_test_poses_tum_%d.txt", getpid()); const std::string outPath = test::tempPath(uFormat("rtabmap_test_poses_tum_%d.txt", test::getPid()));
UFile::erase(outPath.c_str()); UFile::erase(outPath.c_str());
// Format 1 = RGBD-SLAM / TUM: stamp x y z qw qx qy qz (8 fields). // Format 1 = RGBD-SLAM / TUM: stamp x y z qw qx qy qz (8 fields).
rtabmap_->exportPoses(outPath, /*optimized=*/true, /*global=*/false, /*format=*/1); rtabmap_->exportPoses(outPath, /*optimized=*/true, /*global=*/false, /*format=*/1);
+4 -3
View File
@@ -33,6 +33,7 @@
#include <rtabmap/utilite/UFile.h> #include <rtabmap/utilite/UFile.h>
#include <rtabmap/utilite/UConversion.h> #include <rtabmap/utilite/UConversion.h>
#include "TestUtils.h"
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -47,14 +48,14 @@ std::string testDataPath(const std::string & basename)
} }
// Output DB path named after the running test so manual inspection is easy // Output DB path named after the running test so manual inspection is easy
// (rtabmap-databaseViewer /tmp/rtabmap_integration_<TestName>.db). The file // (rtabmap-databaseViewer <tempdir>/rtabmap_integration_<TestName>.db). The
// is overwritten on each run and NOT deleted at teardown. // file is overwritten on each run and NOT deleted at teardown.
std::string workDbForCurrentTest() std::string workDbForCurrentTest()
{ {
const ::testing::TestInfo * info = const ::testing::TestInfo * info =
::testing::UnitTest::GetInstance()->current_test_info(); ::testing::UnitTest::GetInstance()->current_test_info();
const std::string testName = info != nullptr ? info->name() : "unknown"; const std::string testName = info != nullptr ? info->name() : "unknown";
return uFormat("/tmp/rtabmap_integration_%s.db", testName.c_str()); return test::tempPath(uFormat("rtabmap_integration_%s.db", testName.c_str()));
} }
// Result bundle populated by replayDatabase(). Extend as the assertions in the // Result bundle populated by replayDatabase(). Extend as the assertions in the