aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/shared.h
blob: 8a84a94fd91669eff6b14c5b16549438a3045609 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#pragma once

// #################################################################################################

class LuaState
{
    public:

    DECLARE_UNIQUE_TYPE(WithBaseLibs, bool);
    DECLARE_UNIQUE_TYPE(WithFixture, bool);
    lua_State* L{ luaL_newstate() };
    bool finalizerWasCalled{};
    STACK_CHECK_START_REL(L, 0);

    ~LuaState()
    {
        close();
    }
    LuaState(WithBaseLibs withBaseLibs_, WithFixture withFixture_);

    LuaState(LuaState const&) = delete;
    LuaState(LuaState&& rhs_) noexcept
    : L{ std::exchange(rhs_.L, nullptr) }
    {
    }
    LuaState& operator=(LuaState const&) = delete;
    LuaState& operator=(LuaState&& rhs_) noexcept {
        L = std::exchange(rhs_.L, nullptr);
        return *this;
    }

    public:

    operator lua_State*() const { return L; }

    void stackCheck(int delta_) { STACK_CHECK(L, delta_); }
    void close();

    // all these methods leave a single item on the stack: an error string on failure, or a single value that depends on what we do
    [[nodiscard]]
    LuaError doString(std::string_view const& str_) const;
    std::string_view doStringAndRet(std::string_view const& str_) const;
    [[nodiscard]]
    LuaError doFile(std::filesystem::path const& root_, std::string_view const& str_) const;
    [[nodiscard]]
    LuaError loadString(std::string_view const& str_) const;
    [[nodiscard]]
    LuaError loadFile(std::filesystem::path const& root_, std::string_view const& str_) const;
    void requireFailure(std::string_view const& script_);
    void requireNotReturnedString(std::string_view const& script_, std::string_view const& unexpected_);
    void requireReturnedString(std::string_view const& script_, std::string_view const& expected_);
    void requireSuccess(std::string_view const& script_);
    void requireSuccess(std::filesystem::path const& root_, std::string_view const& path_);
    [[nodiscard]]
    LuaError runChunk() const;

    friend std::ostream& operator<<(std::ostream& os_, LuaState const& s_)
    {
        os_ << luaG_tostring(s_.L, kIdxTop);
        return os_;
    }
};

// #################################################################################################

enum class [[nodiscard]] TestType
{
    AssertNoLuaError,
    AssertNoThrow,
    AssertThrows,
};

struct FileRunnerParam
{
    std::string_view script;
    TestType test;
};

// Define a specialization for FileRunnerParam in Catch::Detail::stringify
namespace Catch {
    namespace Detail {
        template <>
        inline std::string stringify(FileRunnerParam const& param_)
        {
            return std::string{ param_.script };
        }
    } // namespace Detail
} // namespace Catch

class FileRunner : private LuaState
{
    private:

    std::string root;

    public:

    FileRunner(std::string_view const& where_);

    void performTest(FileRunnerParam const& testParam_);
};

// #################################################################################################

// Can't #ifdef stuff away inside a macro expansion
#if LUA_VERSION_NUM == 501
#define LUA51_ONLY(a) a
#else
#define LUA51_ONLY(a) ""
#endif

#if LUA_VERSION_NUM == 504
#define LUA54_ONLY(a) a
#else
#define LUA54_ONLY(a) ""
#endif

#if LUAJIT_FLAVOR() == 0
#define PUC_LUA_ONLY(a) a
#define JIT_LUA_ONLY(a) ""
#else
#define PUC_LUA_ONLY(a) ""
#define JIT_LUA_ONLY(a) a
#endif