]>
git.proxmox.com Git - ceph.git/blob - ceph/src/s3select/test/s3select_test.cpp
2 #include "gtest/gtest.h"
4 #include "boost/date_time/gregorian/gregorian.hpp"
5 #include "boost/date_time/posix_time/posix_time.hpp"
7 using namespace s3selectEngine
;
9 std::string
run_expression_in_C_prog(const char* expression
)
11 //purpose: per use-case a c-file is generated, compiles , and finally executed.
13 // side note: its possible to do the following: cat test_hello.c | gcc -pipe -x c - -o /dev/stdout > ./1
14 // gcc can read and write from/to pipe (use pipe2()) i.e. not using file-system , BUT should also run gcc-output from memory
16 const int C_FILE_SIZE
=(1024*1024);
17 std::string c_test_file
= std::string("/tmp/test_s3.c");
18 std::string c_run_file
= std::string("/tmp/s3test");
20 FILE* fp_c_file
= fopen(c_test_file
.c_str(), "w");
22 //contain return result
23 char result_buff
[100];
29 prog_c
= (char*)malloc(C_FILE_SIZE
);
31 size_t sz
=sprintf(prog_c
, "#include <stdio.h>\n \
34 printf(\"%%f\\n\",(double)(%s));\
37 int status
= fwrite(prog_c
, 1, sz
, fp_c_file
);
41 std::string gcc_and_run_cmd
= std::string("gcc ") + c_test_file
+ " -o " + c_run_file
+ " -Wall && " + c_run_file
;
43 FILE* fp_build
= popen(gcc_and_run_cmd
.c_str(), "r"); //TODO read stderr from pipe
47 return std::string("#ERROR#");
50 fgets(result_buff
, sizeof(result_buff
), fp_build
);
52 unlink(c_run_file
.c_str());
53 unlink(c_test_file
.c_str());
55 return std::string(result_buff
);
58 #define OPER oper[ rand() % oper.size() ]
66 std::string oper
= {"+-+*/*"};
70 return std::to_string(rand() % 1000) + ".0" + OPER
+ std::to_string(rand() % 1000) + ".0";
75 if ((rand() % 3) == 0)
78 return std::string("(");
80 return std::string("");
83 std::string
g_closep()
85 if ((rand() % 2) == 0 && open
> 0)
88 return std::string(")");
90 return std::string("");
95 std::string
generate()
100 for (int i
= 0; i
< 10; i
++)
102 exp
= (exp
.size() > 0 ? exp
+ OPER
: std::string("")) + g_openp() + gexpr() + OPER
+ gexpr() + g_closep();
115 std::string
run_s3select(std::string expression
)
117 s3select s3select_syntax
;
119 s3select_syntax
.parse_query(expression
.c_str());
121 std::string s3select_result
;
122 s3selectEngine::csv_object
s3_csv_object(&s3select_syntax
);
123 std::string in
= "1,1,1,1\n";
125 s3_csv_object
.run_s3select_on_object(s3select_result
, in
.c_str(), in
.size(), false, false, true);
127 s3select_result
= s3select_result
.substr(0, s3select_result
.find_first_of(","));
129 return s3select_result
;
132 TEST(TestS3SElect
, s3select_vs_C
)
134 //purpose: validate correct processing of arithmetical expression, it is done by running the same expression
136 // the test validate that syntax and execution-tree (including precedence rules) are done correctly
138 for(int y
=0; y
<10; y
++)
141 std::string exp
= g
.generate();
142 std::string c_result
= run_expression_in_C_prog( exp
.c_str() );
145 double c_dbl_res
= strtod(c_result
.c_str(), &err
);
147 std::string input_query
= "select " + exp
+ " from stdin;" ;
148 std::string s3select_res
= run_s3select(input_query
);
150 double s3select_dbl_res
= strtod(s3select_res
.c_str(), &err
);
152 //std::cout << exp << " " << s3select_dbl_res << " " << s3select_res << " " << c_dbl_res/s3select_dbl_res << std::endl;
153 //std::cout << exp << std::endl;
155 ASSERT_EQ(c_dbl_res
, s3select_dbl_res
);
159 TEST(TestS3SElect
, ParseQuery
)
161 //TODO syntax issues ?
162 //TODO error messeges ?
164 s3select s3select_syntax
;
166 run_s3select(std::string("select (1+1) from stdin;"));
171 TEST(TestS3SElect
, int_compare_operator
)
173 value
a10(10), b11(11), c10(10);
175 ASSERT_EQ( a10
< b11
, true );
176 ASSERT_EQ( a10
> b11
, false );
177 ASSERT_EQ( a10
>= c10
, true );
178 ASSERT_EQ( a10
<= c10
, true );
179 ASSERT_EQ( a10
!= b11
, true );
180 ASSERT_EQ( a10
== b11
, false );
181 ASSERT_EQ( a10
== c10
, true );
184 TEST(TestS3SElect
, float_compare_operator
)
186 value
a10(10.1), b11(11.2), c10(10.1);
188 ASSERT_EQ( a10
< b11
, true );
189 ASSERT_EQ( a10
> b11
, false );
190 ASSERT_EQ( a10
>= c10
, true );
191 ASSERT_EQ( a10
<= c10
, true );
192 ASSERT_EQ( a10
!= b11
, true );
193 ASSERT_EQ( a10
== b11
, false );
194 ASSERT_EQ( a10
== c10
, true );
198 TEST(TestS3SElect
, string_compare_operator
)
200 value
s1("abc"), s2("def"), s3("abc");
202 ASSERT_EQ( s1
< s2
, true );
203 ASSERT_EQ( s1
> s2
, false );
204 ASSERT_EQ( s1
<= s3
, true );
205 ASSERT_EQ( s1
>= s3
, true );
206 ASSERT_EQ( s1
!= s2
, true );
207 ASSERT_EQ( s1
== s3
, true );
208 ASSERT_EQ( s1
== s2
, false );
211 TEST(TestS3SElect
, arithmetic_operator
)
213 value
a(1), b(2), c(3), d(4);
215 ASSERT_EQ( (a
+b
).i64(), 3 );
217 ASSERT_EQ( (value(0)-value(2)*value(4)).i64(), -8 );
218 ASSERT_EQ( (value(1.23)-value(0.1)*value(2)).dbl(), 1.03 );
220 a
=int64_t(1); //a+b modify a
221 ASSERT_EQ( ( (a
+b
) * (c
+d
) ).i64(), 21 );
224 TEST(TestS3SElect
, timestamp_function
)
226 // TODO: support formats listed here:
227 // https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-glacier-select-sql-reference-date.html#s3-glacier-select-sql-reference-to-timestamp
228 const std::string timestamp
= "2007-02-23:14:33:01";
229 // TODO: out_simestamp should be the same as timestamp
230 const std::string out_timestamp
= "2007-Feb-23 14:33:01";
231 const std::string input_query
= "select timestamp(\"" + timestamp
+ "\") from stdin;" ;
232 std::string s3select_res
= run_s3select(input_query
);
233 ASSERT_EQ(s3select_res
, out_timestamp
);
236 TEST(TestS3SElect
, utcnow_function
)
238 const boost::posix_time::ptime
now(boost::posix_time::second_clock::universal_time());
239 const std::string input_query
= "select utcnow() from stdin;" ;
240 auto s3select_res
= run_s3select(input_query
);
241 const boost::posix_time::ptime res_now
;
242 ASSERT_EQ(s3select_res
, boost::posix_time::to_simple_string(now
));