xref: /aosp_15_r20/system/media/audio_utils/tests/audio_deferredexecutor_tests.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <audio_utils/DeferredExecutor.h>
18 #include <atomic>
19 #include <gtest/gtest.h>
20 
21 // Test object
22 class RunOnClose {
23 public:
24     template <typename F>
RunOnClose(F && f)25     explicit RunOnClose(F&& f) : thunk_(std::forward<F>(f)) {}
26     explicit RunOnClose(RunOnClose&& other) = default;
~RunOnClose()27     ~RunOnClose() { if (thunk_) thunk_(); }
28 private:
29     std::function<void()> thunk_;
30 };
31 
TEST(deferredexecutor,basic)32 TEST(deferredexecutor, basic) {
33     std::atomic<int> disposed{};
34     std::atomic<int> deferred{};
35     {
36         android::audio_utils::DeferredExecutor de;
37 
38         de.defer([&](){++deferred;});
39         de.dispose(std::make_shared<RunOnClose>([&]{++disposed;}));
40         EXPECT_EQ(0, deferred);
41         EXPECT_EQ(0, disposed);
42         EXPECT_EQ(false, de.empty());
43         de.process();
44         EXPECT_EQ(1, deferred);
45         EXPECT_EQ(1, disposed);
46         EXPECT_EQ(true, de.empty());
47     }
48     EXPECT_EQ(1, deferred);
49     EXPECT_EQ(1, disposed);
50 }
51 
TEST(deferredexecutor,clear)52 TEST(deferredexecutor, clear) {
53     std::atomic<int> disposed{};
54     std::atomic<int> deferred{};
55     {
56         android::audio_utils::DeferredExecutor de;
57 
58         de.defer([&](){++deferred;});
59         de.dispose(std::make_shared<RunOnClose>([&]{++disposed;}));
60         EXPECT_EQ(0, deferred);
61         EXPECT_EQ(0, disposed);
62         EXPECT_EQ(false, de.empty());
63         de.clear();
64         EXPECT_EQ(0, deferred);
65         EXPECT_EQ(1, disposed);
66         EXPECT_EQ(true, de.empty());
67     }
68     EXPECT_EQ(0, deferred);
69     EXPECT_EQ(1, disposed);
70 }
71 
72 class DtorAndRecursive : public testing::TestWithParam<std::tuple<bool, bool>> {};
73 
TEST_P(DtorAndRecursive,deferred_adds_deferred)74 TEST_P(DtorAndRecursive, deferred_adds_deferred) {
75     const auto [processInDtor, recursive] = GetParam();
76     std::atomic<int> disposed{};
77     std::atomic<int> deferred{};
78     {
79         android::audio_utils::DeferredExecutor de(processInDtor);
80 
81         // The deferred action adds another deferred action.
82         de.defer([&](){ de.defer([&](){++deferred;}); ++deferred;});
83         de.dispose(std::make_shared<RunOnClose>([&]{++disposed;}));
84         EXPECT_EQ(0, deferred);
85         EXPECT_EQ(0, disposed);
86         EXPECT_EQ(false, de.empty());
87         de.process(recursive);
88         EXPECT_EQ(1 + recursive, deferred);
89         EXPECT_EQ(1, disposed);
90         EXPECT_EQ(recursive, de.empty());
91     }
92     EXPECT_EQ(1 + (recursive || processInDtor), deferred);
93     EXPECT_EQ(1, disposed);
94 }
95 
__anon0d4bc96f0802(const auto& param) 96 static const auto paramToString = [](const auto& param) {
97     const auto [processInDtor, recursive] = param.param;
98     return std::string("processInDtor_")
99             .append(processInDtor ? "true" : "false")
100             .append("__recursive_")
101             .append(recursive ? "true" : "false");
102 };
103 
104 INSTANTIATE_TEST_SUITE_P(DeferredExecutorSuite,
105         DtorAndRecursive,
106         testing::Combine(testing::Bool(), testing::Bool()),
107         paramToString);
108