blob: 87cac9e90e26470037f725cd9c87aaa3be60392b [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 <gtest/gtest.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include "common/logging.h"
#include "udf/udf_test_harness.hpp"
#include "util/logging.h"
namespace doris_udf {
DoubleVal zero_udf(FunctionContext* context) {
return DoubleVal(0);
}
StringVal log_udf(FunctionContext* context, const StringVal& arg1) {
std::cerr << (arg1.is_null ? "NULL" : std::string((char*)arg1.ptr, arg1.len)) << std::endl;
return arg1;
}
StringVal upper_udf(FunctionContext* context, const StringVal& input) {
if (input.is_null) {
return StringVal::null();
}
// Create a new StringVal object that's the same length as the input
StringVal result = StringVal(context, input.len);
for (int i = 0; i < input.len; ++i) {
result.ptr[i] = toupper(input.ptr[i]);
}
return result;
}
FloatVal min3(FunctionContext* context, const FloatVal& f1, const FloatVal& f2,
const FloatVal& f3) {
bool is_null = true;
float v = 0.0;
if (!f1.is_null) {
if (is_null) {
v = f1.val;
is_null = false;
} else {
v = std::min(v, f1.val);
}
}
if (!f2.is_null) {
if (is_null) {
v = f2.val;
is_null = false;
} else {
v = std::min(v, f2.val);
}
}
if (!f3.is_null) {
if (is_null) {
v = f3.val;
is_null = false;
} else {
v = std::min(v, f3.val);
}
}
return is_null ? FloatVal::null() : FloatVal(v);
}
StringVal concat(FunctionContext* context, int n, const StringVal* args) {
int size = 0;
bool all_null = true;
for (int i = 0; i < n; ++i) {
if (args[i].is_null) {
continue;
}
size += args[i].len;
all_null = false;
}
if (all_null) {
return StringVal::null();
}
int offset = 0;
StringVal result(context, size);
for (int i = 0; i < n; ++i) {
if (args[i].is_null) {
continue;
}
memcpy(result.ptr + offset, args[i].ptr, args[i].len);
offset += args[i].len;
}
return result;
}
IntVal num_var_args(FunctionContext*, const BigIntVal& dummy, int n, const IntVal* args) {
return IntVal(n);
}
IntVal validat_udf(FunctionContext* context) {
EXPECT_EQ(context->version(), FunctionContext::V2_0);
EXPECT_FALSE(context->has_error());
EXPECT_TRUE(context->error_msg() == NULL);
return IntVal::null();
}
IntVal validate_fail(FunctionContext* context) {
EXPECT_FALSE(context->has_error());
EXPECT_TRUE(context->error_msg() == NULL);
context->set_error("Fail");
EXPECT_TRUE(context->has_error());
EXPECT_TRUE(strcmp(context->error_msg(), "Fail") == 0);
return IntVal::null();
}
IntVal validate_mem(FunctionContext* context) {
EXPECT_TRUE(context->allocate(0) == NULL);
uint8_t* buffer = context->allocate(10);
EXPECT_TRUE(buffer != NULL);
memset(buffer, 0, 10);
context->free(buffer);
return IntVal::null();
}
StringVal time_to_string(FunctionContext* context, const TimestampVal& time) {
boost::posix_time::ptime t(*(boost::gregorian::date*)&time.date);
t += boost::posix_time::nanoseconds(time.time_of_day);
std::stringstream ss;
ss << boost::posix_time::to_iso_extended_string(t) << " "
<< boost::posix_time::to_simple_string(t.time_of_day());
std::string s = ss.str();
StringVal result(context, s.size());
memcpy(result.ptr, s.data(), result.len);
return result;
}
TEST(UdfTest, TestFunctionContext) {
EXPECT_TRUE(UdfTestHarness::validat_udf<IntVal>(validat_udf, IntVal::null()));
EXPECT_FALSE(UdfTestHarness::validat_udf<IntVal>(validate_fail, IntVal::null()));
EXPECT_TRUE(UdfTestHarness::validat_udf<IntVal>(validate_mem, IntVal::null()));
}
TEST(UdfTest, TestValidate) {
EXPECT_TRUE(UdfTestHarness::validat_udf<DoubleVal>(zero_udf, DoubleVal(0)));
EXPECT_FALSE(UdfTestHarness::validat_udf<DoubleVal>(zero_udf, DoubleVal(10)));
EXPECT_TRUE((UdfTestHarness::validat_udf<StringVal, StringVal>(log_udf, StringVal("abcd"),
StringVal("abcd"))));
EXPECT_TRUE((UdfTestHarness::validat_udf<StringVal, StringVal>(upper_udf, StringVal("abcd"),
StringVal("ABCD"))));
EXPECT_TRUE((UdfTestHarness::validat_udf<FloatVal, FloatVal, FloatVal, FloatVal>(
min3, FloatVal(1), FloatVal(2), FloatVal(3), FloatVal(1))));
EXPECT_TRUE((UdfTestHarness::validat_udf<FloatVal, FloatVal, FloatVal, FloatVal>(
min3, FloatVal(1), FloatVal::null(), FloatVal(3), FloatVal(1))));
EXPECT_TRUE((UdfTestHarness::validat_udf<FloatVal, FloatVal, FloatVal, FloatVal>(
min3, FloatVal::null(), FloatVal::null(), FloatVal::null(), FloatVal::null())));
}
TEST(UdfTest, TestTimestampVal) {
boost::gregorian::date d(2003, 3, 15);
TimestampVal t1(*(int32_t*)&d);
EXPECT_TRUE((UdfTestHarness::validat_udf<StringVal, TimestampVal>(time_to_string, t1,
"2003-03-15 00:00:00")));
TimestampVal t2(*(int32_t*)&d, 1000L * 1000L * 5000L);
EXPECT_TRUE((UdfTestHarness::validat_udf<StringVal, TimestampVal>(time_to_string, t2,
"2003-03-15 00:00:05")));
}
TEST(UdfTest, TestVarArgs) {
std::vector<StringVal> input;
input.push_back(StringVal("Hello"));
input.push_back(StringVal("World"));
EXPECT_TRUE((UdfTestHarness::validat_udf<StringVal, StringVal>(concat, input,
StringVal("HelloWorld"))));
input.push_back(StringVal("More"));
EXPECT_TRUE((UdfTestHarness::validat_udf<StringVal, StringVal>(concat, input,
StringVal("HelloWorldMore"))));
std::vector<IntVal> args;
args.resize(10);
EXPECT_TRUE((UdfTestHarness::validat_udf<IntVal, BigIntVal, IntVal>(
num_var_args, BigIntVal(0), args, IntVal(args.size()))));
}
} // namespace doris_udf
int main(int argc, char** argv) {
std::string conffile = std::string(getenv("DORIS_HOME")) + "/conf/be.conf";
if (!doris::config::init(conffile.c_str(), false)) {
fprintf(stderr, "error read config file. \n");
return -1;
}
init_glog("be-test");
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}