tests: Added initial test structure

This commit is contained in:
WerWolv
2021-09-11 14:41:18 +02:00
parent 71b06f4b20
commit 8396e40fa0
11 changed files with 387 additions and 37 deletions

View File

@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.16)
project(tests)
# Add new tests here #
set(AVAILABLE_TESTS
Placement
)
add_executable(tests source/main.cpp )
target_include_directories(tests PRIVATE include)
target_link_libraries(tests libimhex)
set_target_properties(tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_command(TARGET tests
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/test_data" ${CMAKE_BINARY_DIR})
foreach (test IN LISTS AVAILABLE_TESTS)
add_test(NAME "${test}" COMMAND tests "${test}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
endforeach ()

View File

@@ -1,8 +1,39 @@
//
// Created by werwo on 11/09/2021.
//
#pragma once
#ifndef IMHEX_TEST_PATTERN_HPP
#define IMHEX_TEST_PATTERN_HPP
#include <string>
#include <vector>
#endif //IMHEX_TEST_PATTERN_HPP
#include <hex/pattern_language/pattern_data.hpp>
namespace hex::test {
class TestPattern {
public:
TestPattern() = default;
virtual ~TestPattern() {
for (auto &pattern : this->m_patterns)
delete pattern;
}
template<typename T>
static T* createVariablePattern(u64 offset, size_t size, const std::string &typeName, const std::string &varName) {
auto pattern = new T(offset, size);
pattern->setTypeName(typeName);
pattern->setVariableName(varName);
return pattern;
}
virtual std::string getSourceCode() const = 0;
[[nodiscard]]
virtual const std::vector<pl::PatternData*>& getPatterns() const final { return this->m_patterns; }
virtual void addPattern(pl::PatternData *pattern) final {
this->m_patterns.push_back(pattern);
}
private:
std::vector<pl::PatternData*> m_patterns;
};
}

View File

@@ -1,30 +1,23 @@
#pragma once
#include <string>
#include <vector>
#include <hex/pattern_language/pattern_data.hpp>
#include "test_pattern.hpp"
namespace hex::test {
class TestPattern {
class TestPatternExample : public TestPattern {
public:
TestPattern() = default;
virtual TestPattern() {
for (auto &pattern : this->m_patterns)
delete pattern;
}
TestPatternExample() {
virtual std::string getSourceCode() = 0;
}
~TestPatternExample() override = default;
[[nodiscard]]
virtual const std::vector<pl::PatternData*>& getPatterns() const final { return this->m_patterns; }
virtual void addPattern(pl::PatternData *pattern) final {
this->m_patterns.push_back(pattern);
std::string getSourceCode() const override {
return R"(
)";
}
private:
std::vector<pl::PatternData*> m_patterns;
};
}

View File

@@ -4,20 +4,29 @@
namespace hex::test {
class TestPatternExample : public TestPattern {
class TestPatternPlacement : public TestPattern {
public:
TestPatternExample() {
auto placementTest = new pl::PatternDataSigned(0x00, sizeof(u32));
placementTest->setTypeName("u32");
placementTest->setVariableName("placementTest");
addPattern(placementTest);
TestPatternPlacement() {
// placementVar
{
addPattern(createVariablePattern<pl::PatternDataUnsigned>(0x00, sizeof(u32), "u32", "placementVar"));
}
// placementArray
{
auto placementArray = createVariablePattern<pl::PatternDataStaticArray>(0x10, sizeof(u8) * 10, "u8", "placementArray");
placementArray->setEntries(createVariablePattern<pl::PatternDataUnsigned>(0x10, sizeof(u8), "u8", ""), 10);
addPattern(placementArray);
}
}
~TestPatternExample() override = default;
~TestPatternPlacement() override = default;
[[nodiscard]]
std::string getSourceCode() const override {
return R"(
u32 placementTest @ 0x00;
u32 placementVar @ 0x00;
u8 placementArray[10] @ 0x10;
)";
}

View File

@@ -1,8 +1,49 @@
//
// Created by werwo on 11/09/2021.
//
#include <hex/providers/provider.hpp>
#ifndef IMHEX_TEST_PROVIDER_HPP
#define IMHEX_TEST_PROVIDER_HPP
#include <hex/helpers/file.hpp>
#include <hex/helpers/logger.hpp>
#include <stdexcept>
#endif //IMHEX_TEST_PROVIDER_HPP
namespace hex::test {
using namespace hex::prv;
class TestProvider : public prv::Provider {
public:
TestProvider() : Provider() {
this->m_testFile = File("test_data", File::Mode::Read);
if (!this->m_testFile.isValid()) {
hex::log::fatal("Failed to open test data!");
throw std::runtime_error("");
}
}
~TestProvider() override = default;
bool isAvailable() override { return true; }
bool isReadable() override { return true; }
bool isWritable() override { return false; }
bool isResizable() override { return false; }
bool isSavable() override { return false; }
std::vector<std::pair<std::string, std::string>> getDataInformation() override {
return { };
}
void readRaw(u64 offset, void *buffer, size_t size) override {
this->m_testFile.seek(offset);
this->m_testFile.readBuffer(static_cast<u8*>(buffer), size);
}
void writeRaw(u64 offset, const void *buffer, size_t size) override {
this->m_testFile.seek(offset);
this->m_testFile.write(static_cast<const u8*>(buffer), size);
}
size_t getActualSize() override {
return m_testFile.getSize();
}
private:
File m_testFile;
};
}

View File

@@ -1 +1,83 @@
#include <catch.hpp>
#include <map>
#include <string>
#include <cstdlib>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/pattern_language/pattern_language.hpp>
#include "test_provider.hpp"
#include "test_patterns/test_pattern_placement.hpp"
using namespace hex::test;
static std::map<std::string, TestPattern*> testPatterns {
{ "Placement", new TestPatternPlacement() }
};
int main(int argc, char **argv) {
ON_SCOPE_EXIT {
for (auto &[key, value] : testPatterns)
delete value;
};
// Check if a test to run has been provided
if (argc != 2) {
hex::log::fatal("Invalid number of arguments specified! {}", argc);
return EXIT_FAILURE;
}
// Check if that test exists
std::string testName = argv[1];
if (!testPatterns.contains(testName)) {
hex::log::fatal("No test with name {} found!", testName);
return EXIT_FAILURE;
}
const auto &currTest = testPatterns[testName];
auto provider = new TestProvider();
ON_SCOPE_EXIT { delete provider; };
if (provider->getActualSize() == 0) {
hex::log::fatal("Failed to load Testing Data");
return EXIT_FAILURE;
}
hex::pl::PatternLanguage language;
// Check if compilation succeeded
auto patterns = language.executeString(provider, testPatterns[testName]->getSourceCode());
if (!patterns.has_value()) {
hex::log::fatal("Error during compilation!");
for (auto &[level, line] : language.getConsoleLog())
hex::log::info("PL: {}", line);
return EXIT_FAILURE;
}
ON_SCOPE_EXIT {
for (auto &pattern : *patterns)
delete pattern;
};
// Check if the right number of patterns have been produced
if (patterns->size() != currTest->getPatterns().size()) {
hex::log::fatal("Source didn't produce expected number of patterns");
return EXIT_FAILURE;
}
// Check if the produced patterns are the ones expected
for (u32 i = 0; i < patterns->size(); i++) {
auto &left = *patterns->at(i);
auto &right = *currTest->getPatterns().at(i);
if (left != right) {
hex::log::fatal("Pattern with name {}:{} didn't match template", patterns->at(i)->getTypeName(), patterns->at(i)->getVariableName());
return EXIT_FAILURE;
}
}
hex::log::info("Success!");
return EXIT_SUCCESS;
}

BIN
tests/test_data Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB