Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:58:55 +01:00
parent 4af19165ec
commit 68073add76
12458 changed files with 12350765 additions and 2 deletions

View file

@ -0,0 +1,23 @@
project(platform_tests_support)
set(SRC
async_gui_thread.hpp
helpers.hpp
scoped_dir.cpp
scoped_dir.hpp
scoped_file.cpp
scoped_file.hpp
scoped_mwm.cpp
scoped_mwm.hpp
test_socket.cpp
test_socket.hpp
writable_dir_changer.cpp
writable_dir_changer.hpp
)
omim_add_library(${PROJECT_NAME} ${SRC})
target_link_libraries(${PROJECT_NAME}
platform
indexer # feature::DataHeader::Save
)

View file

@ -0,0 +1,29 @@
#pragma once
#include "platform/gui_thread.hpp"
#include "platform/platform.hpp"
#include "base/thread_pool_delayed.hpp"
#include <memory>
namespace platform
{
namespace tests_support
{
class AsyncGuiThread
{
public:
AsyncGuiThread()
{
GetPlatform().SetGuiThread(
std::make_unique<base::DelayedThreadPool>(1 /* threadsCount */, base::DelayedThreadPool::Exit::ExecPending));
}
virtual ~AsyncGuiThread() { GetPlatform().SetGuiThread(std::make_unique<platform::GuiThread>()); }
private:
Platform::ThreadRunner m_runner;
};
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,21 @@
#pragma once
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_LINUX)
#include <sys/resource.h>
#endif
namespace platform
{
namespace tests_support
{
inline void ChangeMaxNumberOfOpenFiles(size_t n)
{
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_LINUX)
struct rlimit rlp;
getrlimit(RLIMIT_NOFILE, &rlp);
rlp.rlim_cur = n;
setrlimit(RLIMIT_NOFILE, &rlp);
#endif
}
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,61 @@
#include "platform/platform_tests_support/scoped_dir.hpp"
#include "testing/testing.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include <sstream>
namespace platform
{
namespace tests_support
{
ScopedDir::ScopedDir(std::string const & relativePath)
: m_fullPath(base::JoinPath(GetPlatform().WritableDir(), relativePath))
, m_relativePath(relativePath)
, m_reset(false)
{
Platform::EError ret = Platform::MkDir(GetFullPath());
switch (ret)
{
case Platform::ERR_OK: break;
case Platform::ERR_FILE_ALREADY_EXISTS:
Platform::EFileType type;
TEST_EQUAL(Platform::ERR_OK, Platform::GetFileType(GetFullPath(), type), ());
TEST_EQUAL(Platform::EFileType::Directory, type, ());
break;
default: TEST(false, ("Can't create directory:", GetFullPath(), "error:", ret)); break;
}
}
ScopedDir::ScopedDir(ScopedDir const & parent, std::string const & name)
: ScopedDir(base::JoinPath(parent.GetRelativePath(), name))
{}
ScopedDir::~ScopedDir()
{
if (m_reset)
return;
std::string const fullPath = GetFullPath();
Platform::EError ret = Platform::RmDir(fullPath);
switch (ret)
{
case Platform::ERR_OK: break;
case Platform::ERR_FILE_DOES_NOT_EXIST:
LOG(LERROR, (fullPath, "was deleted before destruction of ScopedDir."));
break;
case Platform::ERR_DIRECTORY_NOT_EMPTY: LOG(LERROR, ("There are files in", fullPath)); break;
default: LOG(LERROR, ("Platform::RmDir() error for", fullPath, ":", ret)); break;
}
}
std::string DebugPrint(ScopedDir const & dir)
{
std::ostringstream os;
os << "ScopedDir [" << dir.GetFullPath() << "]";
return os.str();
}
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,43 @@
#pragma once
#include "platform/platform.hpp"
#include "base/macros.hpp"
#include <string>
namespace platform
{
namespace tests_support
{
// Scoped test directory in a writable dir.
class ScopedDir
{
public:
/// Creates test dir in a writable directory.
/// @param path Path for a testing directory, should be relative to writable-dir.
ScopedDir(std::string const & relativePath);
ScopedDir(ScopedDir const & parent, std::string const & name);
~ScopedDir();
void Reset() { m_reset = true; }
std::string const & GetFullPath() const { return m_fullPath; }
std::string const & GetRelativePath() const { return m_relativePath; }
bool Exists() const { return GetPlatform().IsFileExistsByFullPath(GetFullPath()); }
private:
std::string const m_fullPath;
std::string const m_relativePath;
bool m_reset;
DISALLOW_COPY_AND_MOVE(ScopedDir);
};
std::string DebugPrint(ScopedDir const & dir);
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,73 @@
#include "platform/platform_tests_support/scoped_file.hpp"
#include "testing/testing.hpp"
#include "platform/country_file.hpp"
#include "platform/mwm_version.hpp"
#include "platform/platform_tests_support/scoped_dir.hpp"
#include "coding/file_writer.hpp"
#include "coding/internal/file_data.hpp"
#include "coding/writer.hpp"
#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include <sstream>
namespace platform
{
namespace tests_support
{
ScopedFile::ScopedFile(std::string const & relativePath, Mode mode) : ScopedFile(relativePath, {} /* contents */, mode)
{}
ScopedFile::ScopedFile(std::string const & relativePath, std::string const & contents)
: ScopedFile(relativePath, contents, Mode::Create)
{}
ScopedFile::ScopedFile(ScopedDir const & dir, CountryFile const & countryFile, MapFileType type)
: ScopedFile(base::JoinPath(dir.GetRelativePath(), countryFile.GetFileName(type)), Mode::Create)
{}
ScopedFile::ScopedFile(std::string const & relativePath, std::string const & contents, Mode mode)
: m_fullPath(base::JoinPath(GetPlatform().WritableDir(), relativePath))
{
if (mode == Mode::DoNotCreate)
return;
try
{
FileWriter writer(GetFullPath());
writer.Write(contents.data(), contents.size());
}
catch (Writer::Exception const & e)
{
LOG(LERROR, ("Can't create test file:", e.what()));
}
CHECK(Exists(), ("Can't create test file", GetFullPath()));
}
ScopedFile::~ScopedFile()
{
if (m_reset)
return;
if (!Exists())
{
LOG(LERROR, ("File", GetFullPath(), "did not exist or was deleted before dtor of ScopedFile."));
return;
}
if (!base::DeleteFileX(GetFullPath()))
LOG(LERROR, ("Can't remove test file:", GetFullPath()));
}
std::string DebugPrint(ScopedFile const & file)
{
std::ostringstream os;
os << "ScopedFile [" << file.GetFullPath() << "]";
return os.str();
}
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,60 @@
#pragma once
#include "platform/country_defines.hpp"
#include "platform/platform.hpp"
#include "base/macros.hpp"
#include <string>
namespace platform
{
class CountryFile;
namespace tests_support
{
class ScopedDir;
class ScopedFile
{
public:
enum class Mode : uint32_t
{
// Create or overwrite the file and remove it at scope exit.
Create,
// Remove the file at scope exit. The caller must
// ensure that the file has been created by that time.
DoNotCreate
};
// Creates a scoped file in the specified mode.
ScopedFile(std::string const & relativePath, Mode mode);
// Creates a scoped file in Mode::Create and writes |contents| to it.
ScopedFile(std::string const & relativePath, std::string const & contents);
// Creates a scoped file in Mode::Create using the path inferred from |countryFile|
// and |mapOptions|.
ScopedFile(ScopedDir const & dir, CountryFile const & countryFile, MapFileType type);
~ScopedFile();
std::string const & GetFullPath() const { return m_fullPath; }
void Reset() { m_reset = true; }
bool Exists() const { return GetPlatform().IsFileExistsByFullPath(GetFullPath()); }
private:
ScopedFile(std::string const & relativePath, std::string const & contents, Mode mode);
std::string const m_fullPath;
bool m_reset = false;
DISALLOW_COPY_AND_MOVE(ScopedFile);
};
std::string DebugPrint(ScopedFile const & file);
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,40 @@
#include "scoped_mwm.hpp"
#include "defines.hpp"
#include "indexer/data_header.hpp"
#include "indexer/feature_impl.hpp"
#include "platform/mwm_version.hpp"
#include "coding/file_writer.hpp"
#include "coding/files_container.hpp"
#include "base/timer.hpp"
namespace platform
{
namespace tests_support
{
ScopedMwm::ScopedMwm(std::string const & relativePath) : m_file(relativePath, ScopedFile::Mode::Create)
{
FilesContainerW container(m_file.GetFullPath());
// Each writer must be in it's own scope to avoid conflicts on the final write.
{
auto w = container.GetWriter(VERSION_FILE_TAG);
version::WriteVersion(*w, base::SecondsSinceEpoch());
}
using namespace feature;
DataHeader header;
header.SetScales(feature::g_arrCountryScales);
header.SetType(DataHeader::MapType::Country);
{
auto w = container.GetWriter(HEADER_FILE_TAG);
header.Save(*w);
}
}
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,28 @@
#pragma once
#include "platform/platform_tests_support/scoped_file.hpp"
#include "base/macros.hpp"
#include <string>
namespace platform
{
namespace tests_support
{
class ScopedFile;
class ScopedMwm
{
public:
explicit ScopedMwm(std::string const & relativePath);
std::string const & GetFullPath() const { return m_file.GetFullPath(); }
private:
ScopedFile m_file;
DISALLOW_COPY_AND_MOVE(ScopedMwm);
};
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,75 @@
#include "test_socket.hpp"
#include "base/assert.hpp"
#include <algorithm>
#include <chrono>
namespace platform
{
namespace tests_support
{
TestSocket::~TestSocket()
{
m_isConnected = false;
}
bool TestSocket::Open(std::string const & host, uint16_t port)
{
if (m_isConnected)
return false;
m_isConnected = true;
return true;
}
void TestSocket::Close()
{
m_isConnected = false;
}
bool TestSocket::Read(uint8_t * data, uint32_t count)
{
if (!m_isConnected)
return false;
std::unique_lock<std::mutex> lock(m_inputMutex);
m_inputCondition.wait_for(lock, std::chrono::milliseconds(m_timeoutMs), [this]() { return !m_input.empty(); });
if (m_input.size() < count)
return false;
std::copy(m_input.begin(), m_input.end(), data);
m_input.erase(m_input.begin(), m_input.begin() + count);
return true;
}
bool TestSocket::Write(uint8_t const * data, uint32_t count)
{
if (!m_isConnected)
return false;
{
std::lock_guard lg(m_outputMutex);
m_output.insert(m_output.end(), data, data + count);
}
m_outputCondition.notify_one();
return true;
}
void TestSocket::SetTimeout(uint32_t milliseconds)
{
m_timeoutMs = milliseconds;
}
size_t TestSocket::ReadServer(std::vector<uint8_t> & destination)
{
std::unique_lock lock(m_outputMutex);
m_outputCondition.wait_for(lock, std::chrono::milliseconds(m_timeoutMs), [this]() { return !m_output.empty(); });
size_t const outputSize = m_output.size();
destination.insert(destination.end(), m_output.begin(), m_output.end());
m_output.clear();
return outputSize;
}
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,54 @@
#pragma once
#include "platform/socket.hpp"
#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <deque>
#include <iterator>
#include <mutex>
#include <string>
#include <vector>
namespace platform
{
namespace tests_support
{
class TestSocket final : public Socket
{
public:
// Socket overrides:
~TestSocket();
bool Open(std::string const & host, uint16_t port) override;
void Close() override;
bool Read(uint8_t * data, uint32_t count) override;
bool Write(uint8_t const * data, uint32_t count) override;
void SetTimeout(uint32_t milliseconds) override;
// Simulates server reading.
// Waits for some data or timeout.
// Returns size of read data.
size_t ReadServer(std::vector<uint8_t> & destination);
template <typename Container>
void WriteServer(Container const & answer)
{
std::lock_guard<std::mutex> lg(m_inputMutex);
m_input.insert(m_input.begin(), std::begin(answer), std::end(answer));
m_inputCondition.notify_one();
}
private:
std::atomic<bool> m_isConnected = {false};
std::atomic<uint32_t> m_timeoutMs = {100};
std::deque<uint8_t> m_input;
std::mutex m_inputMutex;
std::condition_variable m_inputCondition;
std::vector<uint8_t> m_output;
std::mutex m_outputMutex;
std::condition_variable m_outputCondition;
};
} // namespace tests_support
} // namespace platform

View file

@ -0,0 +1,36 @@
#include "testing/testing.hpp"
#include "platform/platform_tests_support/writable_dir_changer.hpp"
#include "platform/platform.hpp"
#include "platform/settings.hpp"
#include "coding/internal/file_data.hpp"
#include "base/file_name_utils.hpp"
WritableDirChanger::WritableDirChanger(std::string const & testDir, SettingsDirPolicy settingsDirPolicy)
: m_writableDirBeforeTest(GetPlatform().WritableDir())
, m_testDirFullPath(m_writableDirBeforeTest + testDir)
, m_settingsDirPolicy(settingsDirPolicy)
{
Platform & platform = GetPlatform();
platform.RmDirRecursively(m_testDirFullPath);
TEST(!platform.IsFileExistsByFullPath(m_testDirFullPath), ());
TEST_EQUAL(Platform::ERR_OK, platform.MkDir(m_testDirFullPath), ());
platform.SetWritableDirForTests(m_testDirFullPath);
if (m_settingsDirPolicy == SettingsDirPolicy::UseWritableDir)
platform.SetSettingsDir(m_testDirFullPath);
settings::Clear();
}
WritableDirChanger::~WritableDirChanger()
{
settings::Clear();
Platform & platform = GetPlatform();
std::string const writableDirForTest = platform.WritableDir();
platform.SetWritableDirForTests(m_writableDirBeforeTest);
if (m_settingsDirPolicy == SettingsDirPolicy::UseWritableDir)
platform.SetSettingsDir(m_writableDirBeforeTest);
platform.RmDirRecursively(writableDirForTest);
}

View file

@ -0,0 +1,21 @@
#pragma once
#include <string>
class WritableDirChanger
{
public:
enum class SettingsDirPolicy
{
UseDefault,
UseWritableDir
};
WritableDirChanger(std::string const & testDir, SettingsDirPolicy settingsDirPolicy = SettingsDirPolicy::UseDefault);
~WritableDirChanger();
private:
std::string const m_writableDirBeforeTest;
std::string const m_testDirFullPath;
SettingsDirPolicy m_settingsDirPolicy;
};