blob: ed390bc4d62fb1d3000dcc695440eb92d4388fbd [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdlib>
#include "test-registry.h"
#include <fbl/function.h>
#include <zxtest/base/assertion.h>
#include <zxtest/base/event-broadcaster.h>
#include <zxtest/base/observer.h>
#include <zxtest/base/runner.h>
#include <zxtest/base/test-case.h>
#include <zxtest/base/test-info.h>
#include <zxtest/base/types.h>
#define ITERATION_EVENT_OBSERVER(Event) \
class FakeObserver : public LifecycleObserver { \
public: \
void OnIteration##Event(const Runner& runner, int iter) final { \
on_notify(runner, iter); \
called = true; \
} \
\
fbl::Function<void(const Runner& runner, int iter)> on_notify; \
bool called = false; \
}
#define ASSERTION_OBSERVER \
class FakeObserver : public LifecycleObserver { \
public: \
void OnAssertion(const Assertion& assertion) final { \
on_notify(assertion); \
called = true; \
} \
\
fbl::Function<void(const Assertion& assertion)> on_notify; \
bool called = false; \
}
#define RUNNER_EVENT_OBSERVER(Event) \
class FakeObserver : public LifecycleObserver { \
public: \
void On##Event(const Runner& runner) final { \
on_notify(runner); \
called = true; \
} \
\
fbl::Function<void(const Runner& runner)> on_notify; \
bool called = false; \
}
// Defines a FakeObserver class which tracks call to OnTestCaseEvent methods.
#define TESTCASE_EVENT_OBSERVER(Event) \
class FakeObserver : public LifecycleObserver { \
public: \
void OnTestCase##Event(const TestCase& test_case) final { \
on_notify(test_case); \
called = true; \
} \
\
fbl::Function<void(const TestCase& test_case)> on_notify; \
bool called = false; \
}
// Defines a FakeObserver class which tracks call to OnTestEvent methods.
#define TEST_EVENT_OBSERVER(Event) \
class FakeObserver : public LifecycleObserver { \
public: \
void OnTest##Event(const TestCase& test_case, const TestInfo& info) final { \
on_notify(test_case, info); \
called = true; \
} \
\
fbl::Function<void(const TestCase& test_case, const TestInfo& info)> on_notify; \
bool called = false; \
}
// Fills ObserverList with |kNumObservers| instances of |FakeObserver|, which should be defined
// for the scope. And sets on_notify of each observer to on_notify_def and registers them
// with |event_broadcaster|.
#define REGISTER_OBSERVERS(observer_list, event_broadcaster, on_notify_def) \
for (int i = 0; i < kNumObservers; ++i) { \
observer_list.push_back({}); \
auto& observer = observer_list[observer_list.size() - 1]; \
observer.on_notify = on_notify_def; \
event_broadcaster.Subscribe(&observer); \
}
namespace zxtest {
namespace test {
namespace {
constexpr char kTestCaseName[] = "TestCase";
constexpr char kTestName[] = "Test";
constexpr int kNumObservers = 100;
const SourceLocation kLocation = {.filename = "filename", .line_number = 20};
void Stub() {}
template <typename T> void ValidateAllObserversNotified(const T& observers) {
for (auto& observer : observers) {
ZX_ASSERT_MSG(observer.called, "EventBroadcaster failed to propagate event.\n");
}
}
} // namespace
void EventBroadcasterOnProgramStart() {
RUNNER_EVENT_OBSERVER(ProgramStart);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
Runner runner(Reporter(/*stream*/ nullptr));
REGISTER_OBSERVERS(observers, event_broadcaster, [&runner](const Runner& actual_runner) {
ZX_ASSERT_MSG(&actual_runner == &runner,
"EventBroadcaster::OnProgramStart propagated the wrong runner.\n");
});
event_broadcaster.OnProgramStart(runner);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnIterationStart() {
ITERATION_EVENT_OBSERVER(Start);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
Runner runner(Reporter(/*stream*/ nullptr));
REGISTER_OBSERVERS(
observers, event_broadcaster, [&runner](const Runner& actual_runner, int iteration) {
ZX_ASSERT_MSG(&actual_runner == &runner,
"EventBroadcaster::OnIterationStart propagated the wrong runner.\n");
ZX_ASSERT_MSG(
iteration == 4,
"EventBroadcaster::OnIterationStart propagated the wron iteration number.\n");
});
event_broadcaster.OnIterationStart(runner, 4);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnEnvironmentSetUp() {
RUNNER_EVENT_OBSERVER(EnvironmentSetUp);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
Runner runner(Reporter(/*stream*/ nullptr));
REGISTER_OBSERVERS(observers, event_broadcaster, [&runner](const Runner& actual_runner) {
ZX_ASSERT_MSG(&actual_runner == &runner,
"EventBroadcaster::OnEnvironmentSetUp propagated the wrong runner.\n");
});
event_broadcaster.OnEnvironmentSetUp(runner);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnTestCaseStart() {
TESTCASE_EVENT_OBSERVER(Start);
TestCase test_case(kTestCaseName, &Stub, &Stub);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(observers, event_broadcaster, [&test_case](const TestCase& actual) {
ZX_ASSERT_MSG(&actual == &test_case,
"EventBroadcaster::OnTestCaseStart propagated the wrong test case\n");
});
event_broadcaster.OnTestCaseStart(test_case);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnTestStart() {
TEST_EVENT_OBSERVER(Start);
TestCase test_case(kTestCaseName, &Stub, &Stub);
TestInfo test_info(kTestName, kLocation, nullptr);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(
observers, event_broadcaster, [&](const TestCase& actual, const TestInfo& actual_info) {
ZX_ASSERT_MSG(&actual == &test_case,
"EventBroadcaster::OnTestStart propagated the wrong test case\n");
ZX_ASSERT_MSG(&actual_info == &test_info,
"EventBroadcaster::OnTestStart propagated the wrong test info\n");
});
event_broadcaster.OnTestStart(test_case, test_info);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnAssertion() {
ASSERTION_OBSERVER;
internal::EventBroadcaster event_broadcaster;
Assertion assertion("Value should be equal", "kExpectedValue", "5", "actual_value", "10",
{.filename = "test.cpp", .line_number = 99999}, /*is_fatal*/ false);
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(observers, event_broadcaster, [&](const Assertion& actual) {
ZX_ASSERT_MSG(&actual == &assertion,
"EventBroadcaster::OnAssertion propagated wrong assertion.\n");
});
event_broadcaster.OnAssertion(assertion);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnTestSkip() {
TEST_EVENT_OBSERVER(Skip);
TestCase test_case(kTestCaseName, &Stub, &Stub);
TestInfo test_info(kTestName, kLocation, nullptr);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(
observers, event_broadcaster, [&](const TestCase& actual, const TestInfo& actual_info) {
ZX_ASSERT_MSG(&actual == &test_case,
"EventBroadcaster::OnTestSkip propagated the wrong test case\n");
ZX_ASSERT_MSG(&actual_info == &test_info,
"EventBroadcaster::OnTestSkip propagated the wrong test info\n");
});
event_broadcaster.OnTestSkip(test_case, test_info);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnTestSuccess() {
TEST_EVENT_OBSERVER(Success);
TestCase test_case(kTestCaseName, &Stub, &Stub);
TestInfo test_info(kTestName, kLocation, nullptr);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(
observers, event_broadcaster, [&](const TestCase& actual, const TestInfo& actual_info) {
ZX_ASSERT_MSG(&actual == &test_case,
"EventBroadcaster::OnTestSuccess propagated the wrong test case\n");
ZX_ASSERT_MSG(&actual_info == &test_info,
"EventBroadcaster::OnTestSuccess propagated the wrong test info\n");
});
event_broadcaster.OnTestSuccess(test_case, test_info);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnTestFailure() {
TEST_EVENT_OBSERVER(Failure);
TestCase test_case(kTestCaseName, &Stub, &Stub);
TestInfo test_info(kTestName, kLocation, nullptr);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(
observers, event_broadcaster, [&](const TestCase& actual, const TestInfo& actual_info) {
ZX_ASSERT_MSG(&actual == &test_case,
"EventBroadcaster::OnTestFailure propagated the wrong test case\n");
ZX_ASSERT_MSG(&actual_info == &test_info,
"EventBroadcaster::OnTestFailure propagated the wrong test info\n");
});
event_broadcaster.OnTestFailure(test_case, test_info);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnTestCaseEnd() {
TESTCASE_EVENT_OBSERVER(End);
TestCase test_case(kTestCaseName, &Stub, &Stub);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
REGISTER_OBSERVERS(observers, event_broadcaster, [&test_case](const TestCase& actual) {
ZX_ASSERT_MSG(&actual == &test_case,
"EventBroadcaster::OnTestCaseEnd propagated the wrong test case\n");
});
event_broadcaster.OnTestCaseEnd(test_case);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnEnvironmentTearDown() {
RUNNER_EVENT_OBSERVER(EnvironmentTearDown);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
Runner runner(Reporter(/*stream*/ nullptr));
REGISTER_OBSERVERS(observers, event_broadcaster, [&runner](const Runner& actual_runner) {
ZX_ASSERT_MSG(&actual_runner == &runner,
"EventBroadcaster::OnIterationStart propagated the wrong runner.\n");
});
event_broadcaster.OnEnvironmentTearDown(runner);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnIterationEnd() {
ITERATION_EVENT_OBSERVER(End);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
Runner runner(Reporter(/*stream*/ nullptr));
REGISTER_OBSERVERS(
observers, event_broadcaster, [&runner](const Runner& actual_runner, int iteration) {
ZX_ASSERT_MSG(&actual_runner == &runner,
"EventBroadcaster::OnEnvironmentTearDown propagated the wrong runner.\n");
ZX_ASSERT_MSG(
iteration == 4,
"EventBroadcaster::OnEnvironmentTearDown propagated the wron iteration number.\n");
});
event_broadcaster.OnIterationEnd(runner, 4);
ValidateAllObserversNotified(observers);
}
void EventBroadcasterOnProgramEnd() {
RUNNER_EVENT_OBSERVER(ProgramEnd);
internal::EventBroadcaster event_broadcaster;
fbl::Vector<FakeObserver> observers;
observers.reserve(kNumObservers);
Runner runner(Reporter(/*stream*/ nullptr));
REGISTER_OBSERVERS(observers, event_broadcaster, [&runner](const Runner& actual_runner) {
ZX_ASSERT_MSG(&actual_runner == &runner,
"EventBroadcaster::OnProgramEnd propagated the wrong runner.\n");
});
event_broadcaster.OnProgramEnd(runner);
ValidateAllObserversNotified(observers);
}
} // namespace test
} // namespace zxtest