blob: efe29e70cf84b18f98847d9946a8fe06b6b1a9b7 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#include "utility/textbased_test/TextBasedTestDriver.hpp"
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include "utility/Macros.hpp"
#include "utility/textbased_test/TextBasedTest.hpp"
#include "glog/logging.h"
#include "gtest/gtest.h"
#define EXPECT_TEXT_CASE(test_case, \
comments_and_options_text, \
option_set, \
test_input_text, \
expected_test_output_text) \
EXPECT_EQ(comments_and_options_text, (test_case)->preceding_text); \
EXPECT_EQ(test_input_text, (test_case)->input_text); \
EXPECT_EQ(expected_test_output_text, (test_case)->expected_output_text); \
EXPECT_EQ(option_set, (test_case)->options)
namespace quickstep {
class TextBasedTestDriverTest : public ::testing::Test {
protected:
TextBasedTestDriverTest()
: preregistered_options_{"option1", "option2", "option3", "option4", "option5", "option6", "option7", "option8",
"option9", "option10"} {
}
/**
* @brief Resets the test driver with the text stored
* in \p string_stream and gets test cases.
*
* @param string_stream The stream where to extract the test cases.
* @return A vector of TextBasedTestCases from the input stream.
*/
std::vector<TextBasedTestCase*>* extractTestCasesFromStream(const std::ostringstream &string_stream) {
std::istringstream input_stream(string_stream.str());
test_driver_.reset(new TextBasedTestDriver(&input_stream, nullptr /* test_runner */));
test_driver_->registerOptions(preregistered_options_);
return test_driver_->populateAndReturnTestCases();
}
std::unique_ptr<TextBasedTestDriver> test_driver_;
// Pre-registered options.
const std::vector<std::string> preregistered_options_;
private:
DISALLOW_COPY_AND_ASSIGN(TextBasedTestDriverTest);
};
TEST_F(TextBasedTestDriverTest, SingleTestCase) {
const std::string comments_and_options =
"\n# Comment line 1\n\n"
"# Comment line 2\r\n\n"
"[option1 option2]\n"
"[ option3 option4 option3 ]\n"
"[default option5]\n";
const std::string test_input_txt =
"input line 1\n\n"
"input line 2 \r\n";
const std::string expected_test_output_text =
"expected output line 1\n"
"----------\n"
"expected output line 2\n\n";
std::ostringstream input_text_stream;
// Empty input stream is OK.
extractTestCasesFromStream(input_text_stream);
// Having only comments is also OK.
input_text_stream << "# Comment";
extractTestCasesFromStream(input_text_stream);
// Having options but no test cases is not allowed.
input_text_stream.str("");
input_text_stream << comments_and_options;
EXPECT_DEATH(extractTestCasesFromStream(input_text_stream), "Has options but no input test text");
// With a valid test case.
input_text_stream << test_input_txt << "--\n" << expected_test_output_text << "==\n";
std::vector<TextBasedTestCase*> *test_cases =
extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
comments_and_options,
std::set<std::string>({"option1", "option2", "option3", "option4", "option5"}),
test_input_txt,
expected_test_output_text);
input_text_stream.str("");
// Do not append a test-case separator at the end.
input_text_stream << comments_and_options << test_input_txt << "--\n" << expected_test_output_text;
test_cases = extractTestCasesFromStream(input_text_stream);
// The result should be the same. The last test-case separator can
// be omitted.
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
comments_and_options,
std::set<std::string>({"option1", "option2", "option3", "option4", "option5"}),
test_input_txt,
expected_test_output_text);
input_text_stream.str("");
// We only require that the input-output (test-case) separators
// begin with "--" ("==").
input_text_stream
<< comments_and_options << test_input_txt << "-------abc\n" << expected_test_output_text << "=======def\n";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
comments_and_options,
std::set<std::string>({"option1", "option2", "option3", "option4", "option5"}),
test_input_txt,
expected_test_output_text);
// Without comments.
input_text_stream.str("");
input_text_stream << "[option1]\n" << test_input_txt << "--\n" << expected_test_output_text << "==\n";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
"[option1]\n",
std::set<std::string>({"option1"}),
test_input_txt,
expected_test_output_text);
// Without options.
input_text_stream.str("");
input_text_stream << "# Comments\n" << test_input_txt << "--\n" << expected_test_output_text << "==\n";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
"# Comments\n",
std::set<std::string>(),
test_input_txt,
expected_test_output_text);
// Without comments and options.
input_text_stream.str("");
input_text_stream << test_input_txt << "--\n" << expected_test_output_text << "==\n";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
"" /* comments_and_options_text */,
std::set<std::string>(),
test_input_txt,
expected_test_output_text);
// With empty expected output.
input_text_stream.str("");
input_text_stream << test_input_txt << "--\n==";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
"" /* comments_and_options_text */,
std::set<std::string>(),
test_input_txt,
"" /* expected_test_output_text */);
input_text_stream.str("");
input_text_stream << test_input_txt << "--";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 1u);
EXPECT_TEXT_CASE((*test_cases)[0],
"" /* comments_and_options_text */,
std::set<std::string>(),
test_input_txt,
"" /* expected_test_output_text */);
}
TEST_F(TextBasedTestDriverTest, DefaultOptionsTest) {
const std::string comments_and_options_0 =
"# Comments for the first case\n"
"[default option1 option2]\n"
"[default option3]\n";
const std::string comments_and_options_1 =
"# Comments for the second case\n"
"[option4 option5]\n";
const std::string test_input_txt =
"input line\n";
const std::string expected_test_output_text =
"expected output line 1\n";
std::ostringstream input_text_stream;
input_text_stream << comments_and_options_0 << test_input_txt << "--\n" << expected_test_output_text << "==\n"
<< comments_and_options_1 << test_input_txt << "--\n" << expected_test_output_text << "==\n";
std::vector<TextBasedTestCase*> *test_cases =
extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 2u);
EXPECT_TEXT_CASE((*test_cases)[0],
comments_and_options_0,
std::set<std::string>({"option1", "option2", "option3"}),
test_input_txt,
expected_test_output_text);
EXPECT_TEXT_CASE((*test_cases)[1],
comments_and_options_1,
std::set<std::string>({"option1", "option2", "option3", "option4", "option5"}),
test_input_txt,
expected_test_output_text);
// A default option statement in a new test case clears the default
// options set by previous test cases. The third and fourth test cases
// do not inherit option1 -- option3.
const std::string comments_and_options_3 =
"# Comments for the third case\n"
"[default option6]\n"
"[option7 option8]\n";
const std::string comments_and_options_4 =
"# Comments for the third case\n"
"[option9 option10]\n";
input_text_stream << comments_and_options_3 << test_input_txt << "--\n" << expected_test_output_text << "==\n"
<< comments_and_options_4 << test_input_txt << "--\n" << expected_test_output_text << "==\n";
test_cases = extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 4u);
EXPECT_TEXT_CASE((*test_cases)[2],
comments_and_options_3,
std::set<std::string>({"option6", "option7", "option8"}),
test_input_txt,
expected_test_output_text);
EXPECT_TEXT_CASE((*test_cases)[3],
comments_and_options_4,
std::set<std::string>({"option6", "option9", "option10"}),
test_input_txt,
expected_test_output_text);
}
TEST_F(TextBasedTestDriverTest, SameAsAboveTest) {
const std::string comments_and_options =
"# Comments for the first case\n"
"[option1 option2]\n";
const std::string test_input_txt =
"input line\n";
const std::string expected_test_output_text =
"expected output line 1\n";
const std::string same_as_above_test_output_text =
"[same as above]";
std::ostringstream input_text_stream;
input_text_stream << comments_and_options << test_input_txt << "--\n" << same_as_above_test_output_text;
EXPECT_DEATH(extractTestCasesFromStream(input_text_stream),
"Cannot specify \"same as above\" in the first test case");
input_text_stream.str("");
input_text_stream << comments_and_options << test_input_txt << "--\n" << expected_test_output_text << "==\n"
<< comments_and_options << test_input_txt << "--\n" << same_as_above_test_output_text;
std::vector<TextBasedTestCase*> *test_cases =
extractTestCasesFromStream(input_text_stream);
CHECK_EQ(test_cases->size(), 2u);
EXPECT_TEXT_CASE((*test_cases)[1],
comments_and_options,
std::set<std::string>({"option1", "option2"}),
test_input_txt,
expected_test_output_text);
}
TEST_F(TextBasedTestDriverTest, OptionErrors) {
const std::string test_input_txt = "input line\n";
const std::string expected_test_output_text = "expected output line\n";
const std::string with_unregistered_option =
"# Comments for the first case\n"
"[unregistered_option]\n";
std::ostringstream input_text_stream;
input_text_stream << with_unregistered_option << test_input_txt << "--\n" << expected_test_output_text;
EXPECT_DEATH(
extractTestCasesFromStream(input_text_stream),
"Option unregistered_option is not found");
const std::string invalid_option_line_0 = "[option1] [option2]\n";
input_text_stream.str("");
input_text_stream << invalid_option_line_0 << test_input_txt << "--\n" << expected_test_output_text;
EXPECT_DEATH(
extractTestCasesFromStream(input_text_stream),
"Cannot have text after options");
const std::string invalid_option_line_1 = "[option1] abc\n";
input_text_stream.str("");
input_text_stream << invalid_option_line_1 << test_input_txt << "--\n" << expected_test_output_text;
EXPECT_DEATH(
extractTestCasesFromStream(input_text_stream),
"Cannot have text after options");
const std::string with_no_options_0 = "[]\n";
input_text_stream.str("");
input_text_stream << with_no_options_0 << test_input_txt << "--\n" << expected_test_output_text;
EXPECT_DEATH(
extractTestCasesFromStream(input_text_stream),
"Has no options specified in the brackets");
const std::string with_no_options_1 = "[ \t ]\n";
input_text_stream.str("");
input_text_stream << with_no_options_1 << test_input_txt << "--\n" << expected_test_output_text;
EXPECT_DEATH(
extractTestCasesFromStream(input_text_stream),
"Has no options specified in the brackets");
const std::string with_no_options_2 = "[ default ]\n";
input_text_stream.str("");
input_text_stream << with_no_options_2 << test_input_txt << "--\n" << expected_test_output_text;
EXPECT_DEATH(
extractTestCasesFromStream(input_text_stream),
"Has no options specified in the brackets");
}
} // namespace quickstep