xref: /aosp_15_r20/external/ot-br-posix/tests/gtest/test_async_task.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2024, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <gtest/gtest.h>
30 
31 #include <memory>
32 #include <string>
33 
34 #include <openthread/error.h>
35 
36 #include "common/code_utils.hpp"
37 #include "ncp/async_task.hpp"
38 
39 using otbr::Ncp::AsyncTask;
40 using otbr::Ncp::AsyncTaskPtr;
41 
TEST(AsyncTask,TestOneStep)42 TEST(AsyncTask, TestOneStep)
43 {
44     AsyncTaskPtr task;
45     AsyncTaskPtr step1;
46     int          resultHandlerCalledTimes = 0;
47     int          stepCount                = 0;
48 
49     auto errorHandler = [&resultHandlerCalledTimes](otError aError, const std::string &aErrorInfo) {
50         OTBR_UNUSED_VARIABLE(aError);
51         OTBR_UNUSED_VARIABLE(aErrorInfo);
52 
53         resultHandlerCalledTimes++;
54     };
55 
56     task = std::make_shared<AsyncTask>(errorHandler);
57     task->First([&stepCount, &step1](AsyncTaskPtr aNext) {
58         step1 = std::move(aNext);
59         stepCount++;
60     });
61     task->Run();
62 
63     step1->SetResult(OT_ERROR_NONE, "Success");
64 
65     EXPECT_EQ(resultHandlerCalledTimes, 1);
66     EXPECT_EQ(stepCount, 1);
67 }
68 
TEST(AsyncTask,TestNoResultReturned)69 TEST(AsyncTask, TestNoResultReturned)
70 {
71     AsyncTaskPtr task;
72     AsyncTaskPtr step1;
73     AsyncTaskPtr step2;
74     AsyncTaskPtr step3;
75 
76     int     resultHandlerCalledTimes = 0;
77     int     stepCount                = 0;
78     otError error                    = OT_ERROR_NONE;
79 
80     auto errorHandler = [&resultHandlerCalledTimes, &error](otError aError, const std::string &aErrorInfo) {
81         OTBR_UNUSED_VARIABLE(aErrorInfo);
82 
83         resultHandlerCalledTimes++;
84         error = aError;
85     };
86 
87     task = std::make_shared<AsyncTask>(errorHandler);
88     task->First([&stepCount, &step1](AsyncTaskPtr aNext) {
89             step1 = std::move(aNext);
90             stepCount++;
91         })
92         ->Then([&stepCount, &step2](AsyncTaskPtr aNext) {
93             step2 = std::move(aNext);
94             stepCount++;
95         })
96         ->Then([&stepCount, &step3](AsyncTaskPtr aNext) {
97             step3 = std::move(aNext);
98             stepCount++;
99         });
100     task->Run();
101 
102     // Asyn task ends without calling 'SetResult'.
103     step1 = nullptr;
104     task  = nullptr;
105 
106     EXPECT_EQ(resultHandlerCalledTimes, 1);
107     EXPECT_EQ(stepCount, 1);
108     EXPECT_EQ(error, OT_ERROR_FAILED);
109 }
110 
TEST(AsyncTask,TestMultipleStepsSuccess)111 TEST(AsyncTask, TestMultipleStepsSuccess)
112 {
113     AsyncTaskPtr task;
114     AsyncTaskPtr step1;
115     AsyncTaskPtr step2;
116     AsyncTaskPtr step3;
117 
118     int     resultHandlerCalledTimes = 0;
119     int     stepCount                = 0;
120     otError error                    = OT_ERROR_NONE;
121 
122     auto errorHandler = [&resultHandlerCalledTimes, &error](otError aError, const std::string &aErrorInfo) {
123         OTBR_UNUSED_VARIABLE(aErrorInfo);
124 
125         resultHandlerCalledTimes++;
126         error = aError;
127     };
128 
129     task = std::make_shared<AsyncTask>(errorHandler);
130     task->First([&stepCount, &step1](AsyncTaskPtr aNext) {
131             step1 = std::move(aNext);
132             stepCount++;
133         })
134         ->Then([&stepCount, &step2](AsyncTaskPtr aNext) {
135             step2 = std::move(aNext);
136             stepCount++;
137         })
138         ->Then([&stepCount, &step3](AsyncTaskPtr aNext) {
139             step3 = std::move(aNext);
140             stepCount++;
141         });
142     task->Run();
143 
144     EXPECT_EQ(stepCount, 1);
145     step1->SetResult(OT_ERROR_NONE, "");
146     EXPECT_EQ(resultHandlerCalledTimes, 0);
147 
148     EXPECT_EQ(stepCount, 2);
149     step2->SetResult(OT_ERROR_NONE, "");
150     EXPECT_EQ(resultHandlerCalledTimes, 0);
151 
152     EXPECT_EQ(stepCount, 3);
153     error = OT_ERROR_GENERIC;
154     step3->SetResult(OT_ERROR_NONE, "");
155     EXPECT_EQ(resultHandlerCalledTimes, 1);
156     EXPECT_EQ(error, OT_ERROR_NONE);
157 }
158 
TEST(AsyncTask,TestMultipleStepsFailedHalfWay)159 TEST(AsyncTask, TestMultipleStepsFailedHalfWay)
160 {
161     AsyncTaskPtr task;
162     AsyncTaskPtr step1;
163     AsyncTaskPtr step2;
164     AsyncTaskPtr step3;
165 
166     int     resultHandlerCalledTimes = 0;
167     int     stepCount                = 0;
168     otError error                    = OT_ERROR_NONE;
169 
170     auto errorHandler = [&resultHandlerCalledTimes, &error](otError aError, const std::string &aErrorInfo) {
171         OTBR_UNUSED_VARIABLE(aErrorInfo);
172 
173         resultHandlerCalledTimes++;
174         error = aError;
175     };
176 
177     task = std::make_shared<AsyncTask>(errorHandler);
178     task->First([&stepCount, &step1](AsyncTaskPtr aNext) {
179             step1 = std::move(aNext);
180             stepCount++;
181         })
182         ->Then([&stepCount, &step2](AsyncTaskPtr aNext) {
183             step2 = std::move(aNext);
184             stepCount++;
185         })
186         ->Then([&stepCount, &step3](AsyncTaskPtr aNext) {
187             step3 = std::move(aNext);
188             stepCount++;
189         });
190     task->Run();
191 
192     EXPECT_EQ(stepCount, 1);
193     step1->SetResult(OT_ERROR_NONE, "");
194     EXPECT_EQ(resultHandlerCalledTimes, 0);
195 
196     EXPECT_EQ(stepCount, 2);
197     step2->SetResult(OT_ERROR_BUSY, "");
198     EXPECT_EQ(resultHandlerCalledTimes, 1);
199     EXPECT_EQ(error, OT_ERROR_BUSY);
200 }
201