CS144Lab/tests/tcp_expectation_forward.hh
2021-09-28 17:03:04 -07:00

92 lines
3.4 KiB
C++

#ifndef SPONGE_LIBSPONGE_TCP_EXPECTATION_FORWARD_HH
#define SPONGE_LIBSPONGE_TCP_EXPECTATION_FORWARD_HH
#include "tcp_segment.hh"
#include "tcp_state.hh"
#include <cstdint>
#include <exception>
#include <optional>
#include <sstream>
class TCPTestHarness;
struct TCPTestStep {
public:
virtual ~TCPTestStep() {}
virtual std::string to_string() const { return "TestStep"; }
virtual void execute(TCPTestHarness &) const {}
virtual TCPSegment expect_seg(TCPTestHarness &) const { throw std::runtime_error("unimplemented"); }
};
struct TCPExpectation;
struct ExpectNoSegment;
struct ExpectState;
struct ExpectNotInState;
struct ExpectOneSegment;
struct ExpectSegment;
struct ExpectData;
struct ExpectNoData;
struct ExpectSegmentAvailable;
struct ExpectBytesInFlight;
struct ExpectUnassembledBytes;
struct ExpectWaitTimer;
struct SendSegment;
struct Write;
struct Tick;
struct Connect;
struct Listen;
struct Close;
class TCPExpectationViolation : public std::runtime_error {
public:
TCPExpectationViolation(const std::string msg) : std::runtime_error(msg) {}
};
class TCPPropertyViolation : public TCPExpectationViolation {
public:
TCPPropertyViolation(const std::string &msg) : TCPExpectationViolation(msg) {}
template <typename T>
static TCPPropertyViolation make(const std::string &property_name, const T &expected_value, const T &actual_value) {
std::stringstream ss{};
ss << "The TCP has `" << property_name << " = " << actual_value << "`, but " << property_name
<< " was expected to be `" << expected_value << "`";
return TCPPropertyViolation{ss.str()};
}
template <typename T>
static TCPPropertyViolation make_not(const std::string &property_name, const T &expected_non_value) {
std::stringstream ss{};
ss << "The TCP has `" << property_name << " = " << expected_non_value << "`, but " << property_name
<< " was expected to **not** be `" << expected_non_value << "`";
return TCPPropertyViolation{ss.str()};
}
};
class SegmentExpectationViolation : public TCPExpectationViolation {
public:
SegmentExpectationViolation(const std::string &msg) : TCPExpectationViolation(msg) {}
static SegmentExpectationViolation violated_verb(const std::string &msg) {
return SegmentExpectationViolation{"The TCP should have produced a segment that " + msg + ", but it did not"};
}
template <typename T>
static SegmentExpectationViolation violated_field(const std::string &field_name,
const T &expected_value,
const T &actual_value) {
std::stringstream ss{};
ss << "The TCP produced a segment with `" << field_name << " = " << actual_value << "`, but " << field_name
<< " was expected to be `" << expected_value << "`";
return SegmentExpectationViolation{ss.str()};
}
};
class StateExpectationViolation : public TCPExpectationViolation {
public:
StateExpectationViolation(const std::string &msg) : TCPExpectationViolation(msg) {}
StateExpectationViolation(const TCPState &expected_state, const TCPState &actual_state)
: TCPExpectationViolation("The TCP was in state `" + actual_state.name() +
"`, but it was expected to be in state `" + expected_state.name() + "`") {}
};
#endif // SPONGE_LIBSPONGE_TCP_EXPECTATION_FORWARD_HH