| /** |
| * 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. |
| **/ |
| |
| #ifndef QUICKSTEP_UTILITY_TEXTBASED_TEST_TEXTBASED_TEST_DRIVER_HPP_ |
| #define QUICKSTEP_UTILITY_TEXTBASED_TEST_TEXTBASED_TEST_DRIVER_HPP_ |
| |
| #include <istream> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "utility/textbased_test/TextBasedTest.hpp" |
| #include "utility/Macros.hpp" |
| |
| /** |
| * @brief Macro to create a text-based test. |
| */ |
| #define QUICKSTEP_GENERATE_TEXT_TEST(TEST_CASE_NAME) \ |
| std::unique_ptr<::quickstep::TextBasedTestDriver> test_driver; \ |
| INSTANTIATE_TEST_CASE_P( \ |
| TEST_CASE_NAME, TextBasedTest, \ |
| ::testing::ValuesIn( \ |
| *test_driver->populateAndReturnTestCases()),) // NOLINT(whitespace/comma) |
| |
| namespace quickstep { |
| |
| /** \addtogroup Utility |
| * @{ |
| */ |
| |
| /** |
| * @brief Extracts text-based test cases from an input text stream. |
| * |
| * Each test case may contain four sections: |
| * comments, options, input text and expected output text. |
| * |
| * 1) The comment line starts with # and is ignored by the test. |
| * Comments are optional. |
| * |
| * 2) Options are used to tell the test runner how to generate the output and |
| * what should be included in the output. For now, each option is just a string. |
| * A list of options can be specified in a pair of brackets and separated |
| * by whitespaces. An option list should occupy exactly one single line. |
| * Options in an option list with "default" at the very beginning |
| * will be included for all the remaining tests unless they are overridden |
| * by another default option list for anther test. The options section is optional. |
| * |
| * Two examples of options: |
| * a) [initial_logical_plan optimized_logical_plan] |
| * b) [default initial_logical_plan] |
| * The first option line specifies two options 'initial_logical_plan' |
| * and 'optimized_logical_plan'. The second line specifies a default |
| * option 'initial_logical_plan'. |
| * |
| * 3) The input text is required and separated from the expected output |
| * text by "--". The expected output text may be empty. |
| * |
| * 4) The test cases are separated by "==". |
| */ |
| class TextBasedTestDriver { |
| public: |
| /** |
| * @brief Constructor. Does not take ownership of \p test_runner. |
| * @param input_stream The stream where to read text-based tests. |
| * @param test_runner The test runner that generates actual output text |
| * for each test case. |
| */ |
| TextBasedTestDriver(std::istream *input_stream, TextBasedTestRunner *test_runner); |
| |
| virtual ~TextBasedTestDriver(); |
| |
| /** |
| * @brief Reads test cases from the input stream. |
| * The returned vector and the pointers in the vector are owned by the |
| * driver. |
| * |
| * @return A vector of test cases. |
| */ |
| std::vector<TextBasedTestCase*>* populateAndReturnTestCases(); |
| |
| /** |
| * @brief Appends the input content with expected outputs |
| * being replaced by actual outputs to \p out. |
| * |
| * @param out The output stream. |
| */ |
| void writeActualOutput(std::ostream *out) const; |
| |
| /** |
| * @brief Writes the input content with expected outputs |
| * being replaced by actual outputs to file. It can be |
| * compared with the input file to see the diff result. |
| * |
| * @param output_filename The output file name. |
| */ |
| void writeActualOutputToFile(const std::string &output_filename) const; |
| |
| /** |
| * @brief Registers a vector of options. |
| * |
| * @param option_names The vector of option names to be registered. |
| */ |
| void registerOptions(const std::vector<std::string> &option_names); |
| |
| /** |
| * @brief Registers a option. |
| * |
| * @param option_name The option name to be registered. |
| */ |
| void registerOption(const std::string &option_name); |
| |
| /** |
| * @brief Checks if an option has been registered. |
| * |
| * @param option_name the option to check. |
| * @return True if it is registered. |
| */ |
| bool isRegisteredOption(const std::string &option_name) const; |
| |
| /** |
| * @brief Checks whether an option is valid. A valid option can |
| * only contain alphanumeric characters or underscores. |
| * |
| * @param option_name The option to check. |
| * @return True if the option is valid. |
| */ |
| bool isValidOption(const std::string &option_name) const; |
| |
| private: |
| /** |
| * @brief Populates <test_cases_> with tests in the input file. |
| */ |
| void populateTestCases(); |
| |
| /** |
| * @return Reads next test case from the input file. |
| * NULL if the end of the file is reached. |
| */ |
| TextBasedTestCase* readNextTestCase(); |
| |
| /** |
| * @brief Clear all test cases. |
| */ |
| void clearTestCases(); |
| |
| /** |
| * @brief Reads options from one line and inserts the options |
| * to \p options_out. If they are default options, |
| * also appends them to \p default_options_out. |
| * |
| * @param line The input line. |
| * @param options_out The set that the new options are inserted to. |
| * @param default_options_out The set that the new options are inserted |
| * to if default is specified. |
| */ |
| void readOptions(const std::string &line, |
| std::set<std::string> *options_out, |
| std::set<std::string> *default_options_out); |
| |
| /** |
| * @brief Checks whether \p str is a separator between test cases (i.e. "=="). |
| */ |
| static bool IsTestCaseSeparator(const std::string &str); |
| |
| /** |
| * @brief Checks whether \p str is a separator between input and output (i.e. "--"). |
| */ |
| static bool IsInputOutputSeparator(const std::string &str); |
| |
| std::istream *input_stream_; |
| |
| std::set<std::string> registered_options_; |
| std::set<std::string> default_options_; |
| std::vector<TextBasedTestCase*> test_cases_; |
| |
| TextBasedTestRunner *test_runner_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TextBasedTestDriver); |
| }; |
| |
| /** @} */ |
| |
| } // namespace quickstep |
| |
| #endif /* QUICKSTEP_UTILITY_TEXTBASED_TEST_TEXTBASED_TEST_DRIVER_HPP_ */ |