Improving the way fileutil.h finds test resources.

Adding the argv[0] path to the working directory to make it possible find the project root even when the test is executed from outside the project dir (like it is on some buildbots).

Removed tests that moves into directories since they no longer work with this approach. The new functionality have been verified by manual tests of the following cases, example with a checkout root dir called webrtc/:
Working dir:                   Command line:
webrtc                         trunk/out/Debug/test
webrtc/trunk                   out/Debug/test
webrtc/trunk/out               Debug/test
webrtc/trunk/out               ./Debug/test
webrtc/trunk/out/Debug         ./test
webrtc/trunk/out/Debug/subdir  ../test
webrtc/trunk/out/Debug/subdir  ./../test

I also made another program with its own main method (only links with 'test_support', not 'test_support_main') and made sure that it was still possible to use as before (i.e. works within the project tree but not above it):

#include "testsupport/fileutils.h"
int main(int argc, char** argv) {
  printf("Working dir: %s\n", webrtc::test::WorkingDir().c_str());
  printf("Project root: %s\n", webrtc::test::ProjectRootPath().c_str());
  printf("Output path: %s\n", webrtc::test::OutputPath().c_str());
}

BUG=Existing implementation cannot handle when the working directory is outside the project checkout.
TEST=test_support_unittests and manual tests with video_codecs_test_framework_integration_tests + passing all trybots + memcheck tool

Review URL: https://webrtc-codereview.appspot.com/858014

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2927 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
kjellander@webrtc.org 2012-10-15 18:14:12 +00:00
parent ef433579cb
commit 83b767b0f5
4 changed files with 39 additions and 44 deletions

View File

@ -9,13 +9,16 @@
*/
#include "test/test_suite.h"
#include "test/testsupport/fileutils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace webrtc {
namespace test {
TestSuite::TestSuite(int argc, char** argv) {
SetRelativeExecutablePath(argv[0]);
testing::InitGoogleMock(&argc, argv); // Runs InitGoogleTest() internally.
}

View File

@ -24,6 +24,7 @@
#endif
#include <cstdio>
#include <cstring>
#include "typedefs.h" // For architecture defines
@ -46,26 +47,41 @@ static const char* kResourcesDirName = "resources";
#endif
const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
namespace {
char relative_dir_path[FILENAME_MAX];
bool relative_dir_path_set = false;
}
void SetRelativeExecutablePath(const std::string& path) {
// Trim away the executable name; we only want to store the relative dir path.
std::string temp_path = path.substr(0, path.find_last_of(kPathDelimiter));
strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
relative_dir_path_set = true;
}
bool FileExists(std::string& file_name) {
struct stat file_info = {0};
return stat(file_name.c_str(), &file_info) == 0;
}
std::string ProjectRootPath() {
std::string working_dir = WorkingDir();
if (working_dir == kFallbackPath) {
std::string path = WorkingDir();
if (path == kFallbackPath) {
return kCannotFindProjectRootDir;
}
if (relative_dir_path_set) {
path = path + kPathDelimiter + relative_dir_path;
}
// Check for our file that verifies the root dir.
std::string current_path(working_dir);
FILE* file = NULL;
int path_delimiter_index = current_path.find_last_of(kPathDelimiter);
int path_delimiter_index = path.find_last_of(kPathDelimiter);
while (path_delimiter_index > -1) {
std::string root_filename = current_path + kPathDelimiter +
kProjectRootFileName;
file = fopen(root_filename.c_str(), "r");
if (file != NULL) {
fclose(file);
return current_path + kPathDelimiter;
std::string root_filename = path + kPathDelimiter + kProjectRootFileName;
if (FileExists(root_filename)) {
return path + kPathDelimiter;
}
// Move up one directory in the directory tree.
current_path = current_path.substr(0, path_delimiter_index);
path_delimiter_index = current_path.find_last_of(kPathDelimiter);
path = path.substr(0, path_delimiter_index);
path_delimiter_index = path.find_last_of(kPathDelimiter);
}
// Reached the root directory.
fprintf(stderr, "Cannot find project root directory!\n");
@ -126,11 +142,6 @@ bool CreateDirectory(std::string directory_name) {
return true;
}
bool FileExists(std::string file_name) {
struct stat file_info = {0};
return stat(file_name.c_str(), &file_info) == 0;
}
std::string ResourcePath(std::string name, std::string extension) {
std::string platform = "win";
#ifdef WEBRTC_LINUX

View File

@ -138,6 +138,13 @@ bool CreateDirectory(std::string directory_name);
// empty or if the file does not exist/is readable.
size_t GetFileSize(std::string filename);
// Sets the relative executable path, i.e. the path to the executable relative
// to the working directory (the value of argv[0] for the main function on most
// platforms). By using this function, it becomes possible to fileutils.h to
// find the correct project paths even when the working directory is outside the
// project tree when running programs linked with the test_support_main target.
void SetRelativeExecutablePath(const std::string& relative_path_to_executable);
} // namespace test
} // namespace webrtc

View File

@ -23,7 +23,6 @@ static const char* kPathDelimiter = "\\";
static const char* kPathDelimiter = "/";
#endif
static const std::string kDummyDir = "file_utils_unittest_dummy_dir";
static const std::string kResourcesDir = "resources";
static const std::string kTestName = "fileutils_unittest";
static const std::string kExtension = "tmp";
@ -68,9 +67,6 @@ class FileUtilsTest : public testing::Test {
ASSERT_GT(fprintf(file, "%s", "Dummy data"), 0);
fclose(file);
}
// Create a dummy subdir that can be chdir'ed into for testing purposes.
empty_dummy_dir_ = original_working_dir_ + kPathDelimiter + kDummyDir;
webrtc::test::CreateDirectory(empty_dummy_dir_);
}
static void TearDownTestCase() {
// Clean up all resource files written
@ -78,7 +74,6 @@ class FileUtilsTest : public testing::Test {
file_it != files_.end(); ++file_it) {
remove(file_it->c_str());
}
std::remove(empty_dummy_dir_.c_str());
}
void SetUp() {
ASSERT_EQ(chdir(original_working_dir_.c_str()), 0);
@ -88,14 +83,12 @@ class FileUtilsTest : public testing::Test {
}
protected:
static FileList files_;
static std::string empty_dummy_dir_;
private:
static std::string original_working_dir_;
};
FileList FileUtilsTest::files_;
std::string FileUtilsTest::original_working_dir_ = "";
std::string FileUtilsTest::empty_dummy_dir_ = "";
// Tests that the project root path is returned for the default working
// directory that is automatically set when the test executable is launched.
@ -117,25 +110,6 @@ TEST_F(FileUtilsTest, OutputPathFromUnchangedWorkingDir) {
ASSERT_EQ(path.length() - expected_end.length(), path.find(expected_end));
}
// Tests setting the current working directory to a directory three levels
// deeper from the current one. Then testing that the project path returned
// is still the same, when the function under test is called again.
TEST_F(FileUtilsTest, ProjectRootPathFromDeeperWorkingDir) {
std::string path = webrtc::test::ProjectRootPath();
std::string original_working_dir = path; // This is the correct project root
// Change to a subdirectory path.
ASSERT_EQ(0, chdir(empty_dummy_dir_.c_str()));
ASSERT_EQ(original_working_dir, webrtc::test::ProjectRootPath());
}
// Similar to the above test, but for the output dir
TEST_F(FileUtilsTest, OutputPathFromDeeperWorkingDir) {
std::string path = webrtc::test::OutputPath();
std::string original_working_dir = path;
ASSERT_EQ(0, chdir(empty_dummy_dir_.c_str()));
ASSERT_EQ(original_working_dir, webrtc::test::OutputPath());
}
// Tests with current working directory set to a directory higher up in the
// directory tree than the project root dir. This case shall return a specified
// error string as a directory (which will be an invalid path).