Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
udf-test-harness.h
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 
16 #ifndef IMPALA_UDF_TEST_HARNESS_H
17 #define IMPALA_UDF_TEST_HARNESS_H
18 
19 #include <iostream>
20 #include <vector>
21 #include <boost/function.hpp>
22 #include <boost/scoped_ptr.hpp>
23 
24 #include "udf/udf.h"
25 #include "udf/udf-debug.h"
26 
27 namespace impala_udf {
28 
31  public:
36  const std::vector<FunctionContext::TypeDesc>& arg_types);
37 
43  //
45  //
47  static void SetConstantArgs(
48  FunctionContext* context, const std::vector<AnyVal*>& constant_args);
49 
52  static void CloseContext(FunctionContext* context);
53 
58  //
62  template<typename RET>
63  static bool ValidateUdf(boost::function<RET(FunctionContext*)> fn,
64  const RET& expected, UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
65  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
66  FunctionContext::TypeDesc return_type; // TODO
67  std::vector<FunctionContext::TypeDesc> arg_types;
68  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
69  SetConstantArgs(context.get(), constant_args);
70  if (!RunPrepareFn(init_fn, context.get())) return false;
71  RET ret = fn(context.get());
72  RunCloseFn(close_fn, context.get());
73  return Validate(context.get(), expected, ret);
74  }
75 
76  template<typename RET, typename A1>
77  static bool ValidateUdf(boost::function<RET(FunctionContext*, const A1&)> fn,
78  const A1& a1, const RET& expected, UdfPrepare init_fn = NULL,
79  UdfClose close_fn = NULL,
80  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
81  FunctionContext::TypeDesc return_type; // TODO
82  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
83  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
84  SetConstantArgs(context.get(), constant_args);
85  if (!RunPrepareFn(init_fn, context.get())) return false;
86  RET ret = fn(context.get(), a1);
87  RunCloseFn(close_fn, context.get());
88  return Validate(context.get(), expected, ret);
89  }
90 
91  template<typename RET, typename A1>
92  static bool ValidateUdf(boost::function<RET(FunctionContext*, int, const A1*)> fn,
93  const std::vector<A1>& a1, const RET& expected, UdfPrepare init_fn = NULL,
94  UdfClose close_fn = NULL,
95  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
96  FunctionContext::TypeDesc return_type; // TODO
97  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
98  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
99  SetConstantArgs(context.get(), constant_args);
100  if (!RunPrepareFn(init_fn, context.get())) return false;
101  RET ret = fn(context.get(), a1.size(), &a1[0]);
102  RunCloseFn(close_fn, context.get());
103  return Validate(context.get(), expected, ret);
104  }
105 
106  template<typename RET, typename A1, typename A2>
107  static bool ValidateUdf(
108  boost::function<RET(FunctionContext*, const A1&, const A2&)> fn,
109  const A1& a1, const A2& a2, const RET& expected, UdfPrepare init_fn = NULL,
110  UdfClose close_fn = NULL,
111  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
112  FunctionContext::TypeDesc return_type; // TODO
113  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
114  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
115  SetConstantArgs(context.get(), constant_args);
116  if (!RunPrepareFn(init_fn, context.get())) return false;
117  RET ret = fn(context.get(), a1, a2);
118  RunCloseFn(close_fn, context.get());
119  return Validate(context.get(), expected, ret);
120  }
121 
122  template<typename RET, typename A1, typename A2>
123  static bool ValidateUdf(
124  boost::function<RET(FunctionContext*, const A1&, int, const A2*)> fn,
125  const A1& a1, const std::vector<A2>& a2, const RET& expected,
126  UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
127  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
128  FunctionContext::TypeDesc return_type; // TODO
129  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
130  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
131  SetConstantArgs(context.get(), constant_args);
132  if (!RunPrepareFn(init_fn, context.get())) return false;
133  RET ret = fn(context.get(), a1, a2.size(), &a2[0]);
134  RunCloseFn(close_fn, context.get());
135  return Validate(context.get(), expected, ret);
136  }
137 
138  template<typename RET, typename A1, typename A2, typename A3>
139  static bool ValidateUdf(
140  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&)> fn,
141  const A1& a1, const A2& a2, const A3& a3, const RET& expected,
142  UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
143  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
144  FunctionContext::TypeDesc return_type; // TODO
145  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
146  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
147  SetConstantArgs(context.get(), constant_args);
148  if (!RunPrepareFn(init_fn, context.get())) return false;
149  RET ret = fn(context.get(), a1, a2, a3);
150  RunCloseFn(close_fn, context.get());
151  return Validate(context.get(), expected, ret);
152  }
153 
154  template<typename RET, typename A1, typename A2, typename A3>
155  static bool ValidateUdf(
156  boost::function<RET(FunctionContext*, const A1&, const A2&, int, const A3*)> fn,
157  const A1& a1, const A2& a2, const std::vector<A3>& a3, const RET& expected,
158  UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
159  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
160  FunctionContext::TypeDesc return_type; // TODO
161  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
162  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
163  SetConstantArgs(context.get(), constant_args);
164  if (!RunPrepareFn(init_fn, context.get())) return false;
165  RET ret = fn(context.get(), a1, a2, a3.size(), &a3[0]);
166  RunCloseFn(close_fn, context.get());
167  return Validate(context.get(), expected, ret);
168  }
169 
170  template<typename RET, typename A1, typename A2, typename A3, typename A4>
171  static bool ValidateUdf(
172  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&,
173  const A4&)> fn,
174  const A1& a1, const A2& a2, const A3& a3, const A4& a4, const RET& expected,
175  UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
176  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
177  FunctionContext::TypeDesc return_type; // TODO
178  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
179  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
180  SetConstantArgs(context.get(), constant_args);
181  if (!RunPrepareFn(init_fn, context.get())) return false;
182  RET ret = fn(context.get(), a1, a2, a3, a4);
183  RunCloseFn(close_fn, context.get());
184  return Validate(context.get(), expected, ret);
185  }
186 
187  template<typename RET, typename A1, typename A2, typename A3, typename A4>
188  static bool ValidateUdf(
189  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&,
190  int, const A4*)> fn,
191  const A1& a1, const A2& a2, const A3& a3, const std::vector<A4>& a4,
192  const RET& expected, UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
193  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
194  FunctionContext::TypeDesc return_type; // TODO
195  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
196  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
197  SetConstantArgs(context.get(), constant_args);
198  if (!RunPrepareFn(init_fn, context.get())) return false;
199  RET ret = fn(context.get(), a1, a2, a3, a4.size(), &a4[0]);
200  RunCloseFn(close_fn, context.get());
201  return Validate(context.get(), expected, ret);
202  }
203 
204  template<typename RET, typename A1, typename A2, typename A3, typename A4,
205  typename A5>
206  static bool ValidateUdf(
207  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&,
208  const A4&, const A5&)> fn,
209  const A1& a1, const A2& a2, const A3& a3, const A4& a4,const A5& a5,
210  const RET& expected, UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
211  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
212  FunctionContext::TypeDesc return_type; // TODO
213  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
214  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
215  SetConstantArgs(context.get(), constant_args);
216  if (!RunPrepareFn(init_fn, context.get())) return false;
217  RET ret = fn(context.get(), a1, a2, a3, a4, a5);
218  RunCloseFn(close_fn, context.get());
219  return Validate(context.get(), expected, ret);
220  }
221 
222  template<typename RET, typename A1, typename A2, typename A3, typename A4,
223  typename A5, typename A6>
224  static bool ValidateUdf(
225  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&,
226  const A4&, const A5&, const A6&)> fn,
227  const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5,
228  const A6& a6, const RET& expected, UdfPrepare init_fn = NULL,
229  UdfClose close_fn = NULL,
230  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
231  FunctionContext::TypeDesc return_type; // TODO
232  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
233  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
234  SetConstantArgs(context.get(), constant_args);
235  if (!RunPrepareFn(init_fn, context.get())) return false;
236  RET ret = fn(context.get(), a1, a2, a3, a4, a5, a6);
237  RunCloseFn(close_fn, context.get());
238  return Validate(context.get(), expected, ret);
239  }
240 
241  template<typename RET, typename A1, typename A2, typename A3, typename A4,
242  typename A5, typename A6, typename A7>
243  static bool ValidateUdf(
244  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&,
245  const A4&, const A5&, const A6&, const A7&)> fn,
246  const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5,
247  const A6& a6, const A7& a7, const RET& expected, UdfPrepare init_fn = NULL,
248  UdfClose close_fn = NULL,
249  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
250  FunctionContext::TypeDesc return_type; // TODO
251  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
252  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
253  SetConstantArgs(context.get(), constant_args);
254  if (!RunPrepareFn(init_fn, context.get())) return false;
255  RET ret = fn(context.get(), a1, a2, a3, a4, a5, a6, a7);
256  RunCloseFn(close_fn, context.get());
257  return Validate(context.get(), expected, ret);
258  }
259 
260  template<typename RET, typename A1, typename A2, typename A3, typename A4,
261  typename A5, typename A6, typename A7, typename A8>
262  static bool ValidateUdf(
263  boost::function<RET(FunctionContext*, const A1&, const A2&, const A3&,
264  const A4&, const A5&, const A6&, const A7&)> fn,
265  const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5,
266  const A6& a6, const A7& a7, const A8& a8, const RET& expected,
267  UdfPrepare init_fn = NULL, UdfClose close_fn = NULL,
268  const std::vector<AnyVal*>& constant_args = std::vector<AnyVal*>()) {
269  FunctionContext::TypeDesc return_type; // TODO
270  std::vector<FunctionContext::TypeDesc> arg_types; // TODO
271  boost::scoped_ptr<FunctionContext> context(CreateTestContext(return_type, arg_types));
272  SetConstantArgs(context.get(), constant_args);
273  if (!RunPrepareFn(init_fn, context.get())) return false;
274  RET ret = fn(context.get(), a1, a2, a3, a4, a5, a6, a7, a8);
275  RunCloseFn(close_fn, context.get());
276  return Validate(context.get(), expected, ret);
277  }
278 
279  private:
280  static bool ValidateError(FunctionContext* context) {
281  if (context->has_error()) {
282  std::cerr << "Udf Failed: " << context->error_msg() << std::endl;
283  return false;
284  }
285  return true;
286  }
287 
288  template<typename RET>
289  static bool Validate(FunctionContext* context, const RET& expected, const RET& actual) {
290  bool valid = true;
291  if (!context->has_error() && actual != expected) {
292  std::cerr << "UDF did not return the correct result:" << std::endl
293  << " Expected: " << DebugString(expected) << std::endl
294  << " Actual: " << DebugString(actual) << std::endl;
295  valid = false;
296  }
297  CloseContext(context);
298  if (!ValidateError(context)) valid = false;
299  return valid;
300  }
301 
302  static bool RunPrepareFn(UdfPrepare prepare_fn, FunctionContext* context) {
303  if (prepare_fn != NULL) {
304  // TODO: FRAGMENT_LOCAL
305  prepare_fn(context, FunctionContext::THREAD_LOCAL);
306  if (!ValidateError(context)) return false;
307  }
308  return true;
309  }
310 
311  static void RunCloseFn(UdfClose close_fn, FunctionContext* context) {
312  if (close_fn != NULL) {
313  // TODO: FRAGMENT_LOCAL
314  close_fn(context, FunctionContext::THREAD_LOCAL);
315  }
316  }
317 };
318 
319 }
320 
321 #endif
void(* UdfClose)(FunctionContext *context, FunctionContext::FunctionStateScope scope)
Definition: udf.h:288
static void RunCloseFn(UdfClose close_fn, FunctionContext *context)
static bool Validate(FunctionContext *context, const RET &expected, const RET &actual)
Utility class to help test UDFs.
static FunctionContext * CreateTestContext(const FunctionContext::TypeDesc &return_type, const std::vector< FunctionContext::TypeDesc > &arg_types)
void(* UdfPrepare)(FunctionContext *context, FunctionContext::FunctionStateScope scope)
Definition: udf.h:275
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &)> fn, const A1 &a1, const A2 &a2, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
bool has_error() const
Returns true if there's been an error set.
Definition: udf.cc:253
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, int, const A3 *)> fn, const A1 &a1, const A2 &a2, const std::vector< A3 > &a3, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *)> fn, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static void SetConstantArgs(FunctionContext *context, const std::vector< AnyVal * > &constant_args)
The AnyVal* values are owned by the caller.
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, int, const A1 *)> fn, const std::vector< A1 > &a1, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &)> fn, const A1 &a1, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
std::string DebugString(const T &val)
Definition: udf-debug.h:27
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool RunPrepareFn(UdfPrepare prepare_fn, FunctionContext *context)
const char * error_msg() const
Returns the current error message. Returns NULL if there is no error.
Definition: udf.cc:257
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &, const A4 &)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, int, const A2 *)> fn, const A1 &a1, const std::vector< A2 > &a2, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &, int, const A4 *)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const std::vector< A4 > &a4, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateUdf(boost::function< RET(FunctionContext *, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)> fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const RET &expected, UdfPrepare init_fn=NULL, UdfClose close_fn=NULL, const std::vector< AnyVal * > &constant_args=std::vector< AnyVal * >())
static bool ValidateError(FunctionContext *context)
static void CloseContext(FunctionContext *context)