1 // Copyright 2011 Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #include "operations.hpp" 30 31 #include <fstream> 32 33 #include <atf-c++.hpp> 34 35 #include "exceptions.hpp" 36 #include "state.ipp" 37 #include "test_utils.hpp" 38 39 40 namespace { 41 42 43 /// Addition function for injection into Lua. 44 /// 45 /// \pre stack(-2) The first summand. 46 /// \pre stack(-1) The second summand. 47 /// \post stack(-1) The result of the sum. 48 /// 49 /// \param state The Lua state. 50 /// 51 /// \return The number of results (1). 52 static int 53 hook_add(lutok::state& state) 54 { 55 state.push_integer(state.to_integer(-1) + state.to_integer(-2)); 56 return 1; 57 } 58 59 60 /// Multiplication function for injection into Lua. 61 /// 62 /// \pre stack(-2) The first factor. 63 /// \pre stack(-1) The second factor. 64 /// \post stack(-1) The product. 65 /// 66 /// \param state The Lua state. 67 /// 68 /// \return The number of results (1). 69 static int 70 hook_multiply(lutok::state& state) 71 { 72 state.push_integer(state.to_integer(-1) * state.to_integer(-2)); 73 return 1; 74 } 75 76 77 } // anonymous namespace 78 79 80 ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty); 81 ATF_TEST_CASE_BODY(create_module__empty) 82 { 83 lutok::state state; 84 std::map< std::string, lutok::cxx_function > members; 85 lutok::create_module(state, "my_math", members); 86 87 state.open_base(); 88 lutok::do_string(state, "return next(my_math) == nil", 0, 1, 0); 89 ATF_REQUIRE(state.to_boolean(-1)); 90 state.pop(1); 91 } 92 93 94 ATF_TEST_CASE_WITHOUT_HEAD(create_module__one); 95 ATF_TEST_CASE_BODY(create_module__one) 96 { 97 lutok::state state; 98 std::map< std::string, lutok::cxx_function > members; 99 members["add"] = hook_add; 100 lutok::create_module(state, "my_math", members); 101 102 lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0); 103 ATF_REQUIRE_EQ(30, state.to_integer(-1)); 104 state.pop(1); 105 } 106 107 108 ATF_TEST_CASE_WITHOUT_HEAD(create_module__many); 109 ATF_TEST_CASE_BODY(create_module__many) 110 { 111 lutok::state state; 112 std::map< std::string, lutok::cxx_function > members; 113 members["add"] = hook_add; 114 members["multiply"] = hook_multiply; 115 members["add2"] = hook_add; 116 lutok::create_module(state, "my_math", members); 117 118 lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0); 119 ATF_REQUIRE_EQ(30, state.to_integer(-1)); 120 lutok::do_string(state, "return my_math.multiply(10, 20)", 0, 1, 0); 121 ATF_REQUIRE_EQ(200, state.to_integer(-1)); 122 lutok::do_string(state, "return my_math.add2(20, 30)", 0, 1, 0); 123 ATF_REQUIRE_EQ(50, state.to_integer(-1)); 124 state.pop(3); 125 } 126 127 128 ATF_TEST_CASE_WITHOUT_HEAD(do_file__some_args); 129 ATF_TEST_CASE_BODY(do_file__some_args) 130 { 131 std::ofstream output("test.lua"); 132 output << "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n"; 133 output.close(); 134 135 lutok::state state; 136 state.push_integer(456); 137 state.push_integer(3); 138 state.push_integer(5); 139 state.push_integer(123); 140 ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 3, -1, 0)); 141 ATF_REQUIRE_EQ(3, state.get_top()); 142 ATF_REQUIRE_EQ(456, state.to_integer(-3)); 143 ATF_REQUIRE_EQ(6, state.to_integer(-2)); 144 ATF_REQUIRE_EQ(10, state.to_integer(-1)); 145 state.pop(3); 146 } 147 148 149 ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results); 150 ATF_TEST_CASE_BODY(do_file__any_results) 151 { 152 std::ofstream output("test.lua"); 153 output << "return 10, 20, 30\n"; 154 output.close(); 155 156 lutok::state state; 157 ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", 0, -1, 0)); 158 ATF_REQUIRE_EQ(3, state.get_top()); 159 ATF_REQUIRE_EQ(10, state.to_integer(-3)); 160 ATF_REQUIRE_EQ(20, state.to_integer(-2)); 161 ATF_REQUIRE_EQ(30, state.to_integer(-1)); 162 state.pop(3); 163 } 164 165 166 ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results); 167 ATF_TEST_CASE_BODY(do_file__no_results) 168 { 169 std::ofstream output("test.lua"); 170 output << "return 10, 20, 30\n"; 171 output.close(); 172 173 lutok::state state; 174 ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua", 0, 0, 0)); 175 ATF_REQUIRE_EQ(0, state.get_top()); 176 } 177 178 179 ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results); 180 ATF_TEST_CASE_BODY(do_file__many_results) 181 { 182 std::ofstream output("test.lua"); 183 output << "return 10, 20, 30\n"; 184 output.close(); 185 186 lutok::state state; 187 ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 0, 2, 0)); 188 ATF_REQUIRE_EQ(2, state.get_top()); 189 ATF_REQUIRE_EQ(10, state.to_integer(-2)); 190 ATF_REQUIRE_EQ(20, state.to_integer(-1)); 191 state.pop(2); 192 } 193 194 195 ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found); 196 ATF_TEST_CASE_BODY(do_file__not_found) 197 { 198 lutok::state state; 199 stack_balance_checker checker(state); 200 ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", 201 lutok::do_file(state, "missing.lua", 0, 0, 0)); 202 } 203 204 205 ATF_TEST_CASE_WITHOUT_HEAD(do_file__error); 206 ATF_TEST_CASE_BODY(do_file__error) 207 { 208 std::ofstream output("test.lua"); 209 output << "a b c\n"; 210 output.close(); 211 212 lutok::state state; 213 stack_balance_checker checker(state); 214 ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'", 215 lutok::do_file(state, "test.lua", 0, 0, 0)); 216 } 217 218 219 ATF_TEST_CASE_WITHOUT_HEAD(do_file__error_with_errfunc); 220 ATF_TEST_CASE_BODY(do_file__error_with_errfunc) 221 { 222 std::ofstream output("test.lua"); 223 output << "unknown_function()\n"; 224 output.close(); 225 226 lutok::state state; 227 lutok::eval(state, "function(message) return 'This is an error!' end", 1); 228 { 229 stack_balance_checker checker(state); 230 ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!", 231 lutok::do_file(state, "test.lua", 0, 0, -2)); 232 } 233 state.pop(1); 234 } 235 236 237 ATF_TEST_CASE_WITHOUT_HEAD(do_string__some_args); 238 ATF_TEST_CASE_BODY(do_string__some_args) 239 { 240 lutok::state state; 241 state.push_integer(456); 242 state.push_integer(3); 243 state.push_integer(5); 244 state.push_integer(123); 245 ATF_REQUIRE_EQ(2, lutok::do_string( 246 state, "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n", 3, -1, 0)); 247 ATF_REQUIRE_EQ(3, state.get_top()); 248 ATF_REQUIRE_EQ(456, state.to_integer(-3)); 249 ATF_REQUIRE_EQ(6, state.to_integer(-2)); 250 ATF_REQUIRE_EQ(10, state.to_integer(-1)); 251 state.pop(3); 252 } 253 254 255 ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results); 256 ATF_TEST_CASE_BODY(do_string__any_results) 257 { 258 lutok::state state; 259 ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", 0, -1, 0)); 260 ATF_REQUIRE_EQ(3, state.get_top()); 261 ATF_REQUIRE_EQ(10, state.to_integer(-3)); 262 ATF_REQUIRE_EQ(20, state.to_integer(-2)); 263 ATF_REQUIRE_EQ(30, state.to_integer(-1)); 264 state.pop(3); 265 } 266 267 268 ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results); 269 ATF_TEST_CASE_BODY(do_string__no_results) 270 { 271 lutok::state state; 272 ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30", 0, 0, 0)); 273 ATF_REQUIRE_EQ(0, state.get_top()); 274 } 275 276 277 ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results); 278 ATF_TEST_CASE_BODY(do_string__many_results) 279 { 280 lutok::state state; 281 ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 0, 2, 0)); 282 ATF_REQUIRE_EQ(2, state.get_top()); 283 ATF_REQUIRE_EQ(10, state.to_integer(-2)); 284 ATF_REQUIRE_EQ(20, state.to_integer(-1)); 285 state.pop(2); 286 } 287 288 289 ATF_TEST_CASE_WITHOUT_HEAD(do_string__error); 290 ATF_TEST_CASE_BODY(do_string__error) 291 { 292 lutok::state state; 293 stack_balance_checker checker(state); 294 ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'", 295 lutok::do_string(state, "a b c", 0, 0, 0)); 296 } 297 298 299 ATF_TEST_CASE_WITHOUT_HEAD(do_string__error_with_errfunc); 300 ATF_TEST_CASE_BODY(do_string__error_with_errfunc) 301 { 302 lutok::state state; 303 lutok::eval(state, "function(message) return 'This is an error!' end", 1); 304 { 305 stack_balance_checker checker(state); 306 ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!", 307 lutok::do_string(state, "unknown_function()", 308 0, 0, -2)); 309 } 310 state.pop(1); 311 } 312 313 314 ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result); 315 ATF_TEST_CASE_BODY(eval__one_result) 316 { 317 lutok::state state; 318 stack_balance_checker checker(state); 319 lutok::eval(state, "3 + 10", 1); 320 ATF_REQUIRE_EQ(13, state.to_integer(-1)); 321 state.pop(1); 322 } 323 324 325 ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results); 326 ATF_TEST_CASE_BODY(eval__many_results) 327 { 328 lutok::state state; 329 stack_balance_checker checker(state); 330 lutok::eval(state, "5, 8, 10", 3); 331 ATF_REQUIRE_EQ(5, state.to_integer(-3)); 332 ATF_REQUIRE_EQ(8, state.to_integer(-2)); 333 ATF_REQUIRE_EQ(10, state.to_integer(-1)); 334 state.pop(3); 335 } 336 337 338 ATF_TEST_CASE_WITHOUT_HEAD(eval__error); 339 ATF_TEST_CASE_BODY(eval__error) 340 { 341 lutok::state state; 342 stack_balance_checker checker(state); 343 ATF_REQUIRE_THROW(lutok::error, 344 lutok::eval(state, "non_existent.method()", 1)); 345 } 346 347 348 ATF_INIT_TEST_CASES(tcs) 349 { 350 ATF_ADD_TEST_CASE(tcs, create_module__empty); 351 ATF_ADD_TEST_CASE(tcs, create_module__one); 352 ATF_ADD_TEST_CASE(tcs, create_module__many); 353 354 ATF_ADD_TEST_CASE(tcs, do_file__some_args); 355 ATF_ADD_TEST_CASE(tcs, do_file__any_results); 356 ATF_ADD_TEST_CASE(tcs, do_file__no_results); 357 ATF_ADD_TEST_CASE(tcs, do_file__many_results); 358 ATF_ADD_TEST_CASE(tcs, do_file__not_found); 359 ATF_ADD_TEST_CASE(tcs, do_file__error); 360 ATF_ADD_TEST_CASE(tcs, do_file__error_with_errfunc); 361 362 ATF_ADD_TEST_CASE(tcs, do_string__some_args); 363 ATF_ADD_TEST_CASE(tcs, do_string__any_results); 364 ATF_ADD_TEST_CASE(tcs, do_string__no_results); 365 ATF_ADD_TEST_CASE(tcs, do_string__many_results); 366 ATF_ADD_TEST_CASE(tcs, do_string__error); 367 ATF_ADD_TEST_CASE(tcs, do_string__error_with_errfunc); 368 369 ATF_ADD_TEST_CASE(tcs, eval__one_result); 370 ATF_ADD_TEST_CASE(tcs, eval__many_results); 371 ATF_ADD_TEST_CASE(tcs, eval__error); 372 } 373