]> git.proxmox.com Git - ceph.git/blob - ceph/src/s3select/test/s3select_test.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / s3select / test / s3select_test.cpp
1 #include "s3select.h"
2 #include "gtest/gtest.h"
3 #include <string>
4 #include "boost/date_time/gregorian/gregorian.hpp"
5 #include "boost/date_time/posix_time/posix_time.hpp"
6
7 using namespace s3selectEngine;
8
9 std::string run_expression_in_C_prog(const char* expression)
10 {
11 //purpose: per use-case a c-file is generated, compiles , and finally executed.
12
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
15
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");
19
20 FILE* fp_c_file = fopen(c_test_file.c_str(), "w");
21
22 //contain return result
23 char result_buff[100];
24
25 char* prog_c;
26
27 if(fp_c_file)
28 {
29 prog_c = (char*)malloc(C_FILE_SIZE);
30
31 size_t sz=sprintf(prog_c, "#include <stdio.h>\n \
32 int main() \
33 {\
34 printf(\"%%f\\n\",(double)(%s));\
35 } ", expression);
36
37 int status = fwrite(prog_c, 1, sz, fp_c_file);
38 fclose(fp_c_file);
39 }
40
41 std::string gcc_and_run_cmd = std::string("gcc ") + c_test_file + " -o " + c_run_file + " -Wall && " + c_run_file;
42
43 FILE* fp_build = popen(gcc_and_run_cmd.c_str(), "r"); //TODO read stderr from pipe
44
45 if(!fp_build)
46 {
47 return std::string("#ERROR#");
48 }
49
50 fgets(result_buff, sizeof(result_buff), fp_build);
51
52 unlink(c_run_file.c_str());
53 unlink(c_test_file.c_str());
54
55 return std::string(result_buff);
56 }
57
58 #define OPER oper[ rand() % oper.size() ]
59
60 class gen_expr
61 {
62
63 private:
64
65 int open = 0;
66 std::string oper= {"+-+*/*"};
67
68 std::string gexpr()
69 {
70 return std::to_string(rand() % 1000) + ".0" + OPER + std::to_string(rand() % 1000) + ".0";
71 }
72
73 std::string g_openp()
74 {
75 if ((rand() % 3) == 0)
76 {
77 open++;
78 return std::string("(");
79 }
80 return std::string("");
81 }
82
83 std::string g_closep()
84 {
85 if ((rand() % 2) == 0 && open > 0)
86 {
87 open--;
88 return std::string(")");
89 }
90 return std::string("");
91 }
92
93 public:
94
95 std::string generate()
96 {
97 std::string exp = "";
98 open = 0;
99
100 for (int i = 0; i < 10; i++)
101 {
102 exp = (exp.size() > 0 ? exp + OPER : std::string("")) + g_openp() + gexpr() + OPER + gexpr() + g_closep();
103 }
104
105 if (open)
106 for (; open--;)
107 {
108 exp += ")";
109 }
110
111 return exp;
112 }
113 };
114
115 std::string run_s3select(std::string expression)
116 {
117 s3select s3select_syntax;
118
119 s3select_syntax.parse_query(expression.c_str());
120
121 std::string s3select_result;
122 s3selectEngine::csv_object s3_csv_object(&s3select_syntax);
123 std::string in = "1,1,1,1\n";
124
125 s3_csv_object.run_s3select_on_object(s3select_result, in.c_str(), in.size(), false, false, true);
126
127 s3select_result = s3select_result.substr(0, s3select_result.find_first_of(","));
128
129 return s3select_result;
130 }
131
132 TEST(TestS3SElect, s3select_vs_C)
133 {
134 //purpose: validate correct processing of arithmetical expression, it is done by running the same expression
135 // in C program.
136 // the test validate that syntax and execution-tree (including precedence rules) are done correctly
137
138 for(int y=0; y<10; y++)
139 {
140 gen_expr g;
141 std::string exp = g.generate();
142 std::string c_result = run_expression_in_C_prog( exp.c_str() );
143
144 char* err=0;
145 double c_dbl_res = strtod(c_result.c_str(), &err);
146
147 std::string input_query = "select " + exp + " from stdin;" ;
148 std::string s3select_res = run_s3select(input_query);
149
150 double s3select_dbl_res = strtod(s3select_res.c_str(), &err);
151
152 //std::cout << exp << " " << s3select_dbl_res << " " << s3select_res << " " << c_dbl_res/s3select_dbl_res << std::endl;
153 //std::cout << exp << std::endl;
154
155 ASSERT_EQ(c_dbl_res, s3select_dbl_res);
156 }
157 }
158
159 TEST(TestS3SElect, ParseQuery)
160 {
161 //TODO syntax issues ?
162 //TODO error messeges ?
163
164 s3select s3select_syntax;
165
166 run_s3select(std::string("select (1+1) from stdin;"));
167
168 ASSERT_EQ(0, 0);
169 }
170
171 TEST(TestS3SElect, int_compare_operator)
172 {
173 value a10(10), b11(11), c10(10);
174
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 );
182 }
183
184 TEST(TestS3SElect, float_compare_operator)
185 {
186 value a10(10.1), b11(11.2), c10(10.1);
187
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 );
195
196 }
197
198 TEST(TestS3SElect, string_compare_operator)
199 {
200 value s1("abc"), s2("def"), s3("abc");
201
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 );
209 }
210
211 TEST(TestS3SElect, arithmetic_operator)
212 {
213 value a(1), b(2), c(3), d(4);
214
215 ASSERT_EQ( (a+b).i64(), 3 );
216
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 );
219
220 a=int64_t(1); //a+b modify a
221 ASSERT_EQ( ( (a+b) * (c+d) ).i64(), 21 );
222 }
223
224 TEST(TestS3SElect, timestamp_function)
225 {
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);
234 }
235
236 TEST(TestS3SElect, utcnow_function)
237 {
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));
243 }
244