1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "../lua_engine.h"
18
19 #include <gtest/gtest.h>
20
21 #include <iostream>
22 #include <sstream>
23 #include <string>
24 #include <vector>
25
26 namespace lua_interpreter {
27 namespace tests {
28
29 // The fixture for testing class LuaEngine
30 class LuaEngineTest : public testing::Test {
31 protected:
32 lua_interpreter::LuaEngine lua_engine_;
33
ConvertVectorToString(std::vector<std::string> vector)34 std::string ConvertVectorToString(std::vector<std::string> vector) {
35 std::stringstream output;
36 for (std::string s : vector) {
37 output << s;
38 }
39 return output.str();
40 }
41
ConvertArrayToString(char ** array,int size)42 std::string ConvertArrayToString(char** array, int size) {
43 std::stringstream output;
44 for (int i = 0; i < size; i++) {
45 output << array[i];
46 }
47 return output.str();
48 }
49 };
50
TEST_F(LuaEngineTest,ExecuteScriptLogCallback)51 TEST_F(LuaEngineTest, ExecuteScriptLogCallback) {
52 std::vector<std::string> output = lua_engine_.ExecuteScript(
53 "function test(data, state) log('Logging here') end", "test", "{}", "{}");
54 std::string actual = ConvertVectorToString(output);
55 EXPECT_NE(actual.find("LUA: Logging here"), std::string::npos);
56 }
57
TEST_F(LuaEngineTest,ExecuteScriptOnSuccessMoreArguments)58 TEST_F(LuaEngineTest, ExecuteScriptOnSuccessMoreArguments) {
59 std::vector<std::string> output = lua_engine_.ExecuteScript(
60 "function test(data, state) on_success({}, {}) end", "test", "{}", "{}");
61 std::string actual = ConvertVectorToString(output);
62 EXPECT_NE(actual.find("on_success can push only a single parameter from "
63 "Lua - a Lua table"),
64 std::string::npos);
65 }
66
TEST_F(LuaEngineTest,ExecuteScriptOnSuccessNonTable)67 TEST_F(LuaEngineTest, ExecuteScriptOnSuccessNonTable) {
68 std::vector<std::string> output = lua_engine_.ExecuteScript(
69 "function test(data, state) on_success('Success!') end", "test", "{}",
70 "{}");
71 std::string actual = ConvertVectorToString(output);
72 EXPECT_NE(actual.find("on_success can push only a single parameter from "
73 "Lua - a Lua table"),
74 std::string::npos);
75 }
76
TEST_F(LuaEngineTest,ExecuteScriptOnSuccessWithPopulatedTable)77 TEST_F(LuaEngineTest, ExecuteScriptOnSuccessWithPopulatedTable) {
78 std::vector<std::string> output = lua_engine_.ExecuteScript(
79 "function test(data, state) tbl = {}; tbl['sessionId'] = 1; "
80 "on_success(tbl) end",
81 "test", "{}", "{}");
82 std::string saved_state = lua_engine_.GetSavedState();
83 EXPECT_EQ("{\"sessionId\":1}\n", saved_state);
84 }
85
TEST_F(LuaEngineTest,ExecuteScriptOnSuccessWithEmptyTable)86 TEST_F(LuaEngineTest, ExecuteScriptOnSuccessWithEmptyTable) {
87 std::vector<std::string> output = lua_engine_.ExecuteScript(
88 "function test(data, state) tbl = {}; "
89 "on_success(tbl) end",
90 "test", "{}", "{}");
91 std::string saved_state = lua_engine_.GetSavedState();
92 EXPECT_EQ("[]\n", saved_state);
93 }
94
TEST_F(LuaEngineTest,ExecuteScriptOnScriptFinishedMoreArguments)95 TEST_F(LuaEngineTest, ExecuteScriptOnScriptFinishedMoreArguments) {
96 std::vector<std::string> output = lua_engine_.ExecuteScript(
97 "function test(data, state) on_script_finished({}, {}) end", "test", "{}",
98 "{}");
99 std::string actual = ConvertVectorToString(output);
100 EXPECT_NE(actual.find("on_script_finished can push only a single parameter "
101 "from Lua - a Lua "
102 "table"),
103 std::string::npos);
104 }
105
TEST_F(LuaEngineTest,ExecuteScriptOnScriptFinishedNonTable)106 TEST_F(LuaEngineTest, ExecuteScriptOnScriptFinishedNonTable) {
107 std::vector<std::string> output = lua_engine_.ExecuteScript(
108 "function test(data, state) on_script_finished('Script "
109 "finished') end",
110 "test", "{}", "{}");
111 std::string actual = ConvertVectorToString(output);
112 EXPECT_NE(actual.find("on_script_finished can push only a single parameter "
113 "from Lua - a Lua "
114 "table"),
115 std::string::npos);
116 }
117
TEST_F(LuaEngineTest,ExecuteScriptOnScriptFinishedWithTable)118 TEST_F(LuaEngineTest, ExecuteScriptOnScriptFinishedWithTable) {
119 std::vector<std::string> output = lua_engine_.ExecuteScript(
120 "function test(data, state) tbl = {}; tbl['sessionId'] = 1; "
121 "on_script_finished(tbl) "
122 "end",
123 "test", "{}", "{}");
124 std::string actual = ConvertVectorToString(output);
125 EXPECT_NE(actual.find("{\"sessionId\":1}"), std::string::npos);
126 }
127
TEST_F(LuaEngineTest,ExecuteScriptOnErrorMoreArguments)128 TEST_F(LuaEngineTest, ExecuteScriptOnErrorMoreArguments) {
129 std::vector<std::string> output = lua_engine_.ExecuteScript(
130 "function test(data, state) on_error('ERROR ONE', 'ERROR "
131 "TWO') end",
132 "test", "{}", "{}");
133 std::string actual = ConvertVectorToString(output);
134 EXPECT_NE(
135 actual.find("on_error can push only a single string parameter from Lua"),
136 std::string::npos);
137 }
138
TEST_F(LuaEngineTest,ExecuteScriptOnErrorNonString)139 TEST_F(LuaEngineTest, ExecuteScriptOnErrorNonString) {
140 std::vector<std::string> output = lua_engine_.ExecuteScript(
141 "function test(data, state) on_error({}) end", "test", "{}", "{}");
142 std::string actual = ConvertVectorToString(output);
143 EXPECT_NE(
144 actual.find("on_error can push only a single string parameter from Lua"),
145 std::string::npos);
146 }
147
TEST_F(LuaEngineTest,ExecuteScriptOnErrorWithSingleString)148 TEST_F(LuaEngineTest, ExecuteScriptOnErrorWithSingleString) {
149 std::vector<std::string> output = lua_engine_.ExecuteScript(
150 "function test(data, state) on_error('ERROR: 2') end", "test", "{}",
151 "{}");
152 std::string actual = ConvertVectorToString(output);
153 EXPECT_NE(actual.find("ERROR: 2"), std::string::npos);
154 }
155
TEST_F(LuaEngineTest,ExecuteScriptOnMetricsReportMoreArguments)156 TEST_F(LuaEngineTest, ExecuteScriptOnMetricsReportMoreArguments) {
157 std::vector<std::string> output = lua_engine_.ExecuteScript(
158 "function test(data, state) on_metrics_report({}, {}, {}) end", "test",
159 "{}", "{}");
160 std::string actual = ConvertVectorToString(output);
161 EXPECT_NE(
162 actual.find(
163 "on_metrics_report should push 1 to 2 parameters of Lua table type. "
164 "The first table is a metrics report and the second is an optional "
165 "state to save"),
166 std::string::npos);
167 }
168
TEST_F(LuaEngineTest,ExecuteScriptOnMetricsReportNonTable)169 TEST_F(LuaEngineTest, ExecuteScriptOnMetricsReportNonTable) {
170 std::vector<std::string> output = lua_engine_.ExecuteScript(
171 "function test(data, state) on_metrics_report('Incoming "
172 "metrics report') "
173 "end",
174 "test", "{}", "{}");
175 std::string actual = ConvertVectorToString(output);
176 EXPECT_NE(
177 actual.find(
178 "on_metrics_report should push 1 to 2 parameters of Lua table type. "
179 "The first table is a metrics report and the second is an optional "
180 "state to save"),
181 std::string::npos);
182 }
183
TEST_F(LuaEngineTest,ExecuteScriptOnMetricsReportNonTableWithTable)184 TEST_F(LuaEngineTest, ExecuteScriptOnMetricsReportNonTableWithTable) {
185 std::vector<std::string> output = lua_engine_.ExecuteScript(
186 "function test(data, state) on_metrics_report('Incoming "
187 "metrics report', "
188 "{}) end",
189 "test", "{}", "{}");
190 std::string actual = ConvertVectorToString(output);
191 EXPECT_NE(
192 actual.find(
193 "on_metrics_report should push 1 to 2 parameters of Lua table type. "
194 "The first table is a metrics report and the second is an optional "
195 "state to save"),
196 std::string::npos);
197 }
198
TEST_F(LuaEngineTest,ExecuteScriptOnMetricsReportTableWithNonTable)199 TEST_F(LuaEngineTest, ExecuteScriptOnMetricsReportTableWithNonTable) {
200 std::vector<std::string> output = lua_engine_.ExecuteScript(
201 "function test(data, state) on_metrics_report({}, 'Saved "
202 "state here') "
203 "end",
204 "test", "{}", "{}");
205 std::string actual = ConvertVectorToString(output);
206 EXPECT_NE(
207 actual.find(
208 "on_metrics_report should push 1 to 2 parameters of Lua table "
209 "type. "
210 "The first table is a metrics report and the second is an optional "
211 "state to save"),
212 std::string::npos);
213 }
214
TEST_F(LuaEngineTest,ExecuteScriptOnMetricsReportSingleTable)215 TEST_F(LuaEngineTest, ExecuteScriptOnMetricsReportSingleTable) {
216 std::vector<std::string> output = lua_engine_.ExecuteScript(
217 "function test(data, state) tbl = {}; tbl['sessionId'] = 1; "
218 "on_metrics_report(tbl) "
219 "end",
220 "test", "{}", "{}");
221 std::string actual = ConvertVectorToString(output);
222 EXPECT_NE(actual.find("{\"sessionId\":1}"), std::string::npos);
223 }
224
TEST_F(LuaEngineTest,ExecuteScriptOnMetricsReportMultipleTable)225 TEST_F(LuaEngineTest, ExecuteScriptOnMetricsReportMultipleTable) {
226 std::vector<std::string> output = lua_engine_.ExecuteScript(
227 "function test(data, state) tbl = {}; tbl['sessionId'] = 1; "
228 "on_metrics_report(tbl, "
229 "tbl) end",
230 "test", "{}", "{}");
231 std::string actual = ConvertVectorToString(output);
232 EXPECT_EQ("{\"sessionId\":1}\n", actual);
233 EXPECT_EQ("{\"sessionId\":1}\n", lua_engine_.GetSavedState());
234 }
235
TEST_F(LuaEngineTest,ExecuteScriptWithPreviousState)236 TEST_F(LuaEngineTest, ExecuteScriptWithPreviousState) {
237 lua_engine_.ExecuteScript(
238 "function test(data, state) tbl = {}; tbl['result'] = state.data + 1; "
239 "on_success(tbl) end",
240 "test", "{}", "{\"data\": 1}");
241 std::string saved_state = lua_engine_.GetSavedState();
242 EXPECT_EQ("{\"result\":2}\n", saved_state);
243 }
244
TEST_F(LuaEngineTest,ExecuteScriptWrongFunctionName)245 TEST_F(LuaEngineTest, ExecuteScriptWrongFunctionName) {
246 std::vector<std::string> output = lua_engine_.ExecuteScript(
247 "function test(data, state) end", "tesT", "{}", "{}");
248 std::string actual = ConvertVectorToString(output);
249 EXPECT_NE(actual.find("Wrong function name."), std::string::npos);
250 }
251
TEST_F(LuaEngineTest,ExecuteScriptSyntaxError)252 TEST_F(LuaEngineTest, ExecuteScriptSyntaxError) {
253 std::vector<std::string> output = lua_engine_.ExecuteScript(
254 "function test(data, state) end f", "test", "{}", "{}");
255 std::string actual = ConvertVectorToString(output);
256 EXPECT_NE(actual.find("Error encountered while loading the script."),
257 std::string::npos);
258 }
259
TEST_F(LuaEngineTest,ExecuteScriptSyntaxErrorInsideFunction)260 TEST_F(LuaEngineTest, ExecuteScriptSyntaxErrorInsideFunction) {
261 std::vector<std::string> output = lua_engine_.ExecuteScript(
262 "function test(data, state) x == 1 end", "test", "{}", "{}");
263 std::string actual = ConvertVectorToString(output);
264 EXPECT_NE(actual.find("Error encountered while loading the script."),
265 std::string::npos);
266 }
267
TEST_F(LuaEngineTest,ExecuteScriptRuntimeError)268 TEST_F(LuaEngineTest, ExecuteScriptRuntimeError) {
269 std::vector<std::string> output = lua_engine_.ExecuteScript(
270 "function test(data, state) unknown_function(data, state) end", "test",
271 "{}", "{}");
272 std::string actual = ConvertVectorToString(output);
273 EXPECT_NE(actual.find("Error encountered while running the script."),
274 std::string::npos);
275 }
276
TEST_F(LuaEngineTest,ExecuteScriptRuntimeErrorWithStackTrace)277 TEST_F(LuaEngineTest, ExecuteScriptRuntimeErrorWithStackTrace) {
278 const char* script = "function func_2(data, state)\n"
279 " func_3(data, state)\n"
280 "end\n"
281 "function func_1(data, state)\n"
282 " func_2(data, state)\n"
283 "end";
284 std::vector<std::string> output = lua_engine_.ExecuteScript(script, "func_1", "{}", "{}");
285 std::string actual = ConvertVectorToString(output);
286 EXPECT_NE(actual.find("Error encountered while running the script."), std::string::npos);
287 EXPECT_NE(actual.find("func_3"), std::string::npos);
288 EXPECT_NE(actual.find("func_2"), std::string::npos);
289 EXPECT_NE(actual.find("func_1"), std::string::npos);
290 }
291
TEST_F(LuaEngineTest,ExecuteScriptInvalidPublishedData)292 TEST_F(LuaEngineTest, ExecuteScriptInvalidPublishedData) {
293 std::vector<std::string> output = lua_engine_.ExecuteScript(
294 "function test(data, state) end", "test", "invalid", "{}");
295 std::string actual = ConvertVectorToString(output);
296 EXPECT_NE(actual.find("Error from parsing published data"),
297 std::string::npos);
298 }
299
TEST_F(LuaEngineTest,ExecuteScriptInvalidSavedState)300 TEST_F(LuaEngineTest, ExecuteScriptInvalidSavedState) {
301 std::vector<std::string> output = lua_engine_.ExecuteScript(
302 "function test(data, state) end", "test", "{}", "invalid");
303 std::string actual = ConvertVectorToString(output);
304 EXPECT_NE(actual.find("Error from parsing saved state"), std::string::npos);
305 }
306
TEST_F(LuaEngineTest,StringVectorToArrayEmpty)307 TEST_F(LuaEngineTest, StringVectorToArrayEmpty) {
308 std::vector<std::string> vector = {};
309 char** array = LuaEngine::StringVectorToCharArray(vector);
310 EXPECT_EQ(nullptr, array);
311 }
312
TEST_F(LuaEngineTest,StringVectorToArrayNonEmpty)313 TEST_F(LuaEngineTest, StringVectorToArrayNonEmpty) {
314 std::vector<std::string> vector = {"1", "2", "3", "4"};
315 char** array = LuaEngine::StringVectorToCharArray(vector);
316 EXPECT_EQ("1234", ConvertArrayToString(array, 4));
317 }
318 } // namespace tests
319 } // namespace lua_interpreter
320
main(int argc,char ** argv)321 int main(int argc, char** argv) {
322 ::testing::InitGoogleTest(&argc, argv);
323 return RUN_ALL_TESTS();
324 }
325