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 49namespace { 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. 79static inline lua_State* 80raw(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. 92class 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 102public: 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