Skip to content

Commit

Permalink
Refactored test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
IESE-T3 committed Jul 19, 2024
1 parent c7bde91 commit f38b67a
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 129 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,4 @@ cmake-build*
.idea
.cache
.env
scripts/
tests/tests_memspec/temp/*
!tests/tests_memspec/temp/.gitkeep
scripts/
68 changes: 46 additions & 22 deletions include/DRAMUtils/memspec/MemSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ NLOHMANN_JSONIFY_ALL_THINGS(MemSpecContainer, memspec)

namespace DRAMUtils {

namespace detail
{
struct keys
{
static constexpr char memSpec[] = "memspec";
};

};

/**
* @brief Parses Memspec from JSON data into a MemSpecVariant object.
*
Expand All @@ -108,16 +117,20 @@ namespace DRAMUtils {
* Defaults to "memspec" if not provided.
*
* @return An optional MemSpecVariant object if the JSON data was successfully parsed or std::nullopt otherwise.
*
* @throws std::exception if the JSON data cannot be parsed into a MemSpecVariant object
*/
std::optional<MemSpec::MemSpecVariant> parse_memspec_from_json(const json_t& json, const std::optional<std::string_view>& key = "memspec")
std::optional<MemSpec::MemSpecVariant> parse_memspec_from_json(const json_t& json, std::string_view key = detail::keys::memSpec)
{
MemSpec::MemSpecVariant result;
if (key && json.contains(*key) && result.from_json(json.at(*key)))
return result;
else if (result.from_json(json))
return result;
try
{
MemSpec::MemSpecVariant result;
if (!key.empty() && json.contains(key) && result.from_json(json.at(key)))
return result;
else if (result.from_json(json))
return result;
}
catch (std::exception&)
{
}

return std::nullopt;
}
Expand All @@ -131,12 +144,17 @@ std::optional<MemSpec::MemSpecVariant> parse_memspec_from_json(const json_t& jso
* Defaults to "memspec" if not provided.
*
* @return An optional MemSpecVariant object if the JSON data was successfully parsed or std::nullopt otherwise.
*
* @throws std::exception if the JSON data cannot be parsed into a MemSpecVariant object
*/
std::optional<MemSpec::MemSpecVariant> parse_Memspec_from_buffer(std::string_view buffer, const std::optional<std::string_view>& key = "memspec")
std::optional<MemSpec::MemSpecVariant> parse_Memspec_from_buffer(std::string_view buffer, std::string_view key = detail::keys::memSpec)
{
return parse_memspec_from_json(json_t::parse(buffer), key);
try
{
return parse_memspec_from_json(json_t::parse(buffer), key);
}
catch (std::exception&)
{
return std::nullopt;
}
}

/**
Expand All @@ -148,19 +166,25 @@ std::optional<MemSpec::MemSpecVariant> parse_Memspec_from_buffer(std::string_vie
* Defaults to "memspec" if not provided.
*
* @return An optional MemSpecVariant object if the JSON data was successfully parsed or std::nullopt otherwise.
*
* @throws std::exception if the JSON data cannot be parsed into a MemSpecVariant object
*/
std::optional<MemSpec::MemSpecVariant> parse_memspec_from_file(const std::filesystem::path &path, const std::optional<std::string_view>& key = "memspec")
std::optional<MemSpec::MemSpecVariant> parse_memspec_from_file(const std::filesystem::path &path, std::string_view key = detail::keys::memSpec)
{
if (!std::filesystem::exists(path))
return std::nullopt;

std::ifstream file(path);
if (!file.is_open())
try
{
if (!std::filesystem::exists(path))
return std::nullopt;

std::ifstream file(path);
if (!file.is_open())
return std::nullopt;

json_t json_obj = json_t::parse(file);
return parse_memspec_from_json(json_obj, key);
}
catch (std::exception&)
{
return std::nullopt;
json_t json_obj = json_t::parse(file);
return parse_memspec_from_json(json_obj, key);
}
}

} // namespace DRAMUtils
Expand Down
228 changes: 124 additions & 104 deletions tests/tests_memspec/base/test_base.cpp
Original file line number Diff line number Diff line change
@@ -1,48 +1,82 @@
#include <gtest/gtest.h>

#include <memory>
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <variant>
#include <utility>
#include <filesystem>
#include <sstream>

#include "DRAMUtils/util/json.h"
#include "DRAMUtils/memspec/MemSpec.h"
#include "DRAMUtils/memspec/standards/MemSpecDDR3.h"

using namespace DRAMUtils;

// TODO change Config::MemSpec namespace to MemSpec
class Memspec_Base_Test : public ::testing::Test {
const char* test_mem_spec = R"(
{
"memarchitecturespec": {
"burstLength": 0,
"dataRate": 0,
"nbrOfBanks": 0,
"nbrOfChannels": 0,
"nbrOfColumns": 0,
"nbrOfDevices": 0,
"nbrOfRows": 0,
"nbrOfRanks": 0,
"width": 0
},
"memoryId": "Test_DDR3",
"memoryType": "DDR3",
"memtimingspec": {
"ACTPDEN": 0,
"AL": 0,
"CCD": 0,
"CKE": 11,
"CKESR": 0,
"DQSCK": 0,
"FAW": 0,
"PRPDEN": 0,
"RAS": 0,
"RC": 0,
"RCD": 0,
"REFI": 0,
"REFPDEN": 0,
"RFC": 0,
"RL": 0,
"RP": 0,
"RRD": 0,
"RTP": 0,
"RTRS": 0,
"WL": 0,
"WR": 0,
"WTR": 0,
"XP": 0,
"XPDLL": 0,
"XS": 0,
"XSDLL": 0,
"tCK": 0.0
}
}
)";

class Memspec_Base_Test : public ::testing::Test
{
protected:
// Test variables
std::string_view path = TEST_RESOURCE_DIR "test.json";
MemSpec::MemSpecContainer writeContainer;
MemSpec::MemSpecContainer readContainer;
// Test data
MemSpec::MemSpecContainer test_container;

bool writeContainerToJsonFile()
// Test util functions
std::stringstream writeContainerToStream(const MemSpec::MemSpecContainer& container)
{
std::ofstream file(path.data());
if(!file.is_open())
return false;
json_t j = writeContainer;
file << j.dump(4);
file.close();
return true;
std::stringstream stream;
json_t j = container;
stream << j.dump(4);
return stream;
}

bool readContainerFromJsonFile()
MemSpec::MemSpecContainer readContainerFromStream(std::stringstream& stream)
{
std::ifstream file(path.data());
if(!file.is_open())
return false;
json_t j;
file >> j;
file.close();
readContainer = j;
return true;
stream >> j;

MemSpec::MemSpecContainer result = j;
return result;
}

MemSpec::MemSpecVariant createDummyMemSpec()
Expand All @@ -68,6 +102,7 @@ class Memspec_Base_Test : public ::testing::Test {

virtual void SetUp()
{
test_container.memspec = createDummyMemSpec();
}

virtual void TearDown()
Expand All @@ -77,80 +112,65 @@ class Memspec_Base_Test : public ::testing::Test {

TEST_F(Memspec_Base_Test, IDVariant)
{
writeContainer.memspec = createDummyMemSpec();
ASSERT_TRUE(writeContainerToJsonFile());
ASSERT_TRUE(readContainerFromJsonFile());
compareMemSpec(readContainer.memspec);
}
auto stream = writeContainerToStream(test_container);
auto out_container = readContainerFromStream(stream);
compareMemSpec(out_container.memspec);
};

TEST_F(Memspec_Base_Test, HelperFunctions)
TEST_F(Memspec_Base_Test, ParseMemSpec)
{
using namespace DRAMUtils::MemSpec;
std::optional<MemSpecVariant> variant_in;
MemSpecVariant variant_out;
json_t j_out, j_in;
std::ifstream file_in;
std::ofstream file_out;

// Write MemSpecContainer to file
writeContainer.memspec = createDummyMemSpec();
ASSERT_TRUE(writeContainerToJsonFile());

// Read from file
variant_in = parse_memspec_from_file(std::filesystem::path(path));
ASSERT_TRUE(variant_in.has_value());
compareMemSpec(*variant_in);

// Read from buffer
file_in = std::ifstream(path.data());
ASSERT_TRUE(file_in.is_open());
std::string buffer((std::istreambuf_iterator<char>(file_in)), std::istreambuf_iterator<char>());
variant_in = parse_Memspec_from_buffer(buffer);
ASSERT_TRUE(variant_in.has_value());
compareMemSpec(*variant_in);

// Read from json
file_in = std::ifstream(path.data());
ASSERT_TRUE(file_in.is_open());
j_in = json_t::parse(file_in);
variant_in = parse_memspec_from_json(j_in);
ASSERT_TRUE(variant_in.has_value());
compareMemSpec(*variant_in);

// Read from json with different key
variant_out = createDummyMemSpec();
file_out = std::ofstream(path.data());
ASSERT_TRUE(file_out.is_open());
j_out.clear();
j_out["test"] = variant_out;
file_out << j_out.dump(4);
file_out.close();
variant_in = parse_memspec_from_file(std::filesystem::path(path), "test");
// Get variant
ASSERT_TRUE(variant_in.has_value());
compareMemSpec(*variant_in);

// Read from json with no key (std::nullopt)
variant_out = createDummyMemSpec();
file_out = std::ofstream(path.data());
ASSERT_TRUE(file_out.is_open());
j_out.clear();
j_out = variant_out;
file_out << j_out.dump(4);
file_out.close();
variant_in = parse_memspec_from_file(std::filesystem::path(path), std::nullopt);
ASSERT_TRUE(variant_in.has_value());
compareMemSpec(*variant_in);

// Test exception with invalid json
variant_out = createDummyMemSpec();
file_out = std::ofstream(path.data());
ASSERT_TRUE(file_out.is_open());
j_out.clear();
j_out = variant_out;
// remove memarchitecturespec.nbrOfRows
j_out["memarchitecturespec"].erase("nbrOfRows");
file_out << j_out.dump(4);
file_out.close();
ASSERT_THROW(parse_memspec_from_file(std::filesystem::path(path), std::nullopt), json_t::out_of_range);
}
// Test data
json_t test_json = test_container;

// Parse from buffer
auto ok_spec = DRAMUtils::parse_Memspec_from_buffer(test_mem_spec);
ASSERT_TRUE(ok_spec);

// Parse from json
auto ok_spec_1 = DRAMUtils::parse_memspec_from_json(test_json);
auto ok_spec_2 = DRAMUtils::parse_memspec_from_json(test_json, "memspec");

ASSERT_TRUE(ok_spec_1);
compareMemSpec(*ok_spec_1);
ASSERT_TRUE(ok_spec_2);
compareMemSpec(*ok_spec_2);

// Test with different key
json_t test_diff_key_json;
test_diff_key_json["other_key"] = test_json["memspec"];

auto ok_spec_3 = DRAMUtils::parse_memspec_from_json(test_diff_key_json, "other_key");
compareMemSpec(*ok_spec_3);

// Parse memspec without container
auto spec_json = test_json["memspec"];

auto ok_spec_4 = DRAMUtils::parse_memspec_from_json(spec_json);
compareMemSpec(*ok_spec_4);
};

TEST_F(Memspec_Base_Test, ParseMemSpec_Invalid)
{
// Test data
json_t test_json = test_container;

// Parse from empty buffer
ASSERT_FALSE(DRAMUtils::parse_Memspec_from_buffer(""));

// Parse with wrong key
auto fail_spec_1 = DRAMUtils::parse_memspec_from_json(test_json, "MemSpeck");
ASSERT_FALSE(fail_spec_1);

// Parse with empty key
auto fail_spec_2 = DRAMUtils::parse_memspec_from_json(test_json, "");
ASSERT_FALSE(fail_spec_2);

// Test with invalid json
json_t invalid = {"test", 0};
ASSERT_FALSE(DRAMUtils::parse_memspec_from_json(invalid));

// Test with invalid memspec
json_t invalid_spec = test_container;
invalid_spec["memspec"]["memarchitecturespec"].erase("nbrOfRows");
ASSERT_FALSE(DRAMUtils::parse_memspec_from_json(invalid_spec));
}
Empty file removed tests/tests_memspec/temp/.gitkeep
Empty file.

0 comments on commit f38b67a

Please sign in to comment.