eche_connection_scheduler_impl_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/webui/eche_app_ui/eche_connection_scheduler_impl.h"
  5. #include <memory>
  6. #include "ash/services/secure_channel/public/cpp/client/fake_connection_manager.h"
  7. #include "ash/webui/eche_app_ui/fake_feature_status_provider.h"
  8. #include "ash/webui/eche_app_ui/feature_status.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/time/time.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace ash {
  13. namespace eche_app {
  14. using ConnectionStatus = secure_channel::ConnectionManager::Status;
  15. class EcheConnectionSchedulerImplTest : public testing::Test {
  16. protected:
  17. EcheConnectionSchedulerImplTest() = default;
  18. EcheConnectionSchedulerImplTest(const EcheConnectionSchedulerImplTest&) =
  19. delete;
  20. EcheConnectionSchedulerImplTest& operator=(
  21. const EcheConnectionSchedulerImplTest&) = delete;
  22. ~EcheConnectionSchedulerImplTest() override = default;
  23. void SetUp() override {
  24. fake_connection_manager_ =
  25. std::make_unique<secure_channel::FakeConnectionManager>();
  26. fake_feature_status_provider_ =
  27. std::make_unique<FakeFeatureStatusProvider>();
  28. }
  29. void CreateConnectionScheduler() {
  30. connection_scheduler_ = std::make_unique<EcheConnectionSchedulerImpl>(
  31. fake_connection_manager_.get(), fake_feature_status_provider_.get());
  32. }
  33. base::TimeDelta GetCurrentBackoffDelay() {
  34. return connection_scheduler_->GetCurrentBackoffDelayTimeForTesting();
  35. }
  36. int GetBackoffFailureCount() {
  37. return connection_scheduler_->GetBackoffFailureCountForTesting();
  38. }
  39. base::test::TaskEnvironment task_environment_{
  40. base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  41. std::unique_ptr<secure_channel::FakeConnectionManager>
  42. fake_connection_manager_;
  43. std::unique_ptr<FakeFeatureStatusProvider> fake_feature_status_provider_;
  44. std::unique_ptr<EcheConnectionSchedulerImpl> connection_scheduler_;
  45. };
  46. TEST_F(EcheConnectionSchedulerImplTest, SuccesssfullyAttemptConnection) {
  47. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  48. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  49. CreateConnectionScheduler();
  50. connection_scheduler_->ScheduleConnectionNow();
  51. // Verify that the ConnectionManager has attempted to connect.
  52. EXPECT_EQ(1u, fake_connection_manager_->num_attempt_connection_calls());
  53. // Simulate state changes with AttemptConnection().
  54. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  55. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnected);
  56. // Verify only 1 call to AttemptConnection() was ever made.
  57. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  58. // Verify that we did not attempt a backoff retry.
  59. EXPECT_EQ(GetBackoffFailureCount(), 0);
  60. }
  61. TEST_F(EcheConnectionSchedulerImplTest,
  62. FeatureDisabledCanEstablishConnectionProperly) {
  63. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  64. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisabled);
  65. CreateConnectionScheduler();
  66. connection_scheduler_->ScheduleConnectionNow();
  67. // Verify that the ConnectionManager did not attempt connection.
  68. EXPECT_EQ(0u, fake_connection_manager_->num_attempt_connection_calls());
  69. // Verify that we did not attempt a backoff retry.
  70. EXPECT_EQ(0, GetBackoffFailureCount());
  71. fake_connection_manager_->SetStatus(ConnectionStatus::kConnected);
  72. CreateConnectionScheduler();
  73. // Verify that the ConnectionManager did not attempt connection.
  74. EXPECT_EQ(0u, fake_connection_manager_->num_attempt_connection_calls());
  75. // Verify that we did not attempt a backoff retry.
  76. EXPECT_EQ(0, GetBackoffFailureCount());
  77. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  78. connection_scheduler_->ScheduleConnectionNow();
  79. // Verify that the ConnectionManager has attempted to connect.
  80. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  81. // Verify that we did not attempt a backoff retry.
  82. EXPECT_EQ(GetBackoffFailureCount(), 0);
  83. // Simulate state changes with AttemptConnection().
  84. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  85. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnected);
  86. // Verify only 1 call to AttemptConnection() was ever made.
  87. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  88. // Verify that we did not attempt a backoff retry.
  89. EXPECT_EQ(GetBackoffFailureCount(), 0);
  90. }
  91. TEST_F(EcheConnectionSchedulerImplTest, ShouldNotEstablishConnection) {
  92. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  93. fake_feature_status_provider_->SetStatus(FeatureStatus::kIneligible);
  94. CreateConnectionScheduler();
  95. connection_scheduler_->ScheduleConnectionNow();
  96. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 0u);
  97. EXPECT_EQ(GetBackoffFailureCount(), 0);
  98. fake_feature_status_provider_->SetStatus(FeatureStatus::kDependentFeature);
  99. connection_scheduler_->ScheduleConnectionNow();
  100. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 0u);
  101. EXPECT_EQ(GetBackoffFailureCount(), 0);
  102. fake_feature_status_provider_->SetStatus(
  103. FeatureStatus::kDependentFeaturePending);
  104. connection_scheduler_->ScheduleConnectionNow();
  105. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 0u);
  106. EXPECT_EQ(GetBackoffFailureCount(), 0);
  107. }
  108. TEST_F(EcheConnectionSchedulerImplTest, BackoffRetryWithUpdatedConnection) {
  109. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  110. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  111. CreateConnectionScheduler();
  112. connection_scheduler_->ScheduleConnectionNow();
  113. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  114. // Simulate state changes with AttemptConnection().
  115. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  116. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  117. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  118. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  119. EXPECT_EQ(GetBackoffFailureCount(), 1);
  120. // Move forward time to the next backoff retry with disconnected status.
  121. task_environment_.FastForwardBy(GetCurrentBackoffDelay());
  122. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 2u);
  123. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  124. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  125. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  126. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  127. EXPECT_EQ(GetBackoffFailureCount(), 2);
  128. // Move forward time to the next backoff retry, this time with connected
  129. // status.
  130. task_environment_.FastForwardBy(GetCurrentBackoffDelay());
  131. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 3u);
  132. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  133. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  134. fake_connection_manager_->SetStatus(ConnectionStatus::kConnected);
  135. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnected);
  136. // Expected no more backoff failures since connection is now established.
  137. EXPECT_EQ(GetBackoffFailureCount(), 0);
  138. // Fast forward time and confirm no other retries have been made.
  139. task_environment_.FastForwardBy(base::Seconds(100));
  140. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 3u);
  141. EXPECT_EQ(GetBackoffFailureCount(), 0);
  142. EXPECT_EQ(fake_feature_status_provider_->GetStatus(),
  143. FeatureStatus::kConnected);
  144. }
  145. TEST_F(EcheConnectionSchedulerImplTest,
  146. BackoffRetryWithUpdatedFeaturesAndConnection) {
  147. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  148. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  149. CreateConnectionScheduler();
  150. connection_scheduler_->ScheduleConnectionNow();
  151. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  152. // Simulate state changes with AttemptConnection().
  153. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  154. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  155. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  156. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  157. EXPECT_EQ(1, GetBackoffFailureCount());
  158. // Simulate the feature status switched to kIneligible.
  159. fake_feature_status_provider_->SetStatus(FeatureStatus::kIneligible);
  160. // Expect the backoff to reset and never attempt to kickoff another
  161. // connection.
  162. EXPECT_EQ(GetBackoffFailureCount(), 0);
  163. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  164. // Expect that connection has been disconnected.
  165. EXPECT_EQ(fake_connection_manager_->num_disconnect_calls(), 1u);
  166. // Fast forward time and confirm no other retries have been made.
  167. task_environment_.FastForwardBy(base::Seconds(100));
  168. EXPECT_EQ(GetBackoffFailureCount(), 0);
  169. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  170. // Simulate the feature re-enabled and the connection kickoff should start.
  171. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  172. // The next ScheduleConnection() was not caused by a previous failure, expect
  173. // backoff failure count to not increase.
  174. EXPECT_EQ(GetBackoffFailureCount(), 0);
  175. // Move forward in time and confirm backoff attempted another retry.
  176. task_environment_.FastForwardBy(GetCurrentBackoffDelay());
  177. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 2u);
  178. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  179. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  180. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  181. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  182. // The next ScheduleConnection() was caused by a previous failure, expect 1
  183. // failure count.
  184. EXPECT_EQ(GetBackoffFailureCount(), 1);
  185. }
  186. TEST_F(EcheConnectionSchedulerImplTest,
  187. DisconnectAndClearBackoffAttemptsSuccesssfully) {
  188. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  189. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  190. CreateConnectionScheduler();
  191. connection_scheduler_->ScheduleConnectionNow();
  192. // Verify that the ConnectionManager has attempted to connect.
  193. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  194. // Simulate state changes with AttemptConnection().
  195. fake_connection_manager_->SetStatus(ConnectionStatus::kConnecting);
  196. fake_feature_status_provider_->SetStatus(FeatureStatus::kConnecting);
  197. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  198. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  199. EXPECT_EQ(1, GetBackoffFailureCount());
  200. connection_scheduler_->DisconnectAndClearBackoffAttempts();
  201. // Expect the backoff to reset and never attempt to kickoff another
  202. // connection.
  203. EXPECT_EQ(GetBackoffFailureCount(), 0);
  204. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  205. // Expect that connection has been disconnected.
  206. EXPECT_EQ(fake_connection_manager_->num_disconnect_calls(), 1u);
  207. }
  208. TEST_F(EcheConnectionSchedulerImplTest, SimulateIneligibleToDisconnected) {
  209. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  210. fake_feature_status_provider_->SetStatus(FeatureStatus::kIneligible);
  211. CreateConnectionScheduler();
  212. EXPECT_EQ(GetBackoffFailureCount(), 0);
  213. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 0u);
  214. // Flip to feature available. Expect a scheduled connection.
  215. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  216. EXPECT_EQ(GetBackoffFailureCount(), 0);
  217. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  218. }
  219. TEST_F(EcheConnectionSchedulerImplTest,
  220. SimulateDependentFeatureToDisconnected) {
  221. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  222. fake_feature_status_provider_->SetStatus(FeatureStatus::kDependentFeature);
  223. CreateConnectionScheduler();
  224. EXPECT_EQ(GetBackoffFailureCount(), 0);
  225. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 0u);
  226. // Flip to feature available. Expect a scheduled connection.
  227. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  228. EXPECT_EQ(GetBackoffFailureCount(), 0);
  229. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  230. }
  231. TEST_F(EcheConnectionSchedulerImplTest,
  232. SimulatekDependentFeaturePendingtoDisconnected) {
  233. fake_connection_manager_->SetStatus(ConnectionStatus::kDisconnected);
  234. fake_feature_status_provider_->SetStatus(
  235. FeatureStatus::kDependentFeaturePending);
  236. CreateConnectionScheduler();
  237. EXPECT_EQ(GetBackoffFailureCount(), 0);
  238. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 0u);
  239. // Flip to feature available. Expect a scheduled connection.
  240. fake_feature_status_provider_->SetStatus(FeatureStatus::kDisconnected);
  241. EXPECT_EQ(GetBackoffFailureCount(), 0);
  242. EXPECT_EQ(fake_connection_manager_->num_attempt_connection_calls(), 1u);
  243. }
  244. } // namespace eche_app
  245. } // namespace ash