1*a1563752Sjmmv // Copyright 2011 Google Inc.
2*a1563752Sjmmv // All rights reserved.
3*a1563752Sjmmv //
4*a1563752Sjmmv // Redistribution and use in source and binary forms, with or without
5*a1563752Sjmmv // modification, are permitted provided that the following conditions are
6*a1563752Sjmmv // met:
7*a1563752Sjmmv //
8*a1563752Sjmmv // * Redistributions of source code must retain the above copyright
9*a1563752Sjmmv // notice, this list of conditions and the following disclaimer.
10*a1563752Sjmmv // * Redistributions in binary form must reproduce the above copyright
11*a1563752Sjmmv // notice, this list of conditions and the following disclaimer in the
12*a1563752Sjmmv // documentation and/or other materials provided with the distribution.
13*a1563752Sjmmv // * Neither the name of Google Inc. nor the names of its contributors
14*a1563752Sjmmv // may be used to endorse or promote products derived from this software
15*a1563752Sjmmv // without specific prior written permission.
16*a1563752Sjmmv //
17*a1563752Sjmmv // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*a1563752Sjmmv // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*a1563752Sjmmv // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*a1563752Sjmmv // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*a1563752Sjmmv // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*a1563752Sjmmv // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*a1563752Sjmmv // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*a1563752Sjmmv // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*a1563752Sjmmv // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*a1563752Sjmmv // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*a1563752Sjmmv // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*a1563752Sjmmv
29*a1563752Sjmmv /// \file test_utils.hpp
30*a1563752Sjmmv /// Utilities for tests of the lua modules.
31*a1563752Sjmmv ///
32*a1563752Sjmmv /// This file is intended to be included once, and only once, for every test
33*a1563752Sjmmv /// program that needs it. All the code is herein contained to simplify the
34*a1563752Sjmmv /// dependency chain in the build rules.
35*a1563752Sjmmv
36*a1563752Sjmmv #if !defined(LUTOK_TEST_UTILS_HPP)
37*a1563752Sjmmv # define LUTOK_TEST_UTILS_HPP
38*a1563752Sjmmv #else
39*a1563752Sjmmv # error "test_utils.hpp can only be included once"
40*a1563752Sjmmv #endif
41*a1563752Sjmmv
42*a1563752Sjmmv #include <atf-c++.hpp>
43*a1563752Sjmmv
44*a1563752Sjmmv #include "c_gate.hpp"
45*a1563752Sjmmv #include "exceptions.hpp"
46*a1563752Sjmmv #include "state.hpp"
47*a1563752Sjmmv
48*a1563752Sjmmv
49*a1563752Sjmmv namespace {
50*a1563752Sjmmv
51*a1563752Sjmmv
52*a1563752Sjmmv /// Checks that a given expression raises a particular lutok::api_error.
53*a1563752Sjmmv ///
54*a1563752Sjmmv /// We cannot make any assumptions regarding the error text provided by Lua, so
55*a1563752Sjmmv /// we resort to checking only which API function raised the error (because our
56*a1563752Sjmmv /// code is the one hardcoding these strings).
57*a1563752Sjmmv ///
58*a1563752Sjmmv /// \param exp_api_function The name of the Lua C API function that causes the
59*a1563752Sjmmv /// error.
60*a1563752Sjmmv /// \param statement The statement to execute.
61*a1563752Sjmmv #define REQUIRE_API_ERROR(exp_api_function, statement) \
62*a1563752Sjmmv do { \
63*a1563752Sjmmv try { \
64*a1563752Sjmmv statement; \
65*a1563752Sjmmv ATF_FAIL("api_error not raised by " #statement); \
66*a1563752Sjmmv } catch (const lutok::api_error& api_error) { \
67*a1563752Sjmmv ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \
68*a1563752Sjmmv } \
69*a1563752Sjmmv } while (0)
70*a1563752Sjmmv
71*a1563752Sjmmv
72*a1563752Sjmmv /// Gets the pointer to the internal lua_State of a state object.
73*a1563752Sjmmv ///
74*a1563752Sjmmv /// This is pure syntactic sugar to simplify typing in the test cases.
75*a1563752Sjmmv ///
76*a1563752Sjmmv /// \param state The Lua state.
77*a1563752Sjmmv ///
78*a1563752Sjmmv /// \return The internal lua_State of the input Lua state.
79*a1563752Sjmmv static inline lua_State*
raw(lutok::state & state)80*a1563752Sjmmv raw(lutok::state& state)
81*a1563752Sjmmv {
82*a1563752Sjmmv return lutok::state_c_gate(state).c_state();
83*a1563752Sjmmv }
84*a1563752Sjmmv
85*a1563752Sjmmv
86*a1563752Sjmmv /// Ensures that the Lua stack maintains its original height upon exit.
87*a1563752Sjmmv ///
88*a1563752Sjmmv /// Use an instance of this class to check that a piece of code does not have
89*a1563752Sjmmv /// side-effects on the Lua stack.
90*a1563752Sjmmv ///
91*a1563752Sjmmv /// To be used within a test case only.
92*a1563752Sjmmv class stack_balance_checker {
93*a1563752Sjmmv /// The Lua state.
94*a1563752Sjmmv lutok::state& _state;
95*a1563752Sjmmv
96*a1563752Sjmmv /// Whether to install a sentinel on the stack for balance enforcement.
97*a1563752Sjmmv bool _with_sentinel;
98*a1563752Sjmmv
99*a1563752Sjmmv /// The height of the stack on creation.
100*a1563752Sjmmv unsigned int _old_count;
101*a1563752Sjmmv
102*a1563752Sjmmv public:
103*a1563752Sjmmv /// Constructs a new stack balance checker.
104*a1563752Sjmmv ///
105*a1563752Sjmmv /// \param state_ The Lua state to validate.
106*a1563752Sjmmv /// \param with_sentinel_ If true, insert a sentinel item into the stack and
107*a1563752Sjmmv /// validate upon exit that the item is still there. This is an attempt
108*a1563752Sjmmv /// to ensure that already-existing items are not removed from the stack
109*a1563752Sjmmv /// by the code under test.
stack_balance_checker(lutok::state & state_,const bool with_sentinel_=true)110*a1563752Sjmmv stack_balance_checker(lutok::state& state_,
111*a1563752Sjmmv const bool with_sentinel_ = true) :
112*a1563752Sjmmv _state(state_),
113*a1563752Sjmmv _with_sentinel(with_sentinel_),
114*a1563752Sjmmv _old_count(_state.get_top())
115*a1563752Sjmmv {
116*a1563752Sjmmv if (_with_sentinel)
117*a1563752Sjmmv _state.push_integer(987654321);
118*a1563752Sjmmv }
119*a1563752Sjmmv
120*a1563752Sjmmv /// Destructor for the object.
121*a1563752Sjmmv ///
122*a1563752Sjmmv /// If the stack height does not match the height when the instance was
123*a1563752Sjmmv /// created, this fails the test case.
~stack_balance_checker(void)124*a1563752Sjmmv ~stack_balance_checker(void)
125*a1563752Sjmmv {
126*a1563752Sjmmv if (_with_sentinel) {
127*a1563752Sjmmv if (!_state.is_number() || _state.to_integer() != 987654321)
128*a1563752Sjmmv ATF_FAIL("Stack corrupted: sentinel not found");
129*a1563752Sjmmv _state.pop(1);
130*a1563752Sjmmv }
131*a1563752Sjmmv
132*a1563752Sjmmv unsigned int new_count = _state.get_top();
133*a1563752Sjmmv if (_old_count != new_count)
134*a1563752Sjmmv //ATF_FAIL(F("Stack not balanced: before %d, after %d") %
135*a1563752Sjmmv // _old_count % new_count);
136*a1563752Sjmmv ATF_FAIL("Stack not balanced");
137*a1563752Sjmmv }
138*a1563752Sjmmv };
139*a1563752Sjmmv
140*a1563752Sjmmv
141*a1563752Sjmmv } // anonymous namespace
142