116
117
118
119
127 wait(
std::chrono::milliseconds timeout = std::chrono::milliseconds{ 5000 })
const
129 return QTest::qWaitFor([
this]() {
130 return m_state->matched;
134 [[nodiscard]]
bool matched()
const {
return m_state->matched; }
138 explicit WaitToken(std::shared_ptr<PendingExpect> state) : m_state(std::move(state))
142 const std::shared_ptr<PendingExpect> m_state;
146 :
QMessageSpy(QLatin1StringView(category.categoryName()))
155 Q_ASSERT(!s_instance);
157 m_previousHandler = qInstallMessageHandler(messageHandler);
162 qInstallMessageHandler(m_previousHandler);
163 s_instance =
nullptr;
167
168
169
170
171
174 auto state = std::make_shared<PendingExpect>(PendingExpect{ type, message,
false });
175 std::lock_guard lock(m_mutex);
176 m_pending.push_back(state);
183
184
188 std::make_shared<PendingExpect>(PendingExpect{ type, pattern,
false });
189 std::lock_guard lock(m_mutex);
190 m_pending.push_back(state);
197 static bool matchesPending(PendingExpect &p, QtMsgType type,
const QString &msg)
199 if (p.matched || p.type != type)
201 return std::visit([&](
auto &m) ->
bool {
202 using T = std::decay_t<
decltype(m)>;
203 if constexpr (std::is_same_v<T, QString>)
206 return m.match(msg).hasMatch();
210 static void messageHandler(QtMsgType type,
const QMessageLogContext &context,
213 Q_ASSERT(s_instance);
215 if (!(s_instance->m_categoryFilter)
216 || QByteArrayView{ context.category } == s_instance->m_categoryFilter) {
217 std::lock_guard lock(s_instance->m_mutex);
218 bool doCleanupOnExit =
false;
219 auto cleanup = qScopeGuard([&] {
220 if (!doCleanupOnExit)
221 q20::erase_if(s_instance->m_pending, [](
const std::weak_ptr<PendingExpect> &p) {
222 auto locked = p.lock();
223 return !locked || p.lock()->matched;
228 for (std::weak_ptr p : s_instance->m_pending) {
229 auto pending = p.lock();
231 doCleanupOnExit =
true;
234 if (matchesPending(*pending, type, msg)) {
235 pending->matched =
true;
236 doCleanupOnExit =
true;
243 if (s_instance->m_previousHandler)
244 s_instance->m_previousHandler(type, context, msg);
249 QtMessageHandler m_previousHandler =
nullptr;
251 const std::optional<QByteArray> m_categoryFilter;
252 std::vector<std::weak_ptr<PendingExpect>> m_pending;