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 /// \file test_utils.hpp 30 /// Utilities for tests of the lua modules. 31 /// 32 /// This file is intended to be included once, and only once, for every test 33 /// program that needs it. All the code is herein contained to simplify the 34 /// dependency chain in the build rules. 35 36 #if !defined(LUTOK_TEST_UTILS_HPP) 37 # define LUTOK_TEST_UTILS_HPP 38 #else 39 # error "test_utils.hpp can only be included once" 40 #endif 41 42 #include <atf-c++.hpp> 43 44 #include "c_gate.hpp" 45 #include "exceptions.hpp" 46 #include "state.hpp" 47 48 49 namespace { 50 51 52 /// Checks that a given expression raises a particular lutok::api_error. 53 /// 54 /// We cannot make any assumptions regarding the error text provided by Lua, so 55 /// we resort to checking only which API function raised the error (because our 56 /// code is the one hardcoding these strings). 57 /// 58 /// \param exp_api_function The name of the Lua C API function that causes the 59 /// error. 60 /// \param statement The statement to execute. 61 #define REQUIRE_API_ERROR(exp_api_function, statement) \ 62 do { \ 63 try { \ 64 statement; \ 65 ATF_FAIL("api_error not raised by " #statement); \ 66 } catch (const lutok::api_error& api_error) { \ 67 ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \ 68 } \ 69 } while (0) 70 71 72 /// Gets the pointer to the internal lua_State of a state object. 73 /// 74 /// This is pure syntactic sugar to simplify typing in the test cases. 75 /// 76 /// \param state The Lua state. 77 /// 78 /// \return The internal lua_State of the input Lua state. 79 static inline lua_State* 80 raw(lutok::state& state) 81 { 82 return lutok::state_c_gate(state).c_state(); 83 } 84 85 86 /// Ensures that the Lua stack maintains its original height upon exit. 87 /// 88 /// Use an instance of this class to check that a piece of code does not have 89 /// side-effects on the Lua stack. 90 /// 91 /// To be used within a test case only. 92 class stack_balance_checker { 93 /// The Lua state. 94 lutok::state& _state; 95 96 /// Whether to install a sentinel on the stack for balance enforcement. 97 bool _with_sentinel; 98 99 /// The height of the stack on creation. 100 unsigned int _old_count; 101 102 public: 103 /// Constructs a new stack balance checker. 104 /// 105 /// \param state_ The Lua state to validate. 106 /// \param with_sentinel_ If true, insert a sentinel item into the stack and 107 /// validate upon exit that the item is still there. This is an attempt 108 /// to ensure that already-existing items are not removed from the stack 109 /// by the code under test. 110 stack_balance_checker(lutok::state& state_, 111 const bool with_sentinel_ = true) : 112 _state(state_), 113 _with_sentinel(with_sentinel_), 114 _old_count(_state.get_top()) 115 { 116 if (_with_sentinel) 117 _state.push_integer(987654321); 118 } 119 120 /// Destructor for the object. 121 /// 122 /// If the stack height does not match the height when the instance was 123 /// created, this fails the test case. 124 ~stack_balance_checker(void) 125 { 126 if (_with_sentinel) { 127 if (!_state.is_number(-1) || _state.to_integer(-1) != 987654321) 128 ATF_FAIL("Stack corrupted: sentinel not found"); 129 _state.pop(1); 130 } 131 132 unsigned int new_count = _state.get_top(); 133 if (_old_count != new_count) 134 //ATF_FAIL(F("Stack not balanced: before %d, after %d") % 135 // _old_count % new_count); 136 ATF_FAIL("Stack not balanced"); 137 } 138 }; 139 140 141 } // anonymous namespace 142