blob: a46bf48a69e09a6cadefd05e2b0e69b1d9216c65 [file] [log] [blame]
// Copyright 2019 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.
#ifndef SRC_MEDIA_AUDIO_LIB_TEST_TEST_FIXTURE_H_
#define SRC_MEDIA_AUDIO_LIB_TEST_TEST_FIXTURE_H_
#include <lib/fit/function.h>
#include <lib/gtest/real_loop_fixture.h>
#include <optional>
#include "src/lib/fxl/logging.h"
namespace media::audio::test {
// For operations expected to generate a response, wait __1 minute__. We do
// this to avoid flaky results when testing on high-load (high-latency)
// environments. For reference, in mid-2018 when observing highly-loaded local
// QEMU instances running code that correctly generated completion responses, we
// observed timeouts if waiting 20 ms, but not when waiting 50 ms. This value
// will be 3000x that (!), and is WELL beyond the limit of human acceptability.
// Thus, intermittent failures (rather than being a "potentially flaky test")
// mean that the system is, intermittently, UNACCEPTABLE.
//
// Also, when expecting a response we can save time by checking more frequently.
// Restated, kDurationResponseExpected should ALWAYS use kDurationGranularity.
//
// These two values codify the following ordered priorities:
// 1) False-positive test failures are expensive and must be eliminated.
// 2) Having done that, streamline test run-time (time=resources=cost);
constexpr zx::duration kDurationResponseExpected = zx::sec(60);
constexpr zx::duration kDurationGranularity = zx::duration::infinite();
constexpr char kDisconnectErr[] =
"Connection to fuchsia.media FIDL interface was lost!\n";
constexpr char kTimeoutErr[] = "Timeout -- no callback received!\n";
constexpr char kCallbackErr[] = "Unexpected callback received!\n";
//
// TestFixture
//
class TestFixture : public ::gtest::RealLoopFixture {
protected:
void SetUp() override;
void TearDown() override;
// Simple handler, when the only required response is to record the error.
auto ErrorHandler() {
return [this](zx_status_t error) {
error_occurred_ = true;
error_code_ = error;
};
}
// Accept (and call) a custom handler, for more nuanced error responses.
template <typename Callable>
auto ErrorHandler(Callable err_handler) {
return [this, err_handler = std::move(err_handler)](zx_status_t error) {
error_occurred_ = true;
error_code_ = error;
err_handler(error);
};
}
// Simple callback, when the only requirement is to record the callback.
auto CompletionCallback() {
return [this]() { callback_received_ = true; };
}
// Accept (and call) a custom callback, for more nuanced behavior.
template <typename Callable>
auto CompletionCallback(Callable callback) {
return [this, callback = std::move(callback)](auto&&... args) {
callback_received_ = true;
callback(std::forward<decltype(args)>(args)...);
};
}
// The below methods contain gtest EXPECT checks that verify basic outcomes.
//
// Wait for CompletionCallback or ErrorHandler, expecting callback.
virtual void ExpectCallback();
// Wait for a more nuanced condition (not just callback_received_).
void ExpectCondition(fit::function<bool()> condition);
// Wait for CompletionCallback or ErrorHandler, expecting the specified error.
virtual void ExpectDisconnect() { ExpectError(ZX_ERR_PEER_CLOSED); }
void ExpectError(zx_status_t expect_error);
// Set expectations for negative test cases. Called by ExpectError/Disconnect.
virtual void SetNegativeExpectations() { error_expected_ = true; }
bool error_expected_ = false;
bool error_occurred_ = false;
zx_status_t error_code_ = ZX_OK;
private:
bool callback_received_ = false;
// Run our asynchronous loop, until the provided condition is satisfied
// (returns TRUE) or until a timeout occurs (returns FALSE).
bool RunUntilComplete(fit::function<bool()> condition);
};
} // namespace media::audio::test
#endif // SRC_MEDIA_AUDIO_LIB_TEST_TEST_FIXTURE_H_