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 40namespace { 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). 52static int 53hook_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). 69static int 70hook_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 80ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty); 81ATF_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 94ATF_TEST_CASE_WITHOUT_HEAD(create_module__one); 95ATF_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 108ATF_TEST_CASE_WITHOUT_HEAD(create_module__many); 109ATF_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 128ATF_TEST_CASE_WITHOUT_HEAD(do_file__some_args); 129ATF_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 149ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results); 150ATF_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 166ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results); 167ATF_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 179ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results); 180ATF_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 195ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found); 196ATF_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 205ATF_TEST_CASE_WITHOUT_HEAD(do_file__error); 206ATF_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 219ATF_TEST_CASE_WITHOUT_HEAD(do_file__error_with_errfunc); 220ATF_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 237ATF_TEST_CASE_WITHOUT_HEAD(do_string__some_args); 238ATF_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 255ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results); 256ATF_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 268ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results); 269ATF_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 277ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results); 278ATF_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 289ATF_TEST_CASE_WITHOUT_HEAD(do_string__error); 290ATF_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 299ATF_TEST_CASE_WITHOUT_HEAD(do_string__error_with_errfunc); 300ATF_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 314ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result); 315ATF_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 325ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results); 326ATF_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 338ATF_TEST_CASE_WITHOUT_HEAD(eval__error); 339ATF_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 348ATF_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