blob: 63bd3ee3879f588c0595c10fc7baf138db9dde9a [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 <stdlib.h>
#include <stdio.h>
#include <iostream>
#include "testutil/gtest-util.h"
#include "util/symbols-util.h"
#include "common/names.h"
namespace impala {
void TestDemangling(const string& mangled, const string& expected_demangled) {
string result = SymbolsUtil::Demangle(mangled);
EXPECT_EQ(result, expected_demangled);
}
void TestDemanglingNoArgs(const string& mangled, const string& expected_demangled) {
string result = SymbolsUtil::DemangleNoArgs(mangled);
EXPECT_EQ(result, expected_demangled);
}
void TestDemanglingNameOnly(const string& mangled, const string& expected_demangled) {
string result = SymbolsUtil::DemangleNameOnly(mangled);
EXPECT_EQ(result, expected_demangled);
}
// Test mangling (name, var_args, args, ret_arg_type), validating the mangled
// string and then the unmangled (~function signature) results.
void TestMangling(const string& name, bool var_args, const vector<ColumnType> args,
ColumnType* ret_arg_type, const string& expected_mangled,
const string& expected_demangled) {
string mangled = SymbolsUtil::MangleUserFunction(name, args, var_args, ret_arg_type);
string demangled = SymbolsUtil::Demangle(mangled);
// Check we could demangle it.
EXPECT_TRUE(!demangled.empty()) << demangled;
EXPECT_EQ(mangled, expected_mangled);
EXPECT_EQ(demangled, expected_demangled);
}
void TestManglingPrepareOrClose(const string& name, const string& expected_mangled,
const string& expected_demangled) {
string mangled = SymbolsUtil::ManglePrepareOrCloseFunction(name);
string demangled = SymbolsUtil::Demangle(mangled);
// Check we could demangle it.
EXPECT_TRUE(!demangled.empty()) << demangled;
EXPECT_EQ(mangled, expected_mangled);
EXPECT_EQ(demangled, expected_demangled);
}
// Not very thoroughly tested since our implementation is just a wrapper around
// the gcc library.
TEST(SymbolsUtil, Demangling) {
TestDemangling("_Z6NoArgsPN10impala_udf15FunctionContextE",
"NoArgs(impala_udf::FunctionContext*)");
TestDemangling("_Z8IdentityPN10impala_udf15FunctionContextERKNS_10TinyIntValE",
"Identity(impala_udf::FunctionContext*, impala_udf::TinyIntVal const&)");
TestDemangling("_Z8IdentityPN10impala_udf15FunctionContextERKNS_9StringValE",
"Identity(impala_udf::FunctionContext*, impala_udf::StringVal const&)");
TestDemangling("_ZN3Foo4TESTEPN10impala_udf15FunctionContextERKNS0_6IntValES5_",
"Foo::TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)");
TestDemangling(
"_Z14VarSumMultiplyPN10impala_udf15FunctionContextERKNS_9DoubleValEiPKNS_6IntValE",
"VarSumMultiply(impala_udf::FunctionContext*, impala_udf::DoubleVal const&, int, "
"impala_udf::IntVal const*)");
TestDemangling("FooBar", "FooBar");
TestDemangling(
"Foo::TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)",
"Foo::TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)");
}
TEST(SymbolsUtil, DemanglingNoArgs) {
TestDemanglingNoArgs("_Z6NoArgsPN10impala_udf15FunctionContextE", "NoArgs");
TestDemanglingNoArgs("_Z8IdentityPN10impala_udf15FunctionContextERKNS_10TinyIntValE",
"Identity");
TestDemanglingNoArgs("_Z8IdentityPN10impala_udf15FunctionContextERKNS_9StringValE",
"Identity");
TestDemanglingNoArgs("_ZN3Foo4TESTEPN10impala_udf15FunctionContextERKNS0_6IntValES5_",
"Foo::TEST");
TestDemanglingNoArgs(
"_Z14VarSumMultiplyPN10impala_udf15FunctionContextERKNS_9DoubleValEiPKNS_6IntValE",
"VarSumMultiply");
TestDemanglingNoArgs("FooBar", "FooBar");
TestDemanglingNoArgs(
"Foo::TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)", "Foo::TEST");
}
TEST(SymbolsUtil, DemanglingNameOnly) {
TestDemanglingNameOnly("_Z6NoArgsPN10impala_udf15FunctionContextE", "NoArgs");
TestDemanglingNameOnly("_Z8IdentityPN10impala_udf15FunctionContextERKNS_10TinyIntValE",
"Identity");
TestDemanglingNameOnly("_Z8IdentityPN10impala_udf15FunctionContextERKNS_9StringValE",
"Identity");
TestDemanglingNameOnly("_ZN3Foo4TESTEPN10impala_udf15FunctionContextERKNS0_6IntValES5_",
"TEST");
TestDemanglingNameOnly(
"_Z14VarSumMultiplyPN10impala_udf15FunctionContextERKNS_9DoubleValEiPKNS_6IntValE",
"VarSumMultiply");
TestDemanglingNameOnly("FooBar", "FooBar");
TestDemanglingNameOnly(
"Foo::TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)", "TEST");
}
// TODO: is there a less arduous way to test this?
TEST(SymbolsUtil, Mangling) {
ColumnType int_ret_type = ColumnType(TYPE_INT);
ColumnType double_ret_type = ColumnType(TYPE_DOUBLE);
vector<ColumnType> args;
TestMangling("Foo", false, args, NULL, "_Z3FooPN10impala_udf15FunctionContextE",
"Foo(impala_udf::FunctionContext*)");
TestMangling("Foo", false, args, &int_ret_type,
"_Z3FooPN10impala_udf15FunctionContextEPNS_6IntValE",
"Foo(impala_udf::FunctionContext*, impala_udf::IntVal*)");
TestMangling("A::B", false, args, NULL, "_ZN1A1BEPN10impala_udf15FunctionContextE",
"A::B(impala_udf::FunctionContext*)");
TestMangling("A::B::C", false, args, NULL, "_ZN1A1B1CEPN10impala_udf15FunctionContextE",
"A::B::C(impala_udf::FunctionContext*)");
TestMangling("A::B::C", false, args, &int_ret_type,
"_ZN1A1B1CEPN10impala_udf15FunctionContextEPNS1_6IntValE",
"A::B::C(impala_udf::FunctionContext*, impala_udf::IntVal*)");
// Try functions with in input INT arg. Then try with varargs and int* return arg.
args.push_back(TYPE_INT);
TestMangling("F", false, args, NULL,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValE",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&)");
TestMangling("F", false, args, &int_ret_type,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValEPS2_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, impala_udf::IntVal*)");
TestMangling("F", true, args, NULL,
"_Z1FPN10impala_udf15FunctionContextEiPKNS_6IntValE",
"F(impala_udf::FunctionContext*, int, impala_udf::IntVal const*)");
TestMangling("F", true, args, &int_ret_type,
"_Z1FPN10impala_udf15FunctionContextEiPKNS_6IntValEPS2_",
"F(impala_udf::FunctionContext*, int, impala_udf::IntVal const*, "
"impala_udf::IntVal*)");
TestMangling("F::B", false, args, NULL,
"_ZN1F1BEPN10impala_udf15FunctionContextERKNS0_6IntValE",
"F::B(impala_udf::FunctionContext*, impala_udf::IntVal const&)");
TestMangling("F::B::C::D", false, args, NULL,
"_ZN1F1B1C1DEPN10impala_udf15FunctionContextERKNS2_6IntValE",
"F::B::C::D(impala_udf::FunctionContext*, impala_udf::IntVal const&)");
TestMangling("F::B", true, args, NULL,
"_ZN1F1BEPN10impala_udf15FunctionContextEiPKNS0_6IntValE",
"F::B(impala_udf::FunctionContext*, int, impala_udf::IntVal const*)");
TestMangling("F::B", true, args, &int_ret_type,
"_ZN1F1BEPN10impala_udf15FunctionContextEiPKNS0_6IntValEPS3_",
"F::B(impala_udf::FunctionContext*, int, impala_udf::IntVal const*, "
"impala_udf::IntVal*)");
// Try addding some redudant argument types. These should get compressed away.
args.push_back(TYPE_INT);
TestMangling("F", false, args, NULL,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValES4_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)");
TestMangling("F", false, args, &int_ret_type,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValES4_PS2_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&, impala_udf::IntVal*)");
TestMangling("F", true, args, NULL,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValEiPS3_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, int, "
"impala_udf::IntVal const*)");
TestMangling("F", true, args, &int_ret_type,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValEiPS3_PS2_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, int, "
"impala_udf::IntVal const*, impala_udf::IntVal*)");
TestMangling("F::B", false, args, NULL,
"_ZN1F1BEPN10impala_udf15FunctionContextERKNS0_6IntValES5_",
"F::B(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)");
args.push_back(TYPE_INT);
TestMangling("F", false, args, NULL,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValES4_S4_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&, impala_udf::IntVal const&)");
TestMangling("F", false, args, &int_ret_type,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValES4_S4_PS2_",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&, impala_udf::IntVal const&, "
"impala_udf::IntVal*)");
TestMangling("F", false, args, &double_ret_type,
"_Z1FPN10impala_udf15FunctionContextERKNS_6IntValES4_S4_PNS_9DoubleValE",
"F(impala_udf::FunctionContext*, impala_udf::IntVal const&, "
"impala_udf::IntVal const&, impala_udf::IntVal const&, "
"impala_udf::DoubleVal*)");
// Try some more complicated cases.
// fn(double, double, int, int)
args.clear();
args.push_back(TYPE_DOUBLE);
args.push_back(TYPE_DOUBLE);
args.push_back(TYPE_INT);
args.push_back(TYPE_INT);
TestMangling("TEST", false, args, NULL,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_9DoubleValES4_RKNS_6IntValES7_",
"TEST(impala_udf::FunctionContext*, impala_udf::DoubleVal const&, "
"impala_udf::DoubleVal const&, impala_udf::IntVal const&, "
"impala_udf::IntVal const&)");
TestMangling("TEST", true, args, NULL,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_9DoubleValES4_RKNS_6IntValEiPS6_",
"TEST(impala_udf::FunctionContext*, impala_udf::DoubleVal const&, "
"impala_udf::DoubleVal const&, impala_udf::IntVal const&, int, "
"impala_udf::IntVal const*)");
TestMangling("TEST", false, args, &int_ret_type,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_9DoubleValES4_RKNS_6IntValES7_PS5_",
"TEST(impala_udf::FunctionContext*, impala_udf::DoubleVal const&, "
"impala_udf::DoubleVal const&, impala_udf::IntVal const&, "
"impala_udf::IntVal const&, impala_udf::IntVal*)");
TestMangling("TEST", true, args, &double_ret_type,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_9DoubleValES4_RKNS_6IntValEiPS6_PS2_",
"TEST(impala_udf::FunctionContext*, impala_udf::DoubleVal const&, "
"impala_udf::DoubleVal const&, impala_udf::IntVal const&, int, "
"impala_udf::IntVal const*, impala_udf::DoubleVal*)");
// fn(int, double, double, int)
args.clear();
args.push_back(TYPE_INT);
args.push_back(TYPE_DOUBLE);
args.push_back(TYPE_DOUBLE);
args.push_back(TYPE_INT);
TestMangling("TEST", false, args, NULL,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_6IntValERKNS_9DoubleValES7_S4_",
"TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, impala_udf::"
"DoubleVal const&, impala_udf::DoubleVal const&, impala_udf::IntVal const&)");
TestMangling("TEST", true, args, NULL,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_6IntValERKNS_9DoubleValES7_iPS3_",
"TEST(impala_udf::FunctionContext*, impala_udf::IntVal const&, impala_udf::"
"DoubleVal const&, impala_udf::DoubleVal const&, int, "
"impala_udf::IntVal const*)");
// All the types.
args.clear();
args.push_back(TYPE_STRING);
args.push_back(TYPE_BOOLEAN);
args.push_back(TYPE_TINYINT);
args.push_back(TYPE_SMALLINT);
args.push_back(TYPE_INT);
args.push_back(TYPE_BIGINT);
args.push_back(TYPE_FLOAT);
args.push_back(TYPE_DOUBLE);
args.push_back(TYPE_TIMESTAMP);
args.push_back(TYPE_DATE);
args.push_back(ColumnType::CreateCharType(10));
TestMangling("AllTypes", false, args, NULL,
"_Z8AllTypesPN10impala_udf15FunctionContextERKNS_9StringValERKNS_10BooleanValE"
"RKNS_10TinyIntValERKNS_11SmallIntValERKNS_6IntValERKNS_9BigIntValE"
"RKNS_8FloatValERKNS_9DoubleValERKNS_12TimestampValERKNS_7DateValE"
"RKNS_9StringValE",
"AllTypes(impala_udf::FunctionContext*, impala_udf::StringVal const&, "
"impala_udf::BooleanVal const&, impala_udf::TinyIntVal const&, "
"impala_udf::SmallIntVal const&, impala_udf::IntVal const&, "
"impala_udf::BigIntVal const&, impala_udf::FloatVal const&, "
"impala_udf::DoubleVal const&, impala_udf::TimestampVal const&, "
"impala_udf::DateVal const&, impala_udf::StringVal const&)");
TestMangling("AllTypes", false, args, &int_ret_type,
"_Z8AllTypesPN10impala_udf15FunctionContextERKNS_9StringValERKNS_10BooleanValE"
"RKNS_10TinyIntValERKNS_11SmallIntValERKNS_6IntValERKNS_9BigIntValE"
"RKNS_8FloatValERKNS_9DoubleValERKNS_12TimestampValERKNS_7DateValE"
"RKNS_9StringValEPSE_",
"AllTypes(impala_udf::FunctionContext*, impala_udf::StringVal const&, "
"impala_udf::BooleanVal const&, impala_udf::TinyIntVal const&, "
"impala_udf::SmallIntVal const&, impala_udf::IntVal const&, "
"impala_udf::BigIntVal const&, impala_udf::FloatVal const&, "
"impala_udf::DoubleVal const&, impala_udf::TimestampVal const&, "
"impala_udf::DateVal const&, impala_udf::StringVal const&, "
"impala_udf::IntVal*)");
TestMangling("AllTypes", false, args, &double_ret_type,
"_Z8AllTypesPN10impala_udf15FunctionContextERKNS_9StringValERKNS_10BooleanValE"
"RKNS_10TinyIntValERKNS_11SmallIntValERKNS_6IntValERKNS_9BigIntValE"
"RKNS_8FloatValERKNS_9DoubleValERKNS_12TimestampValERKNS_7DateValE"
"RKNS_9StringValEPSN_",
"AllTypes(impala_udf::FunctionContext*, impala_udf::StringVal const&, "
"impala_udf::BooleanVal const&, impala_udf::TinyIntVal const&, "
"impala_udf::SmallIntVal const&, impala_udf::IntVal const&, "
"impala_udf::BigIntVal const&, impala_udf::FloatVal const&, "
"impala_udf::DoubleVal const&, impala_udf::TimestampVal const&, "
"impala_udf::DateVal const&, impala_udf::StringVal const&, "
"impala_udf::DoubleVal*)");
// CHAR(N) type. This has restricted use. It can only be an intermediate type.
args.clear();
ColumnType char_ret_type = ColumnType::CreateCharType(10);
TestMangling("TEST", false, args, &char_ret_type,
"_Z4TESTPN10impala_udf15FunctionContextEPNS_9StringValE",
"TEST(impala_udf::FunctionContext*, impala_udf::StringVal*)");
args.push_back(ColumnType::CreateCharType(10));
TestMangling("TEST", false, args, &char_ret_type,
"_Z4TESTPN10impala_udf15FunctionContextERKNS_9StringValEPS2_",
"TEST(impala_udf::FunctionContext*, impala_udf::StringVal const&, "
"impala_udf::StringVal*)");
}
TEST(SymbolsUtil, ManglingPrepareOrClose) {
TestManglingPrepareOrClose("CountPrepare",
"_Z12CountPreparePN10impala_udf15FunctionContextENS0_18FunctionStateScopeE",
"CountPrepare(impala_udf::FunctionContext*,"
" impala_udf::FunctionContext::FunctionStateScope)");
TestManglingPrepareOrClose("foo::bar",
"_ZN3foo3barEPN10impala_udf15FunctionContextENS1_18FunctionStateScopeE",
"foo::bar(impala_udf::FunctionContext*,"
" impala_udf::FunctionContext::FunctionStateScope)");
}
}