Files
ResInsight/ThirdParty/Ert/lib/util/test_work_area.cpp
T

339 lines
10 KiB
C++
Raw Normal View History

/*
2019-05-07 07:15:25 +02:00
Copyright (C) 2013 Equinor ASA, Norway.
The file 'test_work_area.c' is part of ERT - Ensemble based Reservoir Tool.
ERT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ERT is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <ert/util/ert_api_config.hpp>
2016-04-19 14:48:14 +02:00
#ifdef ERT_HAVE_GETUID
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
2016-04-19 14:48:14 +02:00
#include <paths.h>
2013-10-07 13:31:13 +02:00
#endif
2019-05-07 07:15:25 +02:00
#include <ert/util/ert_api_config.hpp>
#include <stdlib.h>
#include <stdio.h>
2013-10-07 13:31:13 +02:00
#include <string.h>
#include <ert/util/util.h>
#include <ert/util/test_work_area.hpp>
2019-05-07 07:15:25 +02:00
#include "detail/util/path.hpp"
/*
This file implements a small work area implementation to be used for
tests which write to disk. The implementation works by creating a
work area in /tmp and then call chdir() change the current working
directory.
An important aspect of this implementation is that test output from
different users should not come in conflict with e.g. permission
problems, to achieve this the directories created will be per user.
When creating the work area you pass in a boolean flag whether you
2016-04-19 14:48:14 +02:00
want the area to be stored when the destructor is called. After the
the work_area is destroyed the cwd is changed back to the value it
had before the area was created.
The functions test_work_area_install_file(),
test_work_area_copy_directory() and
test_work_area_copy_directory_content() can be used to populate the
work area with files and directories needed for the test
execution. These functions have some intelligence when it comes to
interpreting relative paths; a relative path input argument is
interpreted relative to the original cwd.
Basic usage example:
--------------------
-- Create directory /tmp/$USER/ert-test/my/funn/test and call
-- chdir() to the newly created directory.
test_work_area_type * work_area = test_work_area_alloc("my/funny/test" , true);
-- Make files available from the test directory.
test_work_area_install_file(work_area , "/home/user/build/test-data/file1");
test_work_area_install_file(work_area , "relative/path/file2");
-- Recursively copy directory and directory content into test area:
test_work_area_copy_directory(work_area , "/home/user/build/test-data/case1");
...
-- Do normal test operations
...
-- Destroy test_work_area structure; since the work_area is created
2013-10-07 13:31:13 +02:00
-- with input flag @store set to true the are on disk will not be
-- cleared. After the test_work_area_free( ) function has been
-- called the original cwd will be restored.
test_work_area_free( work_area );
*/
2013-10-07 13:31:13 +02:00
#define DEFAULT_STORE false
2016-04-19 14:48:14 +02:00
#define TEST_PATH_FMT "%s/test/%s/%08d" /* username/test/test_name/random-integer */
2013-10-07 13:31:13 +02:00
#define FULL_PATH_FMT "%s/%s" /* prefix/test-path */
2013-10-07 13:31:13 +02:00
#define TEST_WORK_AREA_TYPE_ID 1107355
2019-05-07 07:15:25 +02:00
static char * test_work_area_alloc_prefix( ) {
#ifdef HAVE_WINDOWS_GET_TEMP_PATH
2019-05-07 07:15:25 +02:00
char tmp_path[MAX_PATH];
GetTempPath( MAX_PATH , tmp_path );
return util_alloc_string_copy( tmp_path );
2019-05-07 07:15:25 +02:00
#else
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
const char * prefix_path = getenv("TMPDIR");
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
#ifdef P_tmpdir
if (!prefix_path)
prefix_path = P_tmpdir;
#endif
if (!prefix_path)
prefix_path = _PATH_TMP;
return util_alloc_realpath(prefix_path);
#endif
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
namespace ecl {
namespace util {
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
static bool test_work_area_copy_parent__( const TestArea * work_area , const std::string& input_path, bool copy_content) {
char * full_path;
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
if (util_is_abs_path( input_path.c_str() ))
full_path = util_alloc_string_copy( input_path.c_str() );
else
full_path = util_alloc_filename( work_area->original_cwd().c_str( ) , input_path.c_str() , NULL);
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
if (util_entry_exists( full_path)) {
char * parent_path = util_alloc_parent_path( full_path );
if (copy_content)
work_area->copy_directory_content(std::string(parent_path));
else
work_area->copy_directory(std::string(parent_path));
2019-05-07 07:15:25 +02:00
free( full_path );
free( parent_path );
return true;
} else {
free( full_path );
return false;
}
}
TestArea::TestArea(const std::string& test_name, bool store_area) :
store(store_area)
{
char * prefix = test_work_area_alloc_prefix();
unsigned int random_int;
util_fread_dev_urandom( sizeof random_int, (char *) &random_int);
random_int = random_int % 100000000;
2016-04-19 14:48:14 +02:00
#ifdef ERT_HAVE_GETUID
uid_t uid = getuid();
struct passwd * pw = getpwuid( uid );
2013-10-07 13:31:13 +02:00
char * user_name = util_alloc_string_copy( pw->pw_name );
#else
char * user_name = util_alloc_sprintf("ert-test-%08u" , random_int);
2013-10-07 13:31:13 +02:00
#endif
2019-05-07 07:15:25 +02:00
char * test_path = util_alloc_sprintf( TEST_PATH_FMT , user_name , test_name.c_str() , random_int);
char * test_cwd = util_alloc_sprintf(FULL_PATH_FMT , prefix , test_path );
util_make_path( test_cwd );
{
char * cwd_tmp = util_alloc_cwd();
this->org_cwd = cwd_tmp;
free(cwd_tmp);
}
this->cwd = test_cwd;
if (util_chdir( this->cwd.c_str() ) != 0)
util_abort("%s: Failed to move into temporary directory: %s", __func__, this->cwd.c_str());
2013-10-07 13:31:13 +02:00
free( test_path );
free( user_name );
2019-05-07 07:15:25 +02:00
free( test_cwd );
free( prefix );
}
2019-05-07 07:15:25 +02:00
TestArea::~TestArea() {
if (!this->store)
util_clear_directory( this->cwd.c_str() , true , true );
2019-05-07 07:15:25 +02:00
util_chdir( this->org_cwd.c_str() );
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
const std::string& TestArea::test_cwd() const {
return this->cwd;
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
const std::string& TestArea::original_cwd() const {
return this->org_cwd;
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
std::string TestArea::original_path(const std::string& input_path) const {
if (util_is_abs_path( input_path.c_str() ))
return std::string(input_path);
else {
char * fname = util_alloc_filename( this->original_cwd().c_str(), input_path.c_str() , NULL);
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
std::string return_string = std::string(fname);
free(fname);
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
return return_string;
}
2016-04-19 14:48:14 +02:00
}
2019-05-07 07:15:25 +02:00
void TestArea::copy_file(const std::string& input_src_file) const {
std::string src_file = this->original_path(input_src_file);
if (util_file_exists( src_file.c_str() )) {
char * target_name = util_split_alloc_filename( input_src_file.c_str() );
char * target_file = util_alloc_filename( this->test_cwd().c_str() , target_name , NULL );
util_copy_file( src_file.c_str(), target_file );
free( target_file );
free( target_name );
2016-04-19 14:48:14 +02:00
}
2013-10-07 13:31:13 +02:00
}
2019-05-07 07:15:25 +02:00
void TestArea::copy_directory(const std::string input_directory) const {
std::string src_directory = this->original_path(input_directory);
util_copy_directory(src_directory.c_str() , this->test_cwd().c_str() );
}
2013-10-07 13:31:13 +02:00
2019-05-07 07:15:25 +02:00
void TestArea::copy_directory_content(const std::string input_directory) const {
std::string src_directory = this->original_path(input_directory);
util_copy_directory_content(src_directory.c_str() , this->test_cwd().c_str() );
2016-04-19 14:48:14 +02:00
}
2019-05-07 07:15:25 +02:00
bool TestArea::copy_parent(const std::string input_path) const {
return test_work_area_copy_parent__(this, input_path, false);
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
bool TestArea::copy_parent_content(const std::string input_path) const {
return test_work_area_copy_parent__(this, input_path, true);
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
}
2013-10-07 13:31:13 +02:00
}
2019-05-07 07:15:25 +02:00
/*****************************************************************/
/* C API */
2019-05-07 07:15:25 +02:00
test_work_area_type * test_work_area_alloc__(const char * test_name, bool store_area) {
if (test_name)
return new ecl::util::TestArea(test_name, store_area);
else
return NULL;
}
2019-05-07 07:15:25 +02:00
test_work_area_type * test_work_area_alloc(const char * test_name) {
return test_work_area_alloc__(test_name, false);
}
2016-04-19 14:48:14 +02:00
2019-05-07 07:15:25 +02:00
void test_work_area_free(test_work_area_type * work_area) {
delete work_area;
}
const char * test_work_area_get_cwd( const test_work_area_type * work_area ) {
2019-05-07 07:15:25 +02:00
return work_area->test_cwd().c_str();
}
const char * test_work_area_get_original_cwd( const test_work_area_type * work_area ) {
2019-05-07 07:15:25 +02:00
return work_area->original_cwd().c_str();
}
2019-05-07 07:15:25 +02:00
char * test_work_area_alloc_input_path( const test_work_area_type * work_area , const char * input_path ) {
2019-05-07 07:15:25 +02:00
std::string relocated_input_path = work_area->original_path(std::string(input_path));
return util_alloc_string_copy(relocated_input_path.c_str());
2016-04-19 14:48:14 +02:00
}
2013-10-07 13:31:13 +02:00
2019-05-07 07:15:25 +02:00
/**
The point of this function is that the test code should be able to
access the file @input_file independent of the fact that it has
changed path. If @input_file is an absolute path the function will
2019-05-07 07:15:25 +02:00
do nothing, if @input_file is a relative path the function will
copy @input_file from the location relative to the original cwd to
the corresponding location relative to the test cwd.
*/
2019-05-07 07:15:25 +02:00
void test_work_area_install_file( const test_work_area_type * work_area , const char * input_src_file ) {
if (util_is_abs_path( input_src_file))
return;
else {
2019-05-07 07:15:25 +02:00
std::string src_file = work_area->original_path(input_src_file);
std::string src_path = ecl::util::path::dirname(input_src_file);
2019-05-07 07:15:25 +02:00
if (!util_entry_exists( src_path.c_str() ))
util_make_path( src_path.c_str() );
2019-05-07 07:15:25 +02:00
if (util_file_exists( src_file.c_str() )) {
char * target_file = util_alloc_filename( work_area->test_cwd().c_str(), input_src_file, NULL );
util_copy_file( src_file.c_str() , target_file );
free( target_file );
}
}
}
2019-05-07 07:15:25 +02:00
void test_work_area_copy_file( const test_work_area_type * work_area , const char * input_file) {
if (input_file)
work_area->copy_file(std::string(input_file));
}
2019-05-07 07:15:25 +02:00
void test_work_area_copy_directory( const test_work_area_type * work_area , const char * input_directory) {
work_area->copy_directory(std::string(input_directory));
}
2019-05-07 07:15:25 +02:00
void test_work_area_copy_directory_content( const test_work_area_type * work_area , const char * input_directory) {
work_area->copy_directory_content(std::string(input_directory));
2013-10-07 13:31:13 +02:00
}
2019-05-07 07:15:25 +02:00
bool test_work_area_copy_parent_directory( const test_work_area_type * work_area , const char * input_path) {
return work_area->copy_parent(std::string(input_path));
2013-10-07 13:31:13 +02:00
}
2019-05-07 07:15:25 +02:00
bool test_work_area_copy_parent_content( const test_work_area_type * work_area , const char * input_path) {
return work_area->copy_parent_content(std::string(input_path));
2013-10-07 13:31:13 +02:00
}