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", 1); 89 ATF_REQUIRE(state.to_boolean()); 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)", 1); 103 ATF_REQUIRE_EQ(30, state.to_integer()); 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)", 1); 119 ATF_REQUIRE_EQ(30, state.to_integer()); 120 lutok::do_string(state, "return my_math.multiply(10, 20)", 1); 121 ATF_REQUIRE_EQ(200, state.to_integer()); 122 lutok::do_string(state, "return my_math.add2(20, 30)", 1); 123 ATF_REQUIRE_EQ(50, state.to_integer()); 124 state.pop(3); 125 } 126 127 128 ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results); 129 ATF_TEST_CASE_BODY(do_file__any_results) 130 { 131 std::ofstream output("test.lua"); 132 output << "return 10, 20, 30\n"; 133 output.close(); 134 135 lutok::state state; 136 ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", -1)); 137 ATF_REQUIRE_EQ(3, state.get_top()); 138 ATF_REQUIRE_EQ(10, state.to_integer(-3)); 139 ATF_REQUIRE_EQ(20, state.to_integer(-2)); 140 ATF_REQUIRE_EQ(30, state.to_integer(-1)); 141 state.pop(3); 142 } 143 144 145 ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results); 146 ATF_TEST_CASE_BODY(do_file__no_results) 147 { 148 std::ofstream output("test.lua"); 149 output << "return 10, 20, 30\n"; 150 output.close(); 151 152 lutok::state state; 153 ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua")); 154 ATF_REQUIRE_EQ(0, state.get_top()); 155 } 156 157 158 ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results); 159 ATF_TEST_CASE_BODY(do_file__many_results) 160 { 161 std::ofstream output("test.lua"); 162 output << "return 10, 20, 30\n"; 163 output.close(); 164 165 lutok::state state; 166 ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 2)); 167 ATF_REQUIRE_EQ(2, state.get_top()); 168 ATF_REQUIRE_EQ(10, state.to_integer(-2)); 169 ATF_REQUIRE_EQ(20, state.to_integer(-1)); 170 state.pop(2); 171 } 172 173 174 ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found); 175 ATF_TEST_CASE_BODY(do_file__not_found) 176 { 177 lutok::state state; 178 stack_balance_checker checker(state); 179 ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", 180 lutok::do_file(state, "missing.lua")); 181 } 182 183 184 ATF_TEST_CASE_WITHOUT_HEAD(do_file__error); 185 ATF_TEST_CASE_BODY(do_file__error) 186 { 187 std::ofstream output("test.lua"); 188 output << "a b c\n"; 189 output.close(); 190 191 lutok::state state; 192 stack_balance_checker checker(state); 193 ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'", 194 lutok::do_file(state, "test.lua")); 195 } 196 197 198 ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results); 199 ATF_TEST_CASE_BODY(do_string__any_results) 200 { 201 lutok::state state; 202 ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", -1)); 203 ATF_REQUIRE_EQ(3, state.get_top()); 204 ATF_REQUIRE_EQ(10, state.to_integer(-3)); 205 ATF_REQUIRE_EQ(20, state.to_integer(-2)); 206 ATF_REQUIRE_EQ(30, state.to_integer(-1)); 207 state.pop(3); 208 } 209 210 211 ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results); 212 ATF_TEST_CASE_BODY(do_string__no_results) 213 { 214 lutok::state state; 215 ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30")); 216 ATF_REQUIRE_EQ(0, state.get_top()); 217 } 218 219 220 ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results); 221 ATF_TEST_CASE_BODY(do_string__many_results) 222 { 223 lutok::state state; 224 ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 2)); 225 ATF_REQUIRE_EQ(2, state.get_top()); 226 ATF_REQUIRE_EQ(10, state.to_integer(-2)); 227 ATF_REQUIRE_EQ(20, state.to_integer(-1)); 228 state.pop(2); 229 } 230 231 232 ATF_TEST_CASE_WITHOUT_HEAD(do_string__error); 233 ATF_TEST_CASE_BODY(do_string__error) 234 { 235 lutok::state state; 236 stack_balance_checker checker(state); 237 ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'", 238 lutok::do_string(state, "a b c")); 239 } 240 241 242 ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result); 243 ATF_TEST_CASE_BODY(eval__one_result) 244 { 245 lutok::state state; 246 stack_balance_checker checker(state); 247 lutok::eval(state, "3 + 10"); 248 ATF_REQUIRE_EQ(13, state.to_integer()); 249 state.pop(1); 250 } 251 252 253 ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results); 254 ATF_TEST_CASE_BODY(eval__many_results) 255 { 256 lutok::state state; 257 stack_balance_checker checker(state); 258 lutok::eval(state, "5, 8, 10", 3); 259 ATF_REQUIRE_EQ(5, state.to_integer(-3)); 260 ATF_REQUIRE_EQ(8, state.to_integer(-2)); 261 ATF_REQUIRE_EQ(10, state.to_integer(-1)); 262 state.pop(3); 263 } 264 265 266 ATF_TEST_CASE_WITHOUT_HEAD(eval__error); 267 ATF_TEST_CASE_BODY(eval__error) 268 { 269 lutok::state state; 270 stack_balance_checker checker(state); 271 ATF_REQUIRE_THROW(lutok::error, 272 lutok::eval(state, "non_existent.method()")); 273 } 274 275 276 ATF_INIT_TEST_CASES(tcs) 277 { 278 ATF_ADD_TEST_CASE(tcs, create_module__empty); 279 ATF_ADD_TEST_CASE(tcs, create_module__one); 280 ATF_ADD_TEST_CASE(tcs, create_module__many); 281 282 ATF_ADD_TEST_CASE(tcs, do_file__any_results); 283 ATF_ADD_TEST_CASE(tcs, do_file__no_results); 284 ATF_ADD_TEST_CASE(tcs, do_file__many_results); 285 ATF_ADD_TEST_CASE(tcs, do_file__not_found); 286 ATF_ADD_TEST_CASE(tcs, do_file__error); 287 288 ATF_ADD_TEST_CASE(tcs, do_string__any_results); 289 ATF_ADD_TEST_CASE(tcs, do_string__no_results); 290 ATF_ADD_TEST_CASE(tcs, do_string__many_results); 291 ATF_ADD_TEST_CASE(tcs, do_string__error); 292 293 ATF_ADD_TEST_CASE(tcs, eval__one_result); 294 ATF_ADD_TEST_CASE(tcs, eval__many_results); 295 ATF_ADD_TEST_CASE(tcs, eval__error); 296 } 297