Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
udf-test.cc
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <gtest/gtest.h>
16 #include <iostream>
17 #include <boost/date_time/posix_time/posix_time.hpp>
18 
19 #include "common/logging.h"
21 #include "testutil/test-udfs.h"
22 #include "udf/udf-test-harness.h"
23 
24 #include "common/names.h"
25 
26 using boost::gregorian::date;
27 using boost::posix_time::nanoseconds;
28 using boost::posix_time::ptime;
29 using boost::posix_time::to_iso_extended_string;
30 using boost::posix_time::to_simple_string;
31 using namespace impala;
32 using namespace impala_udf;
33 
35  return DoubleVal(0);
36 }
37 
38 StringVal LogUdf(FunctionContext* context, const StringVal& arg1) {
39  cerr << (arg1.is_null ? "NULL" : string((char*)arg1.ptr, arg1.len)) << endl;
40  return arg1;
41 }
42 
43 StringVal UpperUdf(FunctionContext* context, const StringVal& input) {
44  if (input.is_null) return StringVal::null();
45  // Create a new StringVal object that's the same length as the input
46  StringVal result = StringVal(context, input.len);
47  for (int i = 0; i < input.len; ++i) {
48  result.ptr[i] = toupper(input.ptr[i]);
49  }
50  return result;
51 }
52 
53 FloatVal Min3(FunctionContext* context, const FloatVal& f1,
54  const FloatVal& f2, const FloatVal& f3) {
55  bool is_null = true;
56  float v = 0;
57  if (!f1.is_null) {
58  if (is_null) {
59  v = f1.val;
60  is_null = false;
61  } else {
62  v = std::min(v, f1.val);
63  }
64  }
65  if (!f2.is_null) {
66  if (is_null) {
67  v = f2.val;
68  is_null = false;
69  } else {
70  v = std::min(v, f2.val);
71  }
72  }
73  if (!f3.is_null) {
74  if (is_null) {
75  v = f3.val;
76  is_null = false;
77  } else {
78  v = std::min(v, f3.val);
79  }
80  }
81  return is_null ? FloatVal::null() : FloatVal(v);
82 }
83 
84 StringVal Concat(FunctionContext* context, int n, const StringVal* args) {
85  int size = 0;
86  bool all_null = true;
87  for (int i = 0; i < n; ++i) {
88  if (args[i].is_null) continue;
89  size += args[i].len;
90  all_null = false;
91  }
92  if (all_null) return StringVal::null();
93 
94  int offset = 0;
95  StringVal result(context, size);
96  for (int i = 0; i < n; ++i) {
97  if (args[i].is_null) continue;
98  memcpy(result.ptr + offset, args[i].ptr, args[i].len);
99  offset += args[i].len;
100  }
101  return result;
102 }
103 
104 IntVal NumVarArgs(FunctionContext*, const BigIntVal& dummy, int n, const IntVal* args) {
105  return IntVal(n);
106 }
107 
109  EXPECT_EQ(context->version(), FunctionContext::v1_3);
110  EXPECT_FALSE(context->has_error()) << context->error_msg();
111  EXPECT_TRUE(context->error_msg() == NULL);
112  return IntVal::null();
113 }
114 
116  EXPECT_FALSE(context->has_error());
117  EXPECT_TRUE(context->error_msg() == NULL);
118  context->SetError("Fail");
119  EXPECT_TRUE(context->has_error());
120  EXPECT_TRUE(strcmp(context->error_msg(), "Fail") == 0);
121  return IntVal::null();
122 }
123 
125  EXPECT_TRUE(context->Allocate(0) == NULL);
126  uint8_t* buffer = context->Allocate(10);
127  EXPECT_TRUE(buffer != NULL);
128  memset(buffer, 0, 10);
129  context->Free(buffer);
130  return IntVal::null();
131 }
132 
134  ptime t(*(date*)&time.date);
135  t += nanoseconds(time.time_of_day);
136  stringstream ss;
137  ss << to_iso_extended_string(t.date()) << " " << to_simple_string(t.time_of_day());
138  string s = ss.str();
139  StringVal result(context, s.size());
140  memcpy(result.ptr, s.data(), result.len);
141  return result;
142 }
143 
146  if (scope == FunctionContext::THREAD_LOCAL) {
147  // TODO: NYI
148  // const FunctionContext::TypeDesc* arg_type = context->GetArgType(0);
149  // ASSERT_TRUE(arg_type != NULL);
150  // ASSERT_EQ(arg_type->type, FunctionContext::TYPE_SMALLINT);
151  SmallIntVal* bytes = reinterpret_cast<SmallIntVal*>(context->GetConstantArg(0));
152  ASSERT_TRUE(bytes != NULL);
153  uint8_t* state = context->Allocate(bytes->val);
154  context->SetFunctionState(scope, state);
155  }
156 }
157 
159  void* state = context->GetFunctionState(FunctionContext::THREAD_LOCAL);
160  EXPECT_TRUE(state != NULL);
161  memset(state, 0, bytes.val);
162  return SmallIntVal::null();
163 }
164 
167  if (scope == FunctionContext::THREAD_LOCAL) {
168  void* state = context->GetFunctionState(scope);
169  context->Free(reinterpret_cast<uint8_t*>(state));
170  context->SetFunctionState(scope, NULL);
171  }
172 }
173 
174 TEST(UdfTest, TestFunctionContext) {
175  EXPECT_TRUE(UdfTestHarness::ValidateUdf<IntVal>(ValidateUdf, IntVal::null()));
176  EXPECT_FALSE(UdfTestHarness::ValidateUdf<IntVal>(ValidateFail, IntVal::null()));
177  EXPECT_TRUE(UdfTestHarness::ValidateUdf<IntVal>(ValidateMem, IntVal::null()));
178 
179  scoped_ptr<SmallIntVal> arg(new SmallIntVal(100));
180  vector<AnyVal*> constant_args;
181  constant_args.push_back(arg.get());
182  EXPECT_TRUE((UdfTestHarness::ValidateUdf<SmallIntVal, SmallIntVal>(
183  ValidateSharedState, *arg, SmallIntVal::null(),
185 }
186 
187 TEST(UdfTest, TestValidate) {
188  EXPECT_TRUE(UdfTestHarness::ValidateUdf<DoubleVal>(ZeroUdf, DoubleVal(0)));
189  EXPECT_FALSE(UdfTestHarness::ValidateUdf<DoubleVal>(ZeroUdf, DoubleVal(10)));
190 
191  EXPECT_TRUE((UdfTestHarness::ValidateUdf<StringVal, StringVal>(
192  LogUdf, StringVal("abcd"), StringVal("abcd"))));
193 
194  EXPECT_TRUE((UdfTestHarness::ValidateUdf<StringVal, StringVal>(
195  UpperUdf, StringVal("abcd"), StringVal("ABCD"))));
196 
197  EXPECT_TRUE((UdfTestHarness::ValidateUdf<FloatVal, FloatVal, FloatVal, FloatVal>(
198  Min3, FloatVal(1), FloatVal(2), FloatVal(3), FloatVal(1))));
199  EXPECT_TRUE((UdfTestHarness::ValidateUdf<FloatVal, FloatVal, FloatVal, FloatVal>(
200  Min3, FloatVal(1), FloatVal::null(), FloatVal(3), FloatVal(1))));
201  EXPECT_TRUE((UdfTestHarness::ValidateUdf<FloatVal, FloatVal, FloatVal, FloatVal>(
202  Min3, FloatVal::null(), FloatVal::null(), FloatVal::null(), FloatVal::null())));
203 }
204 
205 TEST(UdfTest, TestTimestampVal) {
206  date d(2003, 3, 15);
207  TimestampVal t1(*(int32_t*)&d);
208  EXPECT_TRUE((UdfTestHarness::ValidateUdf<StringVal, TimestampVal>(
209  TimeToString, t1, "2003-03-15 00:00:00")));
210 
211  TimestampVal t2(*(int32_t*)&d, 1000L * 1000L * 5000L);
212  EXPECT_TRUE((UdfTestHarness::ValidateUdf<StringVal, TimestampVal>(
213  TimeToString, t2, "2003-03-15 00:00:05")));
214 }
215 
216 TEST(UdfTest, TestDecimalVal) {
217  DecimalVal d1(static_cast<int32_t>(1));
218  DecimalVal d2(static_cast<int32_t>(-1));
219  DecimalVal d3(static_cast<int64_t>(1));
220  DecimalVal d4(static_cast<int64_t>(-1));
221  DecimalVal d5(static_cast<int128_t>(1));
222  DecimalVal d6(static_cast<int128_t>(-1));
223  DecimalVal null1 = DecimalVal::null();
224  DecimalVal null2 = DecimalVal::null();
225 
226  // TODO: replace these manual comparisons with a DecimalVal equality function
227  // 1 != -1
228  EXPECT_NE(d1.val16, d2.val16);
229  EXPECT_NE(d3.val16, d4.val16);
230  EXPECT_NE(d5.val16, d6.val16);
231 
232  // 1 == 1
233  EXPECT_EQ(d1.val16, d3.val16);
234  EXPECT_EQ(d1.val16, d5.val16);
235  EXPECT_EQ(d3.val16, d5.val16);
236 
237  // -1 == -1
238  EXPECT_EQ(d2.val16, d4.val16);
239  EXPECT_EQ(d2.val16, d6.val16);
240  EXPECT_EQ(d4.val16, d6.val16);
241 
242  // nulls
243  EXPECT_EQ(null1.is_null, null2.is_null);
244  EXPECT_NE(null1.is_null, d1.is_null);
245 }
246 
247 TEST(UdfTest, TestVarArgs) {
248  vector<StringVal> input;
249  input.push_back(StringVal("Hello"));
250  input.push_back(StringVal("World"));
251 
252  EXPECT_TRUE((UdfTestHarness::ValidateUdf<StringVal, StringVal>(
253  Concat, input, StringVal("HelloWorld"))));
254 
255  input.push_back(StringVal("More"));
256  EXPECT_TRUE((UdfTestHarness::ValidateUdf<StringVal, StringVal>(
257  Concat, input, StringVal("HelloWorldMore"))));
258 
259  vector<IntVal> args;
260  args.resize(10);
261  EXPECT_TRUE((UdfTestHarness::ValidateUdf<IntVal, BigIntVal, IntVal>(
262  NumVarArgs, BigIntVal(0), args, IntVal(args.size()))));
263 }
264 
265 TEST(UdfTest, MemTest) {
266  BigIntVal bytes_arg(1000);
267 
268  EXPECT_TRUE((UdfTestHarness::ValidateUdf<BigIntVal, BigIntVal>(
269  ::MemTest, bytes_arg, bytes_arg, ::MemTestPrepare, ::MemTestClose)));
270 
271  EXPECT_FALSE((UdfTestHarness::ValidateUdf<BigIntVal, BigIntVal>(
272  ::MemTest, bytes_arg, bytes_arg, ::MemTestPrepare, NULL)));
273 
274  EXPECT_FALSE((UdfTestHarness::ValidateUdf<BigIntVal, BigIntVal>(
275  ::DoubleFreeTest, bytes_arg, bytes_arg)));
276 
277 }
278 
279 int main(int argc, char** argv) {
281  ::testing::InitGoogleTest(&argc, argv);
282  return RUN_ALL_TESTS();
283 }
int main(int argc, char **argv)
Definition: udf-test.cc:279
BigIntVal MemTest(FunctionContext *context, const BigIntVal &bytes)
Definition: test-udfs.cc:260
int64_t time_of_day
Nanoseconds in current day.
Definition: udf.h:499
IntVal ValidateFail(FunctionContext *context)
Definition: udf-test.cc:115
void MemTestPrepare(FunctionContext *context, FunctionContext::FunctionStateScope scope)
Definition: test-udfs.cc:251
__int128_t val16
Definition: udf.h:572
TEST(AtomicTest, Basic)
Definition: atomic-test.cc:28
bool has_error() const
Returns true if there's been an error set.
Definition: udf.cc:253
StringVal TimeToString(FunctionContext *context, const TimestampVal &time)
Definition: udf-test.cc:133
FloatVal Min3(FunctionContext *context, const FloatVal &f1, const FloatVal &f2, const FloatVal &f3)
Definition: udf-test.cc:53
int32_t date
Gregorian date. This has the same binary format as boost::gregorian::date.
Definition: udf.h:497
This object has a compatible storage format with boost::ptime.
Definition: udf.h:495
uint8_t * ptr
Definition: udf.h:523
ImpalaVersion version() const
Returns the version of Impala that's currently running.
Definition: udf.cc:233
bool is_null
Definition: udf.h:359
StringVal LogUdf(FunctionContext *context, const StringVal &arg1)
Definition: udf-test.cc:38
void InitGoogleLoggingSafe(const char *arg)
Definition: logging.cc:55
void * GetFunctionState(FunctionStateScope scope) const
Definition: udf-ir.cc:38
void Free(uint8_t *buffer)
Frees a buffer returned from Allocate() or Reallocate()
Definition: udf.cc:291
void SetFunctionState(FunctionStateScope scope, void *ptr)
Definition: udf.cc:370
DoubleVal ZeroUdf(FunctionContext *context)
Definition: udf-test.cc:34
IntVal ValidateMem(FunctionContext *context)
Definition: udf-test.cc:124
const char * error_msg() const
Returns the current error message. Returns NULL if there is no error.
Definition: udf.cc:257
SmallIntVal ValidateSharedState(FunctionContext *context, SmallIntVal bytes)
Definition: udf-test.cc:158
uint8_t * Allocate(int byte_size)
Definition: udf.cc:262
uint8_t offset[7 *64-sizeof(uint64_t)]
void MemTestClose(FunctionContext *context, FunctionContext::FunctionStateScope scope)
Definition: test-udfs.cc:268
IntVal ValidateUdf(FunctionContext *context)
Definition: udf-test.cc:108
void SetError(const char *error_msg)
Definition: udf.cc:332
void ValidateSharedStateClose(FunctionContext *context, FunctionContext::FunctionStateScope scope)
Definition: udf-test.cc:165
void ValidateSharedStatePrepare(FunctionContext *context, FunctionContext::FunctionStateScope scope)
Definition: udf-test.cc:144
BigIntVal DoubleFreeTest(FunctionContext *context, BigIntVal bytes)
Definition: test-udfs.cc:278
AnyVal * GetConstantArg(int arg_idx) const
Definition: udf-ir.cc:25
StringVal Concat(FunctionContext *context, int n, const StringVal *args)
Definition: udf-test.cc:84
IntVal NumVarArgs(FunctionContext *, const BigIntVal &dummy, int n, const IntVal *args)
Definition: udf-test.cc:104
StringVal UpperUdf(FunctionContext *context, const StringVal &input)
Definition: udf-test.cc:43