Coverage Report

Created: 2026-10-24 08:16

/work/testing/support/public/tox_runner.hh
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2026 The TokTok team.
3
 */
4
5
#ifndef C_TOXCORE_TESTING_SUPPORT_TOX_RUNNER_H
6
#define C_TOXCORE_TESTING_SUPPORT_TOX_RUNNER_H
7
8
#include <atomic>
9
#include <functional>
10
#include <future>
11
#include <thread>
12
#include <type_traits>
13
#include <utility>
14
#include <vector>
15
16
#include "../../../toxcore/attributes.h"
17
#include "../../../toxcore/tox_events.h"
18
#include "mpsc_queue.hh"
19
#include "simulation.hh"
20
21
namespace tox::test {
22
23
class ToxRunner {
24
public:
25
    explicit ToxRunner(SimulatedNode &node, const Tox_Options *_Nullable options = nullptr);
26
    ~ToxRunner();
27
28
    ToxRunner(const ToxRunner &) = delete;
29
    ToxRunner &operator=(const ToxRunner &) = delete;
30
31
    struct ToxEventsDeleter {
32
0
        void operator()(Tox_Events *_Nonnull e) const { tox_events_free(e); }
33
    };
34
    using ToxEventsPtr = std::unique_ptr<Tox_Events, ToxEventsDeleter>;
35
36
    /**
37
     * @brief Schedules a task for execution on the runner's thread.
38
     *
39
     * This method is thread-safe and non-blocking. The task is queued and will
40
     * be executed during the runner's event loop cycle.
41
     *
42
     * @param task The function to execute, taking a raw Tox pointer.
43
     */
44
    void execute(std::function<void(Tox *_Nonnull)> task);
45
46
    /**
47
     * @brief Executes a task on the runner's thread and waits for the result.
48
     *
49
     * This method blocks the calling thread until the task has been executed
50
     * by the runner. It automatically handles return value propagation and
51
     * exception safety (though exceptions are not currently propagated).
52
     *
53
     * @tparam Func The type of the callable object.
54
     * @param func The callable to execute, taking a raw Tox pointer.
55
     * @return The result of the callable execution.
56
     */
57
    template <typename Func>
58
    auto invoke(Func &&func) -> std::invoke_result_t<Func, Tox *_Nonnull>
59
0
    {
60
0
        using R = std::invoke_result_t<Func, Tox *_Nonnull>;
61
0
        auto promise = std::make_shared<std::promise<R>>();
62
0
        auto future = promise->get_future();
63
64
0
        execute([p = promise, f = std::forward<Func>(func)](Tox *_Nonnull tox) {
65
0
            if constexpr (std::is_void_v<R>) {
66
0
                f(tox);
67
0
                p->set_value();
68
0
            } else {
69
0
                p->set_value(f(tox));
70
0
            }
71
0
        });
Unexecuted instantiation: unity_1_cxx.cxx:_ZZN3tox4test9ToxRunner6invokeIZNS0_23setup_connected_friendsERNS0_10SimulationEP3ToxRNS0_13SimulatedNodeEiPK11Tox_OptionsbE3$_0EENSt13invoke_resultIT_JS6_EE4typeEOSE_ENKUlS6_E_clES6_
Unexecuted instantiation: unity_1_cxx.cxx:_ZZN3tox4test9ToxRunner6invokeIZNS0_23setup_connected_friendsERNS0_10SimulationEP3ToxRNS0_13SimulatedNodeEiPK11Tox_OptionsbE3$_2EENSt13invoke_resultIT_JS6_EE4typeEOSE_ENKUlS6_E_clES6_
72
73
0
        return future.get();
74
0
    }
Unexecuted instantiation: unity_1_cxx.cxx:_ZN3tox4test9ToxRunner6invokeIZNS0_23setup_connected_friendsERNS0_10SimulationEP3ToxRNS0_13SimulatedNodeEiPK11Tox_OptionsbE3$_0EENSt13invoke_resultIT_JS6_EE4typeEOSE_
Unexecuted instantiation: unity_1_cxx.cxx:_ZN3tox4test9ToxRunner6invokeIZNS0_23setup_connected_friendsERNS0_10SimulationEP3ToxRNS0_13SimulatedNodeEiPK11Tox_OptionsbE3$_2EENSt13invoke_resultIT_JS6_EE4typeEOSE_
75
76
    /**
77
     * @brief Retrieves all accumulated Tox event batches.
78
     *
79
     * Returns a vector of unique pointers to Tox_Events structures that have
80
     * been collected by the runner since the last call. Ownership is transferred
81
     * to the caller. This method is thread-safe.
82
     *
83
     * @return A vector of Tox_Events pointers.
84
     */
85
    std::vector<ToxEventsPtr> poll_events();
86
87
    /**
88
     * @brief Accesses the underlying Tox instance directly.
89
     *
90
     * @warning Thread-Safety Violation: This method provides unsafe access to the
91
     * Tox instance. It should ONLY be used when the runner thread is known to be
92
     * idle (e.g., before the loop starts) or for accessing constant/read-only properties.
93
     * For all other operations, use `execute` or `invoke`.
94
     */
95
0
    Tox *_Nullable unsafe_tox() { return tox_.get(); }
96
97
    /**
98
     * @brief Temporarily stops the runner from participating in the simulation.
99
     *
100
     * Unregisters the runner and its tick listener from the simulation.
101
     * While paused, the runner will not call tox_iterate.
102
     */
103
    void pause();
104
105
    /**
106
     * @brief Resumes the runner's participation in the simulation.
107
     */
108
    void resume();
109
110
    /**
111
     * @brief Returns true if the runner is currently active.
112
     */
113
0
    bool is_active() const { return active_; }
114
115
private:
116
    void loop();
117
118
    SimulatedNode::ToxPtr tox_;
119
    std::thread thread_;
120
    std::atomic<bool> active_{true};
121
122
    struct Message {
123
        enum Type { Task, Tick, Stop } type;
124
        std::function<void(Tox *_Nonnull)> task;
125
        uint64_t generation = 0;
126
    };
127
128
    MpscQueue<Message> queue_;
129
    MpscQueue<ToxEventsPtr> events_queue_;
130
131
    Simulation::TickListenerId tick_listener_id_ = -1;
132
    SimulatedNode &node_;
133
};
134
135
}  // namespace tox::test
136
137
#endif  // C_TOXCORE_TESTING_SUPPORT_TOX_RUNNER_H