blob: 2de5e377951a46189bf0344d7f21086a40eab715 [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.
#include "src/media/audio/audio_core/threading_model.h"
#include <lib/async/cpp/task.h>
#include <gtest/gtest.h>
namespace media::audio {
namespace {
void ValidateThreadingModel(ThreadingModel* threading_model) {
// Sanity test we can run task on all loops.
bool fidl_task_run = false;
async::PostTask(threading_model->FidlDomain().dispatcher(),
[&fidl_task_run] { fidl_task_run = true; });
bool io_task_run = false;
async::PostTask(threading_model->IoDomain().dispatcher(), [&io_task_run] { io_task_run = true; });
// For threading models that use dynamically allocated loops, we submit a task to one loop we
// immediately release and another to a loop we retain to validate both modes of operation work.
bool mix1_task_run = false;
auto mix_domain1 = threading_model->AcquireMixDomain("");
async::PostTask(mix_domain1->dispatcher(), [&mix1_task_run] { mix1_task_run = true; });
bool mix2_task_run = false;
auto mix_domain2 = threading_model->AcquireMixDomain("");
async::PostTask(mix_domain2->dispatcher(), [&mix2_task_run] { mix2_task_run = true; });
// We quit first here to cause |RunAndJoinAllThreads| to exit after all currently queued tasks
// have executed.
threading_model->Quit();
threading_model->RunAndJoinAllThreads();
EXPECT_TRUE(fidl_task_run);
EXPECT_TRUE(io_task_run);
EXPECT_TRUE(mix1_task_run);
EXPECT_TRUE(mix2_task_run);
}
TEST(ThreadingModelTest, MixOnFidlThreadModel) {
auto threading_model = ThreadingModel::CreateWithMixStrategy(MixStrategy::kMixOnFidlThread);
// Expect |AcquireMixDomain| to be the same dispatcher as |FidlDomain().dispatcher|.
{
auto mix_domain = threading_model->AcquireMixDomain("");
EXPECT_EQ(threading_model->FidlDomain().dispatcher(), mix_domain->dispatcher());
}
// Expect |AcquireMixDomain| to return the same dispatcher across multiple calls.
{
auto mix_domain1 = threading_model->AcquireMixDomain("");
auto mix_domain2 = threading_model->AcquireMixDomain("");
EXPECT_EQ(mix_domain1->dispatcher(), mix_domain2->dispatcher());
}
// |IoDomain().dispatcher| should be different from |FidlDomain().dispatcher|.
EXPECT_NE(threading_model->FidlDomain().dispatcher(), threading_model->IoDomain().dispatcher());
ValidateThreadingModel(threading_model.get());
}
TEST(ThreadingModelTest, MixOnSingleThreadModel) {
auto threading_model = ThreadingModel::CreateWithMixStrategy(MixStrategy::kMixOnSingleThread);
// Expect all dispatchers to be unique.
{
auto mix_domain = threading_model->AcquireMixDomain("");
EXPECT_NE(threading_model->FidlDomain().dispatcher(), mix_domain->dispatcher());
}
{
auto mix_domain = threading_model->AcquireMixDomain("");
EXPECT_NE(threading_model->IoDomain().dispatcher(), mix_domain->dispatcher());
}
EXPECT_NE(threading_model->FidlDomain().dispatcher(), threading_model->IoDomain().dispatcher());
// But |AcquireMixDomain| always returns the same dispatcher.
{
auto mix_domain1 = threading_model->AcquireMixDomain("");
auto mix_domain2 = threading_model->AcquireMixDomain("");
EXPECT_EQ(mix_domain1->dispatcher(), mix_domain2->dispatcher());
}
ValidateThreadingModel(threading_model.get());
}
TEST(ThreadingModelTest, ThreadPerMixModel) {
auto threading_model = ThreadingModel::CreateWithMixStrategy(MixStrategy::kThreadPerMix);
// Expect all dispatchers to be unique.
{
auto mix_domain = threading_model->AcquireMixDomain("");
EXPECT_NE(threading_model->FidlDomain().dispatcher(), mix_domain->dispatcher());
}
{
auto mix_domain = threading_model->AcquireMixDomain("");
EXPECT_NE(threading_model->IoDomain().dispatcher(), mix_domain->dispatcher());
}
EXPECT_NE(threading_model->FidlDomain().dispatcher(), threading_model->IoDomain().dispatcher());
// And |AcquireMixDomain| returns different instances
{
auto mix_domain1 = threading_model->AcquireMixDomain("");
auto mix_domain2 = threading_model->AcquireMixDomain("");
EXPECT_NE(mix_domain1->dispatcher(), mix_domain2->dispatcher());
}
ValidateThreadingModel(threading_model.get());
}
} // namespace
} // namespace media::audio