1 parent
ebf8ff7869
commit
41599fa82f
67 files changed
+8775
-4
No files matched your search
@@ -0,0 +1,137 @@
|
||||
// Подставная «java» для тестов. Без Qt, чтобы её копию можно было положить
|
||||
// в любую папку и запустить без поиска библиотек Qt.
|
||||
//
|
||||
// Поведение задаётся файлом fake-java.cfg рядом с исполняемым файлом,
|
||||
// по строке «ключ=значение»:
|
||||
// version=21.0.2 что печатать на «-version» (в stderr, как настоящая java)
|
||||
// exit=0 код выхода обычного запуска
|
||||
// sleep_ms=0 сколько «работать» перед выходом
|
||||
// args_file=<путь> куда записать аргументы, по одному на строку
|
||||
// dump_env=<ИМЯ> дописать в args_file строку «env:ИМЯ=значение» (можно несколько)
|
||||
// stdout=<строка> что напечатать в stdout (можно несколько)
|
||||
// create=<путь>\t<текст> создать файл с текстом; относительный путь — от рабочей папки
|
||||
// crash=1 завершиться аварийно (abort)
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace {
|
||||
|
||||
fs::path executablePath(const char *argv0)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
wchar_t buffer[MAX_PATH * 4];
|
||||
const DWORD size = GetModuleFileNameW(nullptr, buffer, DWORD(std::size(buffer)));
|
||||
return fs::path(std::wstring(buffer, size));
|
||||
#elif defined(__APPLE__)
|
||||
char buffer[4096];
|
||||
uint32_t size = sizeof(buffer);
|
||||
if (_NSGetExecutablePath(buffer, &size) == 0)
|
||||
return fs::canonical(buffer);
|
||||
return fs::absolute(argv0);
|
||||
#else
|
||||
std::error_code ec;
|
||||
const fs::path self = fs::read_symlink("/proc/self/exe", ec);
|
||||
return ec ? fs::absolute(argv0) : self;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::string version = "17.0.8";
|
||||
int exitCode = 0;
|
||||
int sleepMs = 0;
|
||||
bool crash = false;
|
||||
std::string argsFile;
|
||||
std::vector<std::string> dumpEnv;
|
||||
std::vector<std::string> stdoutLines;
|
||||
std::vector<std::pair<std::string, std::string>> creates;
|
||||
|
||||
std::ifstream config(executablePath(argv[0]).parent_path() / "fake-java.cfg");
|
||||
for (std::string line; std::getline(config, line);) {
|
||||
if (!line.empty() && line.back() == '\r')
|
||||
line.pop_back();
|
||||
const auto eq = line.find('=');
|
||||
if (eq == std::string::npos)
|
||||
continue;
|
||||
const std::string key = line.substr(0, eq);
|
||||
const std::string value = line.substr(eq + 1);
|
||||
if (key == "version")
|
||||
version = value;
|
||||
else if (key == "exit")
|
||||
exitCode = std::atoi(value.c_str());
|
||||
else if (key == "sleep_ms")
|
||||
sleepMs = std::atoi(value.c_str());
|
||||
else if (key == "crash")
|
||||
crash = value == "1";
|
||||
else if (key == "args_file")
|
||||
argsFile = value;
|
||||
else if (key == "dump_env")
|
||||
dumpEnv.push_back(value);
|
||||
else if (key == "stdout")
|
||||
stdoutLines.push_back(value);
|
||||
else if (key == "create") {
|
||||
const auto tab = value.find('\t');
|
||||
creates.emplace_back(value.substr(0, tab),
|
||||
tab == std::string::npos ? std::string() : value.substr(tab + 1));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (std::string(argv[i]) == "-version") {
|
||||
std::cerr << "openjdk version \"" << version << "\" 2024-01-16\n"
|
||||
<< "OpenJDK Runtime Environment (fake)\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!argsFile.empty()) {
|
||||
std::ofstream out(argsFile, std::ios::trunc);
|
||||
for (int i = 1; i < argc; ++i)
|
||||
out << argv[i] << '\n';
|
||||
for (const std::string &name : dumpEnv) {
|
||||
const char *value = std::getenv(name.c_str());
|
||||
out << "env:" << name << '=' << (value ? value : "") << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &[path, text] : creates) {
|
||||
const fs::path target(path);
|
||||
std::error_code ec;
|
||||
if (target.has_parent_path())
|
||||
fs::create_directories(target.parent_path(), ec);
|
||||
std::ofstream(target, std::ios::trunc | std::ios::binary) << text;
|
||||
}
|
||||
|
||||
for (const std::string &line : stdoutLines)
|
||||
std::cout << line << '\n';
|
||||
std::cout.flush();
|
||||
|
||||
if (sleepMs > 0)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepMs));
|
||||
if (crash) {
|
||||
#if defined(_WIN32)
|
||||
// QProcess считает аварией коды 0x8xxxxxxx–0xCxxxxxxx; abort() дал бы код 3.
|
||||
TerminateProcess(GetCurrentProcess(), 0xC0000005);
|
||||
#endif
|
||||
std::abort();
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
Reference in new issue
Block a user