From 2faad2fde5f5c4ddeb9241703ea8e14ded6b9628 Mon Sep 17 00:00:00 2001 From: rui-mo Date: Fri, 12 Apr 2024 09:58:20 +0800 Subject: [PATCH] try --- velox/expression/tests/ArgGenerator.h | 3 +- velox/expression/tests/ExpressionFuzzer.cpp | 144 +---------------- velox/expression/tests/ExpressionFuzzer.h | 6 +- .../expression/tests/ExpressionFuzzerTest.cpp | 12 +- .../tests/ExpressionFuzzerVerifier.cpp | 7 +- .../tests/ExpressionFuzzerVerifier.h | 4 +- velox/expression/tests/FuzzerRunner.cpp | 13 +- velox/expression/tests/FuzzerRunner.h | 8 +- .../tests/SparkExpressionFuzzerTest.cpp | 2 +- .../prestosql/fuzzer/PlusMinusArgGenerator.h | 151 ++++++++++++++++++ 10 files changed, 196 insertions(+), 154 deletions(-) create mode 100644 velox/functions/prestosql/fuzzer/PlusMinusArgGenerator.h diff --git a/velox/expression/tests/ArgGenerator.h b/velox/expression/tests/ArgGenerator.h index d7c0d81c95514..79d6abdc225c7 100644 --- a/velox/expression/tests/ArgGenerator.h +++ b/velox/expression/tests/ArgGenerator.h @@ -45,8 +45,7 @@ class DecimalArgGeneratorBase : public ArgGenerator { // Return randomly selected pair of input types that produce the specified // result type. - Inputs findInputs(const TypePtr& returnType, FuzzerGenerator& rng) - const; + Inputs findInputs(const TypePtr& returnType, FuzzerGenerator& rng) const; const std::vector& getAllTypes() const; diff --git a/velox/expression/tests/ExpressionFuzzer.cpp b/velox/expression/tests/ExpressionFuzzer.cpp index 73aaf751fed84..98d3d6e117b10 100644 --- a/velox/expression/tests/ExpressionFuzzer.cpp +++ b/velox/expression/tests/ExpressionFuzzer.cpp @@ -32,134 +32,6 @@ namespace facebook::velox::test { namespace { -class PlusMinusArgGenerator : public DecimalArgGeneratorBase { - public: - PlusMinusArgGenerator() { - initialize(); - } - - protected: - std::optional> toReturnType(int count, ...) override { - VELOX_CHECK_EQ(count, 4); - va_list args; - va_start(args, count); - int p1 = va_arg(args, int); - int s1 = va_arg(args, int); - int p2 = va_arg(args, int); - int s2 = va_arg(args, int); - va_end(args); - - auto s = std::max(s1, s2); - auto p = std::min(38, std::max(p1 - s1, p2 - s2) + 1 + s); - return {{p, s}}; - } -}; - -class MultiplyArgGenerator : public DecimalArgGeneratorBase { - public: - MultiplyArgGenerator() { - initialize(); - } - - protected: - std::optional> toReturnType(int count, ...) override { - VELOX_CHECK_EQ(count, 4); - va_list args; - va_start(args, count); - int p1 = va_arg(args, int); - int s1 = va_arg(args, int); - int p2 = va_arg(args, int); - int s2 = va_arg(args, int); - va_end(args); - - if (s1 + s2 > 38) { - return std::nullopt; - } - - auto p = std::min(38, p1 + p2); - auto s = s1 + s2; - return {{p, s}}; - } -}; - -class DivideArgGenerator : public DecimalArgGeneratorBase { - public: - DivideArgGenerator() { - initialize(); - } - - protected: - std::optional> toReturnType(int count, ...) override { - VELOX_CHECK_EQ(count, 4); - va_list args; - va_start(args, count); - int p1 = va_arg(args, int); - int s1 = va_arg(args, int); - int p2 = va_arg(args, int); - int s2 = va_arg(args, int); - va_end(args); - - if (s1 + s2 > 38) { - return std::nullopt; - } - - auto p = std::min(38, p1 + s2 + std::max(0, s2 - s1)); - auto s = std::max(s1, s2); - return {{p, s}}; - } -}; - -class FloorAndRoundArgGenerator : public ArgGenerator { - public: - std::vector generateArgs( - const exec::FunctionSignature& signature, - const TypePtr& returnType, - FuzzerGenerator& rng) override { - if (signature.argumentTypes().size() == 1) { - return generateSingleArg(returnType, rng); - } else { - VELOX_CHECK_EQ(2, signature.argumentTypes().size()) - return generateTwoArgs(returnType); - } - } - - private: - std::vector generateSingleArg( - const TypePtr& returnType, - FuzzerGenerator& rng) { - auto [p, s] = getDecimalPrecisionScale(*returnType); - - // p = p1 - s1 + min(s1, 1) - // s = 0 - if (s != 0) { - return {}; - } - - const auto rand32 = [](FuzzerGenerator& rng) { - return boost::random::uniform_int_distribution()(rng); - }; - - auto s1 = rand32(rng) % (38 - p + 1); - if (s1 == 0) { - return {DECIMAL(p, 0)}; - } - - return {DECIMAL(p - 1 + s1, s1)}; - } - - std::vector generateTwoArgs(const TypePtr& returnType) { - auto [p, s] = getDecimalPrecisionScale(*returnType); - - // p = p1 + 1 - // s = s1 - if (p == 1 || p == s) { - return {}; - } - - return {DECIMAL(p - 1, s), INTEGER()}; - } -}; - using exec::SignatureBinder; using exec::SignatureBinderBase; @@ -658,22 +530,16 @@ ExpressionFuzzer::ExpressionFuzzer( FunctionSignatureMap signatureMap, size_t initialSeed, const std::shared_ptr& vectorFuzzer, - const std::optional& options) + const std::optional& options, + const std::unordered_map>& + argGenerators) : options_(options.value_or(Options())), vectorFuzzer_(vectorFuzzer), - state{rng_, std::max(1, options_.maxLevelOfNesting)} { + state{rng_, std::max(1, options_.maxLevelOfNesting)}, + argGenerators_(argGenerators) { VELOX_CHECK(vectorFuzzer, "Vector fuzzer must be provided"); seed(initialSeed); - argGenerators_.emplace("plus", std::make_shared()); - argGenerators_.emplace("minus", std::make_shared()); - argGenerators_.emplace("multiply", std::make_shared()); - argGenerators_.emplace("divide", std::make_shared()); - argGenerators_.emplace( - "floor", std::make_shared()); - argGenerators_.emplace( - "round", std::make_shared()); - appendSpecialForms(signatureMap, options_.specialForms); filterSignatures( signatureMap, options_.useOnlyFunctions, options_.skipFunctions); diff --git a/velox/expression/tests/ExpressionFuzzer.h b/velox/expression/tests/ExpressionFuzzer.h index f58348efccc4c..56ef50b9dccc6 100644 --- a/velox/expression/tests/ExpressionFuzzer.h +++ b/velox/expression/tests/ExpressionFuzzer.h @@ -19,12 +19,12 @@ #include "velox/core/ITypedExpr.h" #include "velox/core/QueryCtx.h" #include "velox/expression/Expr.h" +#include "velox/expression/tests/ArgGenerator.h" #include "velox/expression/tests/ExpressionVerifier.h" #include "velox/expression/tests/utils/FuzzerToolkit.h" #include "velox/functions/FunctionRegistry.h" #include "velox/vector/fuzzer/VectorFuzzer.h" #include "velox/vector/tests/utils/VectorMaker.h" -#include "velox/expression/tests/ArgGenerator.h" namespace facebook::velox::test { @@ -108,7 +108,9 @@ class ExpressionFuzzer { FunctionSignatureMap signatureMap, size_t initialSeed, const std::shared_ptr& vectorFuzzer, - const std::optional& options = std::nullopt); + const std::optional& options = std::nullopt, + const std::unordered_map>& + argGenerators = {}); template void registerFuncOverride(TFunc func, const std::string& name); diff --git a/velox/expression/tests/ExpressionFuzzerTest.cpp b/velox/expression/tests/ExpressionFuzzerTest.cpp index 1c6a675bfdf73..f642d17bf21ba 100644 --- a/velox/expression/tests/ExpressionFuzzerTest.cpp +++ b/velox/expression/tests/ExpressionFuzzerTest.cpp @@ -18,7 +18,9 @@ #include #include +#include "velox/expression/tests/ArgGenerator.h" #include "velox/expression/tests/FuzzerRunner.h" +#include "velox/functions/prestosql/fuzzer/PlusMinusArgGenerator.h" #include "velox/functions/prestosql/registration/RegistrationFunctions.h" DEFINE_int64( @@ -27,6 +29,8 @@ DEFINE_int64( "Initial seed for random number generator used to reproduce previous " "results (0 means start with random seed)."); +using facebook::velox::exec::test; +using facebook::velox::test::ArgGenerator; using facebook::velox::test::FuzzerRunner; int main(int argc, char** argv) { @@ -65,6 +69,12 @@ int main(int argc, char** argv) { "regexp_extract_all", "regexp_like", }; + std::unordered_map> argGenerators = + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}; + size_t initialSeed = FLAGS_seed == 0 ? std::time(nullptr) : FLAGS_seed; - return FuzzerRunner::run(initialSeed, skipFunctions, {{}}); + return FuzzerRunner::run(initialSeed, skipFunctions, {{}}, argGenerators); } diff --git a/velox/expression/tests/ExpressionFuzzerVerifier.cpp b/velox/expression/tests/ExpressionFuzzerVerifier.cpp index 8e36fd739f21c..2a9ac03145e6c 100644 --- a/velox/expression/tests/ExpressionFuzzerVerifier.cpp +++ b/velox/expression/tests/ExpressionFuzzerVerifier.cpp @@ -80,7 +80,9 @@ RowVectorPtr wrapChildren( ExpressionFuzzerVerifier::ExpressionFuzzerVerifier( const FunctionSignatureMap& signatureMap, size_t initialSeed, - const ExpressionFuzzerVerifier::Options& options) + const ExpressionFuzzerVerifier::Options& options, + const std::unordered_map>& + argGenerators) : options_(options), queryCtx_(std::make_shared( nullptr, @@ -98,7 +100,8 @@ ExpressionFuzzerVerifier::ExpressionFuzzerVerifier( signatureMap, initialSeed, vectorFuzzer_, - options.expressionFuzzerOptions) { + options.expressionFuzzerOptions, + argGenerators) { seed(initialSeed); // Init stats and register listener. diff --git a/velox/expression/tests/ExpressionFuzzerVerifier.h b/velox/expression/tests/ExpressionFuzzerVerifier.h index 2f85b5d52bc71..04d5b8cebc774 100644 --- a/velox/expression/tests/ExpressionFuzzerVerifier.h +++ b/velox/expression/tests/ExpressionFuzzerVerifier.h @@ -51,7 +51,9 @@ class ExpressionFuzzerVerifier { ExpressionFuzzerVerifier( const FunctionSignatureMap& signatureMap, size_t initialSeed, - const Options& options); + const Options& options, + const std::unordered_map>& + argGenerators); // This function starts the test that is performed by the // ExpressionFuzzerVerifier which is generating random expressions and diff --git a/velox/expression/tests/FuzzerRunner.cpp b/velox/expression/tests/FuzzerRunner.cpp index e947f147c6853..d0b077e339e2a 100644 --- a/velox/expression/tests/FuzzerRunner.cpp +++ b/velox/expression/tests/FuzzerRunner.cpp @@ -210,8 +210,10 @@ ExpressionFuzzerVerifier::Options getExpressionFuzzerVerifierOptions( int FuzzerRunner::run( size_t seed, const std::unordered_set& skipFunctions, - const std::unordered_map& queryConfigs) { - runFromGtest(seed, skipFunctions, queryConfigs); + const std::unordered_map& queryConfigs, + const std::unordered_map>& + argGenerators) { + runFromGtest(seed, skipFunctions, queryConfigs, argGenerators); return RUN_ALL_TESTS(); } @@ -219,13 +221,16 @@ int FuzzerRunner::run( void FuzzerRunner::runFromGtest( size_t seed, const std::unordered_set& skipFunctions, - const std::unordered_map& queryConfigs) { + const std::unordered_map& queryConfigs, + const std::unordered_map>& + argGenerators) { memory::MemoryManager::testingSetInstance({}); auto signatures = facebook::velox::getFunctionSignatures(); ExpressionFuzzerVerifier( signatures, seed, - getExpressionFuzzerVerifierOptions(skipFunctions, queryConfigs)) + getExpressionFuzzerVerifierOptions(skipFunctions, queryConfigs), + argGenerators) .go(); } } // namespace facebook::velox::test diff --git a/velox/expression/tests/FuzzerRunner.h b/velox/expression/tests/FuzzerRunner.h index cbf3d5ac290a9..37cba47c00bbc 100644 --- a/velox/expression/tests/FuzzerRunner.h +++ b/velox/expression/tests/FuzzerRunner.h @@ -33,12 +33,16 @@ class FuzzerRunner { static int run( size_t seed, const std::unordered_set& skipFunctions, - const std::unordered_map& queryConfigs); + const std::unordered_map& queryConfigs, + const std::unordered_map>& + argGenerators); static void runFromGtest( size_t seed, const std::unordered_set& skipFunctions, - const std::unordered_map& queryConfigs); + const std::unordered_map& queryConfigs, + const std::unordered_map>& + argGenerators); }; } // namespace facebook::velox::test diff --git a/velox/expression/tests/SparkExpressionFuzzerTest.cpp b/velox/expression/tests/SparkExpressionFuzzerTest.cpp index c9531632f4137..aac1b9e642201 100644 --- a/velox/expression/tests/SparkExpressionFuzzerTest.cpp +++ b/velox/expression/tests/SparkExpressionFuzzerTest.cpp @@ -60,5 +60,5 @@ int main(int argc, char** argv) { std::unordered_map queryConfigs = { {facebook::velox::core::QueryConfig::kSparkPartitionId, "123"}}; - return FuzzerRunner::run(FLAGS_seed, skipFunctions, queryConfigs); + return FuzzerRunner::run(FLAGS_seed, skipFunctions, queryConfigs, {}); } diff --git a/velox/functions/prestosql/fuzzer/PlusMinusArgGenerator.h b/velox/functions/prestosql/fuzzer/PlusMinusArgGenerator.h new file mode 100644 index 0000000000000..d0d6232fc49d7 --- /dev/null +++ b/velox/functions/prestosql/fuzzer/PlusMinusArgGenerator.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * 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 "velox/expression/tests/ArgGenerator.h" +#include + +namespace facebook::velox::exec::test { + +class PlusMinusArgGenerator : public facebook::velox::test::DecimalArgGeneratorBase { + public: + PlusMinusArgGenerator() { + initialize(); + } + + protected: + std::optional> toReturnType(int count, ...) override { + VELOX_CHECK_EQ(count, 4); + va_list args; + va_start(args, count); + int p1 = va_arg(args, int); + int s1 = va_arg(args, int); + int p2 = va_arg(args, int); + int s2 = va_arg(args, int); + va_end(args); + + auto s = std::max(s1, s2); + auto p = std::min(38, std::max(p1 - s1, p2 - s2) + 1 + s); + return {{p, s}}; + } +}; + +class MultiplyArgGenerator : public DecimalArgGeneratorBase { + public: + MultiplyArgGenerator() { + initialize(); + } + + protected: + std::optional> toReturnType(int count, ...) override { + VELOX_CHECK_EQ(count, 4); + va_list args; + va_start(args, count); + int p1 = va_arg(args, int); + int s1 = va_arg(args, int); + int p2 = va_arg(args, int); + int s2 = va_arg(args, int); + va_end(args); + + if (s1 + s2 > 38) { + return std::nullopt; + } + + auto p = std::min(38, p1 + p2); + auto s = s1 + s2; + return {{p, s}}; + } +}; + +class DivideArgGenerator : public DecimalArgGeneratorBase { + public: + DivideArgGenerator() { + initialize(); + } + + protected: + std::optional> toReturnType(int count, ...) override { + VELOX_CHECK_EQ(count, 4); + va_list args; + va_start(args, count); + int p1 = va_arg(args, int); + int s1 = va_arg(args, int); + int p2 = va_arg(args, int); + int s2 = va_arg(args, int); + va_end(args); + + if (s1 + s2 > 38) { + return std::nullopt; + } + + auto p = std::min(38, p1 + s2 + std::max(0, s2 - s1)); + auto s = std::max(s1, s2); + return {{p, s}}; + } +}; + +class FloorAndRoundArgGenerator : public ArgGenerator { + public: + std::vector generateArgs( + const exec::FunctionSignature& signature, + const TypePtr& returnType, + FuzzerGenerator& rng) override { + if (signature.argumentTypes().size() == 1) { + return generateSingleArg(returnType, rng); + } else { + VELOX_CHECK_EQ(2, signature.argumentTypes().size()) + return generateTwoArgs(returnType); + } + } + + private: + std::vector generateSingleArg( + const TypePtr& returnType, + FuzzerGenerator& rng) { + auto [p, s] = getDecimalPrecisionScale(*returnType); + + // p = p1 - s1 + min(s1, 1) + // s = 0 + if (s != 0) { + return {}; + } + + const auto rand32 = [](FuzzerGenerator& rng) { + return boost::random::uniform_int_distribution()(rng); + }; + + auto s1 = rand32(rng) % (38 - p + 1); + if (s1 == 0) { + return {DECIMAL(p, 0)}; + } + + return {DECIMAL(p - 1 + s1, s1)}; + } + + std::vector generateTwoArgs(const TypePtr& returnType) { + auto [p, s] = getDecimalPrecisionScale(*returnType); + + // p = p1 + 1 + // s = s1 + if (p == 1 || p == s) { + return {}; + } + + return {DECIMAL(p - 1, s), INTEGER()}; + } +}; + +} // namespace facebook::velox::exec::test