// Copyright 2023 PingCAP, Inc. // // Licensed 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. #pragma once #include #include #include #include #include #include #include #include #include namespace DB::tests { TiDB::TP dataTypeToTP(const DataTypePtr & type); ColumnsWithTypeAndName readBlock(BlockInputStreamPtr stream); ColumnsWithTypeAndName readBlocks(std::vector streams); #define WRAP_FOR_TEST_BEGIN \ std::vector pipeline_bools{false, true}; \ for (auto enable_pipeline : pipeline_bools) \ { \ enablePipeline(enable_pipeline); #define WRAP_FOR_TEST_END } class ExecutorTest : public ::testing::Test { protected: void SetUp() override; void TearDown() override; public: ExecutorTest() : context(TiFlashTestEnv::getContext()) {} static void SetUpTestCase(); virtual void initializeContext(); void initializeClientInfo() const; DAGContext & getDAGContext(); void enablePipeline(bool is_enable) const; static ::testing::AssertionResult dagRequestEqual( const char * lhs_expr, const char * rhs_expr, const String & expected_string, const std::shared_ptr & actual); void executeInterpreter( const String & expected_string, const std::shared_ptr & request, size_t concurrency); void executeInterpreterWithDeltaMerge( const String & expected_string, const std::shared_ptr & request, size_t concurrency); ColumnsWithTypeAndName executeRawQuery(const String & query, size_t concurrency = 1); void executeAndAssertColumnsEqual( const std::shared_ptr & request, const ColumnsWithTypeAndName & expect_columns); // To check the output column with index = column_index sorted. struct SortInfo { size_t column_index; bool desc; }; using SortInfos = std::vector; // check whether the column in each output block sorted. void executeAndAssertSortedBlocks(const std::shared_ptr & request, const SortInfos & sort_infos); void executeAndAssertRowsEqual(const std::shared_ptr & request, size_t expect_rows); enum SourceType { TableScan, ExchangeReceiver }; // for single source query, the source executor name is ${type}_0 static String getSourceName(SourceType type) { switch (type) { case TableScan: return "table_scan_0"; case ExchangeReceiver: return "exchange_receiver_0"; default: throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown Executor Source type {}", fmt::underlying(type)); } } ColumnsWithTypeAndName executeStreams(DAGContext * dag_context, bool is_internal = true); ColumnsWithTypeAndName executeStreams(const std::shared_ptr & request, size_t concurrency = 1); ColumnsWithTypeAndName executeStreamsWithMemoryTracker( const std::shared_ptr & request, size_t concurrency = 1); Blocks getExecuteStreamsReturnBlocks(const std::shared_ptr & request, size_t concurrency = 1); /// test execution summary // using ProfileInfo = std::pair; using Expect = std::unordered_map; static constexpr int not_check_rows = -1; static constexpr int not_check_concurrency = -1; void testForExecutionSummary( const std::shared_ptr & request, const Expect & expect, size_t concurrency = 10); private: void executeExecutor( const std::shared_ptr & request, std::function<::testing::AssertionResult(const ColumnsWithTypeAndName &)> assert_func); void checkBlockSorted( const std::shared_ptr & request, const SortInfos & sort_infos, std::function<::testing::AssertionResult(const ColumnsWithTypeAndName &, const ColumnsWithTypeAndName &)> assert_func); protected: MockDAGRequestContext context; std::unique_ptr dag_context_ptr; }; #define ASSERT_DAGREQUEST_EQAUL(str, request) ASSERT_PRED_FORMAT2(ExecutorTest::dagRequestEqual, (str), (request)); #define ASSERT_BLOCKINPUTSTREAM_EQAUL(str, request, concurrency) executeInterpreter((str), (request), (concurrency)) // nullable type using ColStringNullableType = std::optional::FieldType>; using ColInt8NullableType = std::optional::FieldType>; using ColUInt8NullableType = std::optional::FieldType>; using ColInt16NullableType = std::optional::FieldType>; using ColInt32NullableType = std::optional::FieldType>; using ColInt64NullableType = std::optional::FieldType>; using ColFloat32NullableType = std::optional::FieldType>; using ColFloat64NullableType = std::optional::FieldType>; using ColMyDateNullableType = std::optional::FieldType>; using ColMyDateTimeNullableType = std::optional::FieldType>; using ColDecimalNullableType = std::optional::FieldType>; // non nullable type using ColUInt64Type = typename TypeTraits::FieldType; using ColInt64Type = typename TypeTraits::FieldType; using ColFloat64Type = typename TypeTraits::FieldType; using ColStringType = typename TypeTraits::FieldType; using ColInt32Type = typename TypeTraits::FieldType; using ColUInt8Type = typename TypeTraits::FieldType; using ColInt8Type = typename TypeTraits::FieldType; // nullable column using ColumnWithNullableString = std::vector; using ColumnWithNullableInt8 = std::vector; using ColumnWithNullableUInt8 = std::vector; using ColumnWithNullableInt16 = std::vector; using ColumnWithNullableInt32 = std::vector; using ColumnWithNullableInt64 = std::vector; using ColumnWithNullableFloat32 = std::vector; using ColumnWithNullableFloat64 = std::vector; using ColumnWithNullableMyDate = std::vector; using ColumnWithNullableMyDateTime = std::vector; using ColumnWithNullableDecimal = std::vector; // non nullable column using ColumnWithInt64 = std::vector; using ColumnWithUInt64 = std::vector; using ColumnWithFloat64 = std::vector; using ColumnWithString = std::vector; using ColumnWithUInt8 = std::vector; using ColumnWithInt8 = std::vector; using ColumnWithInt32 = std::vector; } // namespace DB::tests