Skip to content

Commit

Permalink
Refactor: inject mockable RawIOManipulator in TestCaseDriver
Browse files Browse the repository at this point in the history
  • Loading branch information
fushar committed Sep 12, 2017
1 parent fc0ee3f commit 4bd9dc5
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 33 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ include_directories(include)
set(INCLUDE
include/tcframe/driver.hpp
include/tcframe/driver/Driver.hpp
include/tcframe/driver/RawIOManipulator.hpp
include/tcframe/driver/SlugParser.hpp
include/tcframe/driver/SpecDriver.hpp
include/tcframe/driver/TestCaseDriver.hpp
Expand Down Expand Up @@ -166,6 +167,7 @@ set(INCLUDE

set(TEST_UNIT
test/unit/tcframe/driver/MockDriver.hpp
test/unit/tcframe/driver/MockRawIOManipulator.hpp
test/unit/tcframe/driver/MockSpecDriver.hpp
test/unit/tcframe/driver/MockTestCaseDriver.hpp
test/unit/tcframe/driver/SpecDriverTests.cpp
Expand Down
1 change: 1 addition & 0 deletions include/tcframe/driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

#include "tcframe/driver/Driver.hpp"
#include "tcframe/driver/SlugParser.hpp"
#include "tcframe/driver/RawIOManipulator.hpp"
#include "tcframe/driver/SpecDriver.hpp"
#include "tcframe/driver/TestCaseDriver.hpp"
1 change: 1 addition & 0 deletions include/tcframe/driver/Driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class Driver {
MultipleTestCasesConfig multipleTestCasesConfig = testSpec_->TProblemSpec::buildMultipleTestCasesConfig();

auto testCaseDriver = new TestCaseDriver(
new RawIOManipulator(),
new IOManipulator(ioFormat),
new Verifier(constraintSuite),
multipleTestCasesConfig);
Expand Down
25 changes: 25 additions & 0 deletions include/tcframe/driver/RawIOManipulator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <ostream>
#include <string>

using std::endl;
using std::ostream;
using std::string;

namespace tcframe {

class RawIOManipulator {
public:
virtual ~RawIOManipulator() {}

virtual void print(ostream* out, const string& data) {
*out << data;
}

virtual void printLine(ostream* out, const string& data) {
*out << data << endl;
}
};

}
12 changes: 8 additions & 4 deletions include/tcframe/driver/TestCaseDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <stdexcept>
#include <string>

#include "RawIOManipulator.hpp"
#include "tcframe/spec/config.hpp"
#include "tcframe/spec/exception.hpp"
#include "tcframe/spec/io.hpp"
Expand All @@ -22,6 +23,7 @@ namespace tcframe {

class TestCaseDriver {
private:
RawIOManipulator* rawIOManipulator_;
IOManipulator* ioManipulator_;
Verifier* verifier_;
MultipleTestCasesConfig multipleTestCasesConfig_;
Expand All @@ -30,10 +32,12 @@ class TestCaseDriver {
virtual ~TestCaseDriver() {}

TestCaseDriver(
RawIOManipulator* rawIOManipulator,
IOManipulator* ioManipulator,
Verifier* verifier,
const MultipleTestCasesConfig& multipleTestCasesConfig)
: ioManipulator_(ioManipulator)
, rawIOManipulator_(rawIOManipulator)
, verifier_(verifier)
, multipleTestCasesConfig_(multipleTestCasesConfig) {}

Expand Down Expand Up @@ -83,12 +87,12 @@ class TestCaseDriver {
void writeInput(const TestCase& testCase, ostream* out) {
if (multipleTestCasesConfig_.counter()) {
int testCaseId = 1;
*out << testCaseId << endl;
rawIOManipulator_->printLine(out, StringUtils::toString(testCaseId));
}

if (testCase.data()->type() == TestCaseDataType::SAMPLE) {
auto data = (SampleTestCaseData*) testCase.data();
*out << data->input();
rawIOManipulator_->print(out, data->input());
} else {
ioManipulator_->printInput(out);
}
Expand All @@ -103,11 +107,11 @@ class TestCaseDriver {
void writeSampleOutput(const TestCase& testCase, ostream* out) {
if (multipleTestCasesConfig_.counter() && multipleTestCasesConfig_.outputPrefix()) {
string firstOutputPrefix = StringUtils::interpolate(multipleTestCasesConfig_.outputPrefix().value(), 1);
*out << firstOutputPrefix;
rawIOManipulator_->print(out, firstOutputPrefix);
}

auto data = (SampleTestCaseData*) testCase.data();
*out << data->output().value();
rawIOManipulator_->print(out, data->output().value());
}

void applyOutput(istream* in) {
Expand Down
15 changes: 15 additions & 0 deletions test/unit/tcframe/driver/MockRawIOManipulator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include "gmock/gmock.h"

#include "tcframe/driver/RawIOManipulator.hpp"

namespace tcframe {

class MockRawIOManipulator : public RawIOManipulator {
public:
MOCK_METHOD2(print, void(ostream*, const string&));
MOCK_METHOD2(printLine, void(ostream*, const string&));
};

}
2 changes: 1 addition & 1 deletion test/unit/tcframe/driver/MockTestCaseDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace tcframe {
class MockTestCaseDriver : public TestCaseDriver {
public:
MockTestCaseDriver()
: TestCaseDriver(nullptr, nullptr, MultipleTestCasesConfig()) {}
: TestCaseDriver(nullptr, nullptr, nullptr, MultipleTestCasesConfig()) {}

MOCK_METHOD2(generateInput, void(const TestCase&, ostream*));
MOCK_METHOD2(generateSampleOutput, void(const TestCase&, ostream*));
Expand Down
63 changes: 35 additions & 28 deletions test/unit/tcframe/driver/TestCaseDriverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <sstream>
#include <streambuf>

#include "MockRawIOManipulator.hpp"
#include "../spec/io/MockIOManipulator.hpp"
#include "../spec/verifier/MockVerifier.hpp"
#include "tcframe/driver/TestCaseDriver.hpp"
Expand All @@ -28,6 +29,7 @@ class TestCaseDriverTests : public Test {
static int N;

protected:
MOCK(RawIOManipulator) rawIOManipulator;
MOCK(IOManipulator) ioManipulator;
MOCK(Verifier) verifier;

Expand All @@ -50,12 +52,14 @@ class TestCaseDriverTests : public Test {
.OutputPrefix("Case #%d: ")
.build();

ostream* out = new ostringstream();

TestCaseDriver driver = createDriver(MultipleTestCasesConfig());
TestCaseDriver driverWithMultipleTestCases = createDriver(multipleTestCasesConfig);
TestCaseDriver driverWithMultipleTestCasesWithOutputPrefix = createDriver(multipleTestCasesConfigWithOutputPrefix);

TestCaseDriver createDriver(const MultipleTestCasesConfig& multipleTestCasesConfig) {
return {&ioManipulator, &verifier, multipleTestCasesConfig};
return {&rawIOManipulator, &ioManipulator, &verifier, multipleTestCasesConfig};
}

void SetUp() {
Expand All @@ -81,46 +85,45 @@ int TestCaseDriverTests::T;
int TestCaseDriverTests::N;

TEST_F(TestCaseDriverTests, GenerateInput_Sample) {
ostringstream out;
{
InSequence sequence;
EXPECT_CALL(ioManipulator, parseInput(Truly(InputStreamContentIs("42\n"))));
EXPECT_CALL(verifier, verifyConstraints(set<int>{1, 2}));
EXPECT_CALL(rawIOManipulator, print(out, "42\n"));
}
driver.generateInput(sampleTestCase, &out);
EXPECT_THAT(out.str(), Eq("42\n"));
driver.generateInput(sampleTestCase, out);
}

TEST_F(TestCaseDriverTests, GenerateInput_Official) {
ostringstream out;
{
InSequence sequence;
EXPECT_CALL(verifier, verifyConstraints(set<int>{1, 2}));
EXPECT_CALL(ioManipulator, printInput(&out));
EXPECT_CALL(ioManipulator, printInput(out));
}
N = 0;
driver.generateInput(officialTestCase, &out);
driver.generateInput(officialTestCase, out);
EXPECT_THAT(N, Eq(42));
}

TEST_F(TestCaseDriverTests, GenerateInput_Failed_Verification) {
ConstraintsVerificationResult failedResult({}, {1});
ON_CALL(verifier, verifyConstraints(_))
.WillByDefault(Return(failedResult));
ostringstream out;
try {
driver.generateInput(officialTestCase, &out);
driver.generateInput(officialTestCase, out);
FAIL();
} catch (FormattedError& e) {
EXPECT_THAT(e, Eq(failedResult.asFormattedError()));
}
}

TEST_F(TestCaseDriverTests, GenerateSampleOutput) {
ostringstream out;
EXPECT_CALL(ioManipulator, parseOutput(Truly(InputStreamContentIs("yes\n"))));
driver.generateSampleOutput(sampleTestCase, &out);
EXPECT_THAT(out.str(), Eq("yes\n"));
{
InSequence sequence;
EXPECT_CALL(ioManipulator, parseOutput(Truly(InputStreamContentIs("yes\n"))));
EXPECT_CALL(rawIOManipulator, print(out, "yes\n"));
}
driver.generateSampleOutput(sampleTestCase, out);
}

TEST_F(TestCaseDriverTests, ValidateOutput) {
Expand All @@ -130,34 +133,35 @@ TEST_F(TestCaseDriverTests, ValidateOutput) {
}

TEST_F(TestCaseDriverTests, GenerateInput_MultipleTestCases_Sample) {
ostringstream out;
{
InSequence sequence;
EXPECT_CALL(ioManipulator, parseInput(Truly(InputStreamContentIs("42\n"))));
EXPECT_CALL(verifier, verifyConstraints(set<int>{1, 2}));
EXPECT_CALL(rawIOManipulator, printLine(out, "1"));
EXPECT_CALL(rawIOManipulator, print(out, "42\n"));
}
driverWithMultipleTestCases.generateInput(sampleTestCase, &out);
EXPECT_THAT(out.str(), Eq("1\n42\n"));
driverWithMultipleTestCases.generateInput(sampleTestCase, out);
}

TEST_F(TestCaseDriverTests, GenerateInput_MultipleTestCases_Official) {
ostringstream out;
{
InSequence sequence;
EXPECT_CALL(verifier, verifyConstraints(set<int>{1, 2}));
EXPECT_CALL(ioManipulator, printInput(&out));
EXPECT_CALL(rawIOManipulator, printLine(out, "1"));
EXPECT_CALL(ioManipulator, printInput(out));
}
N = 0;
driverWithMultipleTestCases.generateInput(officialTestCase, &out);
driverWithMultipleTestCases.generateInput(officialTestCase, out);
EXPECT_THAT(N, Eq(42));
EXPECT_THAT(out.str(), Eq("1\n"));
}

TEST_F(TestCaseDriverTests, GenerateSampleOutput_MultipleTestCases) {
ostringstream out;
EXPECT_CALL(ioManipulator, parseOutput(Truly(InputStreamContentIs("yes\n"))));
driverWithMultipleTestCases.generateSampleOutput(sampleTestCase, &out);
EXPECT_THAT(out.str(), Eq("yes\n"));
{
InSequence sequence;
EXPECT_CALL(ioManipulator, parseOutput(Truly(InputStreamContentIs("yes\n"))));
EXPECT_CALL(rawIOManipulator, print(out, "yes\n"));
}
driverWithMultipleTestCases.generateSampleOutput(sampleTestCase, out);
}

TEST_F(TestCaseDriverTests, ValidateOutput_MultipleTestCases) {
Expand All @@ -167,10 +171,13 @@ TEST_F(TestCaseDriverTests, ValidateOutput_MultipleTestCases) {
}

TEST_F(TestCaseDriverTests, GenerateSampleOutput_MultipleTestCases_WithOutputPrefix) {
ostringstream out;
EXPECT_CALL(ioManipulator, parseOutput(Truly(InputStreamContentIs("yes\n"))));
driverWithMultipleTestCasesWithOutputPrefix.generateSampleOutput(sampleTestCase, &out);
EXPECT_THAT(out.str(), Eq("Case #1: yes\n"));
{
InSequence sequence;
EXPECT_CALL(ioManipulator, parseOutput(Truly(InputStreamContentIs("yes\n"))));
EXPECT_CALL(rawIOManipulator, print(out, "Case #1: "));
EXPECT_CALL(rawIOManipulator, print(out, "yes\n"));
}
driverWithMultipleTestCasesWithOutputPrefix.generateSampleOutput(sampleTestCase, out);
}

TEST_F(TestCaseDriverTests, ValidateOutput_MultipleTestCases_WithOutputPrefix) {
Expand Down

0 comments on commit 4bd9dc5

Please sign in to comment.