diff --git a/garnet/packages/tests/BUILD.gn b/garnet/packages/tests/BUILD.gn index 56f7b282f9265c531647e28db726130e43b77bc5..ae0004a7d674fba1fd7fa01705077a673569421e 100644 --- a/garnet/packages/tests/BUILD.gn +++ b/garnet/packages/tests/BUILD.gn @@ -796,6 +796,7 @@ group("media") { "//garnet/public/lib/media/timeline:media_lib_timeline_tests", "//sdk/lib/media/audio_dfx/cpp:audio_dfx_tests", "//src/media/audio/audio_core/mixer:audio_mixer_tests", + "//src/media/audio/audio_core/test:audio_device_tests", "//src/media/audio/audio_core/test:audio_fidl_tests", ] } diff --git a/src/media/audio/audio_core/test/BUILD.gn b/src/media/audio/audio_core/test/BUILD.gn index 8a066a096fad2a1273e5116fadb03526b7ae5c03..8cfed5f7da6326e1caf041ad7031d79fa95eb2c3 100644 --- a/src/media/audio/audio_core/test/BUILD.gn +++ b/src/media/audio/audio_core/test/BUILD.gn @@ -8,12 +8,25 @@ import("//build/testing/environments.gni") group("test") { testonly = true deps = [ - ":audio_device_tests_bin", + ":audio_device_tests", ":audio_fidl_tests", ":audio_loopback_tests_bin", ] } +test_package("audio_device_tests") { + deps = [ + ":audio_device_tests_bin", + ] + + tests = [ + { + name = "audio_device_tests" + environments = basic_envs + }, + ] +} + executable("audio_device_tests_bin") { testonly = true output_name = "audio_device_tests" diff --git a/src/media/audio/audio_core/test/audio_device_test.cc b/src/media/audio/audio_core/test/audio_device_test.cc index 3a85d6798695c478340a6e752d67bdba8a0be572..4b868ccb2a66d27c72150c974261000567512413 100644 --- a/src/media/audio/audio_core/test/audio_device_test.cc +++ b/src/media/audio/audio_core/test/audio_device_test.cc @@ -23,7 +23,7 @@ namespace media::audio::test { // std::shared_ptr<const ::component::Services> AudioDeviceTest::environment_services_; -fuchsia::virtualaudio::ControlSyncPtr AudioDeviceTest::control_; +fuchsia::virtualaudio::ControlSyncPtr AudioDeviceTest::control_sync_; uint16_t AudioDeviceTest::initial_input_device_count_ = kInvalidDeviceCount; uint16_t AudioDeviceTest::initial_output_device_count_ = kInvalidDeviceCount; @@ -37,6 +37,45 @@ uint32_t AudioDeviceTest::initial_output_gain_flags_ = 0; // // AudioDeviceTest implementation // + +// static +void AudioDeviceTest::SetEnvironmentServices( + std::shared_ptr<const ::component::Services> environment_services) { + environment_services_ = environment_services; +} + +// static +void AudioDeviceTest::SetControl( + fuchsia::virtualaudio::ControlSyncPtr control_sync) { + AudioDeviceTest::control_sync_ = std::move(control_sync); +} + +// static +void AudioDeviceTest::ResetVirtualDevices() { + DisableVirtualDevices(); + zx_status_t status = control_sync_->Enable(); + ASSERT_EQ(status, ZX_OK); +} + +// static +void AudioDeviceTest::DisableVirtualDevices() { + zx_status_t status = control_sync_->Disable(); + ASSERT_EQ(status, ZX_OK); + + uint32_t num_inputs = -1, num_outputs = -1, num_tries = 0; + do { + status = control_sync_->GetNumDevices(&num_inputs, &num_outputs); + ASSERT_EQ(status, ZX_OK); + + ++num_tries; + } while ((num_inputs != 0 || num_outputs != 0) && num_tries < 100); + ASSERT_EQ(num_inputs, 0u); + ASSERT_EQ(num_outputs, 0u); +} + +// static +void AudioDeviceTest::TearDownTestSuite() { DisableVirtualDevices(); } + void AudioDeviceTest::SetUp() { ::gtest::RealLoopFixture::SetUp(); diff --git a/src/media/audio/audio_core/test/audio_device_test.h b/src/media/audio/audio_core/test/audio_device_test.h index 5285ad2ddd52a8e2560e2ba47fb3dab2db086174..5c5dc7dfee360f747e4ed8b1db667cf019149537 100644 --- a/src/media/audio/audio_core/test/audio_device_test.h +++ b/src/media/audio/audio_core/test/audio_device_test.h @@ -24,6 +24,7 @@ constexpr uint32_t kSetFlagMask = fuchsia::media::SetAudioGainFlag_GainValid | fuchsia::media::SetAudioGainFlag_MuteValid | fuchsia::media::SetAudioGainFlag_AgcValid; +// We set vars to these values before async callbacks, to detect no-response. constexpr uint16_t kInvalidDeviceCount = -1; constexpr uint64_t kInvalidDeviceToken = -1; constexpr fuchsia::media::AudioGainInfo kInvalidGainInfo = { @@ -39,26 +40,19 @@ const fuchsia::media::AudioDeviceInfo kInvalidDeviceInfo = { class AudioDeviceTest : public gtest::RealLoopFixture { public: static void SetEnvironmentServices( - std::shared_ptr<const ::component::Services> environment_services) { - environment_services_ = environment_services; - } + std::shared_ptr<const ::component::Services> environment_services); // Set up once when binary loaded; this is used at start/end of each suite. - static void SetControl(fuchsia::virtualaudio::ControlSyncPtr control) { - AudioDeviceTest::control_ = std::move(control); - } - static void ResetVirtualDevices() { - control_->Disable(); - control_->Enable(); - } - static void DisableVirtualDevices() { control_->Disable(); } + static void SetControl(fuchsia::virtualaudio::ControlSyncPtr control_sync); + static void ResetVirtualDevices(); + static void DisableVirtualDevices(); protected: // "Regional" per-test-suite set-up. Called before first test in this suite. - static void SetUpTestSuite() { DisableVirtualDevices(); } + // static void SetUpTestSuite(); // Per-test-suite tear-down. Called after last test in this suite. - static void TearDownTestSuite() { DisableVirtualDevices(); } + static void TearDownTestSuite(); void SetUp() override; void TearDown() override; @@ -93,7 +87,7 @@ class AudioDeviceTest : public gtest::RealLoopFixture { static uint32_t initial_output_gain_flags_; static std::shared_ptr<const ::component::Services> environment_services_; - static fuchsia::virtualaudio::ControlSyncPtr control_; + static fuchsia::virtualaudio::ControlSyncPtr control_sync_; fuchsia::media::AudioDeviceEnumeratorPtr audio_dev_enum_; diff --git a/src/media/audio/audio_core/test/audio_tests_shared.h b/src/media/audio/audio_core/test/audio_tests_shared.h index a71b1809a08d4b14342279b3f3dec4a9a2e7b308..ac7011b831bd33ef97a83c669c35355eb4bae22f 100644 --- a/src/media/audio/audio_core/test/audio_tests_shared.h +++ b/src/media/audio/audio_core/test/audio_tests_shared.h @@ -9,25 +9,31 @@ namespace media::audio::test { -// For operations expected to complete, wait five seconds to avoid flaky test -// behavior in high-load (high-latency) test environments. For reference, today -// on highly-loaded QEMU instances we see timeouts if we wait 20 ms, but not if -// we wait 50 ms. This value is a full 100x that value, so shouldn't be flaky. +// For operations expected to generate a response, wait __5 minutes__. +// 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 15000x that (!), and WELL beyond +// the limit of any human acceptability, so shouldn't exhibit flakiness. // -// Conversely, when we DO expect a timeout, wait 50 ms (normal response is <5 -// ms, usually <1). These values codify the following ordered priorities: -// 1) False-positive test failures are expensive and must be eliminated; -// 2) Having satisfying #1, streamline test-run-time (time=resources=cost); -// 3) Minimize false-negative test outcomes (undetected regressions). +// Conversely, when we DO expect a timeout, wait only __50 ms__. +// Normal response is <5 ms, usually <1 ms on well-performing systems. +// +// 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); +// 2a) Also, avoid false-negatives (minimize undetected regressions). // // Finally, when waiting for a timeout, our granularity (how frequently we check -// for response) can be coarse, but when expecting a response we can save time -// by checking more frequently than the default 10 ms. The kDurationGranularity -// constant should only be used in conjunction with kDurationResponseExpected. +// for response) can be coarse (the default is every 10 ms). However, when +// expecting a response we can save time by checking more frequently. Restated, +// kDurationResponseExpected should ALWAYS use kDurationGranularity, and +// kDurationTimeoutExpected need NEVER do so. // // TODO(mpuryear): Refactor tests to eliminate "wait for nothing bad to happen". -constexpr zx::duration kDurationResponseExpected = zx::sec(5); -constexpr zx::duration kDurationTimeoutExpected = zx::msec(100); +constexpr zx::duration kDurationResponseExpected = zx::sec(300); +constexpr zx::duration kDurationTimeoutExpected = zx::msec(50); constexpr zx::duration kDurationGranularity = zx::msec(1); constexpr char kConnectionErr[] =