Commit 4f2d576e authored by Patrick Chen's avatar Patrick Chen

refactor code: use report

parent bba0f3ca
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
"script": [ "script": [
{ {
"command": "GetGreetingMessage", "command": "GetGreetingMessage",
"expect": "Hello, Master!" "expect": "Hello, Master!",
"runs": ["GetName"],
"posts": []
} }
] ]
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <string> #include <string>
#include <unordered_set>
namespace xs { namespace test namespace xs { namespace test
...@@ -28,6 +29,8 @@ namespace xs { namespace test ...@@ -28,6 +29,8 @@ namespace xs { namespace test
public: public:
std::string name_; std::string name_;
nlohmann::json value_; nlohmann::json value_;
std::unordered_set<std::string> runs_;
std::unordered_set<std::string> posts_;
}; };
} } } }
......
...@@ -14,6 +14,14 @@ namespace xs { namespace test ...@@ -14,6 +14,14 @@ namespace xs { namespace test
{ {
class Tester final class Tester final
{ {
public:
struct Report
{
bool pass;
std::unordered_set<std::string> missedCommands;
std::unordered_set<std::string> missedEvents;
};
public: public:
Tester() = delete; Tester() = delete;
~Tester() noexcept = default; ~Tester() noexcept = default;
...@@ -33,12 +41,16 @@ namespace xs { namespace test ...@@ -33,12 +41,16 @@ namespace xs { namespace test
void onEvent(const std::string& name, const std::string& params) noexcept; void onEvent(const std::string& name, const std::string& params) noexcept;
void registerServices() noexcept; void registerServices() noexcept;
void resetCounters() noexcept;
Report createReport(const std::string& response, const Expectation& expectation) noexcept;
public: private:
Config config_; Config config_;
ExchangeServer server_; ExchangeServer server_;
std::unordered_map<std::string, const Service*> acceptCommands_; std::unordered_map<std::string, const Service*> acceptCommands_;
std::unordered_map<std::string, const Service*> acceptEvents_; std::unordered_map<std::string, const Service*> acceptEvents_;
std::unordered_map<std::string, unsigned> receivedCommandCount_;
std::unordered_map<std::string, unsigned> receivedEventCount_;
}; };
} } } }
......
#include "test/Expectation.h" #include "test/Expectation.h"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <stdexcept>
namespace xs { namespace test namespace xs { namespace test
{ {
Expectation::Expectation(const nlohmann::json& object) Expectation::Expectation(const nlohmann::json& object)
: Expectation(object["command"].get<std::string>(), object["expect"]) : Expectation(object["command"].get<std::string>(), object["expect"])
{ } {
if (object.count("runs")) {
for (const auto& element : object["runs"]) {
if (!element.is_string()) {
throw std::runtime_error("element in \"runs\" is not string");
}
runs_.emplace(element.get<std::string>());
}
}
if (object.count("posts")) {
for (const auto& element : object["posts"]) {
if (!element.is_string()) {
throw std::runtime_error("element in \"posts\" is not string");
}
posts_.emplace(element.get<std::string>());
}
}
}
bool Expectation::verify(const nlohmann::json& object) noexcept bool Expectation::verify(const nlohmann::json& object) noexcept
{ {
...@@ -17,6 +36,14 @@ namespace xs { namespace test ...@@ -17,6 +36,14 @@ namespace xs { namespace test
return false; return false;
} }
if (object.count("runs") && !object["runs"].is_array()) {
return false;
}
if (object.count("posts") && !object["posts"].is_array()) {
return false;
}
return ( return (
object["command"].is_string() object["command"].is_string()
&& ( && (
......
#include "test/Service.h" #include "test/Service.h"
#include "test/Tester.h" #include "test/Tester.h"
#include <boost/algorithm/string/join.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/range/adaptors.hpp> #include <boost/range/adaptors.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
...@@ -52,13 +53,54 @@ void Tester::registerServices() noexcept ...@@ -52,13 +53,54 @@ void Tester::registerServices() noexcept
} }
} }
void Tester::resetCounters() noexcept
{
receivedCommandCount_.clear();
receivedEventCount_.clear();
}
Tester::Report Tester::createReport(const std::string& response, const Expectation& expectation) noexcept
{
Report report;
if (expectation.value_.is_string()) {
report.pass = (response == expectation.value_.get<std::string>());
} else {
try {
report.pass = (nlohmann::json::parse(response) == expectation.value_);
} catch (...) {
}
}
if (!expectation.runs_.empty()) {
for (const auto& command : expectation.runs_) {
if (!receivedCommandCount_[command]) {
report.missedCommands.emplace(command);
report.pass = false;
}
}
}
if (!expectation.posts_.empty()) {
for (const auto& event : expectation.posts_) {
if (!receivedEventCount_[event]) {
report.missedEvents.emplace(event);
report.pass = false;
}
}
}
return report;
}
std::string Tester::onCommand(const std::string& name, const std::string& params) noexcept std::string Tester::onCommand(const std::string& name, const std::string& params) noexcept
{ {
const auto found = acceptCommands_.find(name); const auto found = acceptCommands_.find(name);
const auto* service = std::get<1>(*found); const auto* service = std::get<1>(*found);
const auto& response = service->response_; const auto& response = service->response_;
/// TODO: keep track the status receivedCommandCount_[name]++;
return detail::toString(response); return detail::toString(response);
} }
...@@ -68,32 +110,35 @@ void Tester::onEvent(const std::string& name, const std::string& params) noexcep ...@@ -68,32 +110,35 @@ void Tester::onEvent(const std::string& name, const std::string& params) noexcep
const auto* service = std::get<1>(*found); const auto* service = std::get<1>(*found);
const auto& response = service->response_; const auto& response = service->response_;
/// TODO: keep track the status receivedEventCount_[name]++;
} }
void Tester::run() noexcept void Tester::run() noexcept
{ {
for (const auto& e : config_.getExpectations()) { for (const auto& expectation : config_.getExpectations()) {
const auto& command = e.name_; resetCounters();
const auto& expect = e.value_;
const auto response = server_.runCmd(command, "");
bool asExpect = false;
if (expect.is_string()) {
asExpect = (response == expect.get<std::string>());
} else {
try {
asExpect = (nlohmann::json::parse(response) == expect);
} catch (...) {
} const auto response = server_.runCmd(expectation.name_, "");
const auto report = createReport(response, expectation);
if (report.pass) {
std::cout << "[PASS] run command: " << expectation.name_ << std::endl;
continue;
} }
if (asExpect) { std::cout << "[FAILED] run command: " << expectation.name_ << std::endl;
std::cout << "[PASS] run command: " << command << std::endl; if (report.missedCommands.empty() && report.missedEvents.empty()) {
std::cout << boost::format(R"([REASON] unexpected response: "%1%"(real) vs %2%(expect))")
% response % detail::toString(expectation.value_)
<< std::endl;
} else if (!report.missedCommands.empty()) {
std::cout << boost::format("[REASON] missed commands: [%1%]")
% boost::algorithm::join(report.missedCommands, ", ")
<< std::endl;
} else { } else {
std::cout << "[FAILED] run command: " << command << " with unexpected response: " std::cout << boost::format("[REASON] missed events: [%1%]")
<< "\"" << response << "\"(real) vs " << detail::toString(expect) << "(expect)" << std::endl; % boost::algorithm::join(report.missedEvents, ", ")
<< std::endl;
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment