Merge pull request #1586 from Sonicadvance1/testharness_env

TestHarnessRunner: Wire up environment variable option setting
This commit is contained in:
Ryan Houdek authored and GitHub committed 2022-02-28 07:05:28 -08:00
commit 3ba2d6cfb4
3 files changed
+96 -2

No files matched your search

+24 -2
View File
@@ -148,7 +148,7 @@ def parse_json(json_text, output_file):
OptionRegData = {}
OptionMemoryRegions = {}
OptionMemoryData = {}
OptionEnvironmentVariables = {}
json_object = json.loads(json_text)
json_object = {k.upper(): v for k, v in json_object.items()}
@@ -242,6 +242,14 @@ def parse_json(json_text, output_file):
length, byte_data = parse_hexstring(data_val)
OptionMemoryData[int(data_key, 0)] = (length, byte_data)
if ("ENV" in json_object):
data = json_object["ENV"]
if not (type(data) is dict):
sys.exit("Environment variables value must be list of key:value pairs")
for data_key, data_val in data.items():
OptionEnvironmentVariables[data_key] = data_val
# If Match option wasn't touched then set it to the default
if (OptionMatch == Regs.REG_INVALID):
OptionMatch = Regs.REG_NONE
@@ -250,6 +258,7 @@ def parse_json(json_text, output_file):
memRegions = bytes()
regData = bytes()
memData = bytes()
envData = bytes()
# Write memory regions
for key, val in OptionMemoryRegions.items():
@@ -271,6 +280,13 @@ def parse_json(json_text, output_file):
for byte in data:
memData += struct.pack('B', byte)
# Write environment variables
for key, val in OptionEnvironmentVariables.items():
envData += key.encode()
envData += struct.pack('B', 0)
envData += val.encode()
envData += struct.pack('B', 0)
config_file = open(output_file, "wb")
config_file.write(struct.pack('Q', OptionMatch.value))
config_file.write(struct.pack('Q', OptionIgnore.value))
@@ -280,7 +296,7 @@ def parse_json(json_text, output_file):
config_file.write(struct.pack('I', OptionMode.value))
# Total length of header, including offsets/counts below
headerLength = (8 * 4) + (4 * 2) + (4 * 6)
headerLength = (8 * 4) + (4 * 2) + (4 * 8)
offset = headerLength
# memory regions offset/count
@@ -298,10 +314,16 @@ def parse_json(json_text, output_file):
config_file.write(struct.pack('I', len(OptionMemoryData)))
offset += len(memData)
# environment data offset/count
config_file.write(struct.pack('I', offset))
config_file.write(struct.pack('I', len(OptionEnvironmentVariables)))
offset += len(envData)
# write out the actual data for memory regions, reg data and memory data
config_file.write(memRegions)
config_file.write(regData)
config_file.write(memData)
config_file.write(envData)
config_file.close()
+20
View File
@@ -161,6 +161,21 @@ namespace FEX::HarnessHelper {
void Init(std::string const &ConfigFilename) {
ReadFile(ConfigFilename, &RawConfigFile);
memcpy(&BaseConfig, RawConfigFile.data(), sizeof(ConfigStructBase));
GetEnvironmentOptions();
}
std::vector<std::pair<std::string_view, std::string_view>> GetEnvironmentOptions() {
std::vector<std::pair<std::string_view, std::string_view>> Env{};
uintptr_t DataOffset = BaseConfig.OptionEnvOptionOffset;
for (unsigned i = 0; i < BaseConfig.OptionEnvOptionCount; ++i) {
// Environment variables are null terminated strings
std::string_view Key = RawConfigFile.data() + DataOffset;
std::string_view Value = RawConfigFile.data() + DataOffset + Key.size() + 1;
DataOffset += Key.size() + Value.size() + 2;
Env.emplace_back(Key, Value);
}
return Env;
}
bool CompareStates(FEXCore::Core::CPUState const* State1, FEXCore::Core::CPUState const* State2) {
@@ -316,6 +331,8 @@ namespace FEX::HarnessHelper {
uint32_t OptionRegDataCount;
uint32_t OptionMemDataOffset;
uint32_t OptionMemDataCount;
uint32_t OptionEnvOptionOffset;
uint32_t OptionEnvOptionCount;
uint8_t AdditionalData[];
} FEX_PACKED;
@@ -424,6 +441,9 @@ namespace FEX::HarnessHelper {
Config.LoadMemory();
}
std::vector<std::pair<std::string_view, std::string_view>> GetEnvironmentOptions() {
return Config.GetEnvironmentOptions();
}
bool CompareStates(FEXCore::Core::CPUState const* State1, FEXCore::Core::CPUState const* State2) {
return Config.CompareStates(State1, State2);
+52
View File
@@ -64,6 +64,53 @@ void AssertHandler(char const *Message) {
fmt::print("[ASSERT] {}\n", Message);
}
namespace {
static const std::vector<std::pair<const char*, FEXCore::Config::ConfigOption>> EnvConfigLookup = {{
#define OPT_BASE(type, group, enum, json, default) {"FEX_" #enum, FEXCore::Config::ConfigOption::CONFIG_##enum},
#include <FEXCore/Config/ConfigValues.inl>
}};
// Claims to be a local application config layer
class TestEnvLoader final : public FEXCore::Config::Layer {
public:
explicit TestEnvLoader(std::vector<std::pair<std::string_view, std::string_view>> _Env)
: FEXCore::Config::Layer(FEXCore::Config::LayerType::LAYER_LOCAL_APP)
, Env {std::move(_Env)} {
Load();
}
void Load() override {
std::unordered_map<std::string_view, std::string_view> EnvMap;
for (auto &Option : Env) {
std::string_view Key = Option.first;
std::string_view Value = Option.second;
#define ENVLOADER
#include <FEXCore/Config/ConfigOptions.inl>
EnvMap.insert_or_assign(Key, Value);
}
auto GetVar = [&](const std::string_view id) -> std::optional<std::string_view> {
const auto it = EnvMap.find(id);
if (it == EnvMap.end())
return std::nullopt;
return it->second;
};
for (auto &it : EnvConfigLookup) {
if (auto Value = GetVar(it.first); Value) {
Set(it.second, *Value);
}
}
}
private:
std::vector<std::pair<std::string_view, std::string_view>> Env;
};
}
int main(int argc, char **argv, char **const envp) {
LogMan::Throw::InstallHandler(AssertHandler);
LogMan::Msg::InstallHandler(MsgHandler);
@@ -80,6 +127,11 @@ int main(int argc, char **argv, char **const envp) {
}
FEX::HarnessHelper::HarnessCodeLoader Loader{Args[0], Args[1].c_str()};
// Adds in environment options from the test harness config
FEXCore::Config::AddLayer(std::make_unique<TestEnvLoader>(Loader.GetEnvironmentOptions()));
FEXCore::Config::ReloadMetaLayer();
FEXCore::Config::Set(FEXCore::Config::CONFIG_IS64BIT_MODE, Loader.Is64BitMode() ? "1" : "0");
FEXCore::Context::InitializeStaticTables(Loader.Is64BitMode() ? FEXCore::Context::MODE_64BIT : FEXCore::Context::MODE_32BIT);