/net/spdy/priority_write_scheduler_test.cc

https://gitlab.com/0072016/Facebook-SDK- · C++ · 289 lines · 201 code · 48 blank · 40 comment · 0 complexity · 0c1abc5d1c57a94578333af47fbd3abf MD5 · raw file

  1. // Copyright (c) 2015 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 "net/spdy/priority_write_scheduler.h"
  5. #include "net/test/gtest_util.h"
  6. namespace net {
  7. namespace test {
  8. namespace {
  9. class PriorityWriteSchedulerTest : public ::testing::Test {
  10. public:
  11. PriorityWriteScheduler<int> scheduler_;
  12. };
  13. TEST_F(PriorityWriteSchedulerTest, RegisterUnregisterStreams) {
  14. EXPECT_FALSE(scheduler_.HasReadyStreams());
  15. scheduler_.RegisterStream(1, 1);
  16. // Try redundant registrations.
  17. EXPECT_DFATAL(scheduler_.RegisterStream(1, 1), "Stream 1 already registered");
  18. EXPECT_DFATAL(scheduler_.RegisterStream(1, 2), "Stream 1 already registered");
  19. scheduler_.RegisterStream(2, 3);
  20. // Verify registration != ready.
  21. EXPECT_FALSE(scheduler_.HasReadyStreams());
  22. scheduler_.UnregisterStream(1);
  23. scheduler_.UnregisterStream(2);
  24. // Try redundant unregistration.
  25. EXPECT_DFATAL(scheduler_.UnregisterStream(1), "Stream 1 not registered");
  26. EXPECT_DFATAL(scheduler_.UnregisterStream(2), "Stream 2 not registered");
  27. }
  28. TEST_F(PriorityWriteSchedulerTest, GetStreamPriority) {
  29. EXPECT_DFATAL(EXPECT_EQ(kV3LowestPriority, scheduler_.GetStreamPriority(1)),
  30. "Stream 1 not registered");
  31. scheduler_.RegisterStream(1, 3);
  32. EXPECT_EQ(3, scheduler_.GetStreamPriority(1));
  33. // Redundant registration shouldn't change stream priority.
  34. EXPECT_DFATAL(scheduler_.RegisterStream(1, 4), "Stream 1 already registered");
  35. EXPECT_EQ(3, scheduler_.GetStreamPriority(1));
  36. scheduler_.UpdateStreamPriority(1, 5);
  37. EXPECT_EQ(5, scheduler_.GetStreamPriority(1));
  38. // Toggling ready state shouldn't change stream priority.
  39. scheduler_.MarkStreamReady(1, true);
  40. EXPECT_EQ(5, scheduler_.GetStreamPriority(1));
  41. // Test changing priority of ready stream.
  42. EXPECT_EQ(1u, scheduler_.NumReadyStreams(5));
  43. scheduler_.UpdateStreamPriority(1, 6);
  44. EXPECT_EQ(6, scheduler_.GetStreamPriority(1));
  45. EXPECT_EQ(0u, scheduler_.NumReadyStreams(5));
  46. EXPECT_EQ(1u, scheduler_.NumReadyStreams(6));
  47. EXPECT_EQ(1, scheduler_.PopNextReadyStream());
  48. EXPECT_EQ(6, scheduler_.GetStreamPriority(1));
  49. scheduler_.UnregisterStream(1);
  50. EXPECT_DFATAL(EXPECT_EQ(kV3LowestPriority, scheduler_.GetStreamPriority(1)),
  51. "Stream 1 not registered");
  52. }
  53. TEST_F(PriorityWriteSchedulerTest, UpdateStreamPriority) {
  54. // Updating priority of unregistered stream should have no effect.
  55. EXPECT_DFATAL(EXPECT_EQ(kV3LowestPriority, scheduler_.GetStreamPriority(3)),
  56. "Stream 3 not registered");
  57. EXPECT_DFATAL(scheduler_.UpdateStreamPriority(3, 1),
  58. "Stream 3 not registered");
  59. EXPECT_DFATAL(EXPECT_EQ(kV3LowestPriority, scheduler_.GetStreamPriority(3)),
  60. "Stream 3 not registered");
  61. scheduler_.RegisterStream(3, 1);
  62. EXPECT_EQ(1, scheduler_.GetStreamPriority(3));
  63. scheduler_.UpdateStreamPriority(3, 2);
  64. EXPECT_EQ(2, scheduler_.GetStreamPriority(3));
  65. // Updating priority of stream to current priority value is valid, but has no
  66. // effect.
  67. scheduler_.UpdateStreamPriority(3, 2);
  68. EXPECT_EQ(2, scheduler_.GetStreamPriority(3));
  69. // Even though stream 4 is marked ready after stream 5, it should be returned
  70. // first by PopNextReadyStream() since it has higher priority.
  71. scheduler_.RegisterStream(4, 1);
  72. scheduler_.MarkStreamReady(3, false); // priority 2
  73. scheduler_.MarkStreamReady(4, false); // priority 1
  74. EXPECT_EQ(4, scheduler_.PopNextReadyStream());
  75. EXPECT_EQ(3, scheduler_.PopNextReadyStream());
  76. // Verify that lowering priority of stream 4 causes it to be returned later
  77. // by PopNextReadyStream().
  78. scheduler_.MarkStreamReady(3, false); // priority 2
  79. scheduler_.MarkStreamReady(4, false); // priority 1
  80. scheduler_.UpdateStreamPriority(4, 3);
  81. EXPECT_EQ(3, scheduler_.PopNextReadyStream());
  82. EXPECT_EQ(4, scheduler_.PopNextReadyStream());
  83. scheduler_.UnregisterStream(3);
  84. EXPECT_DFATAL(scheduler_.UpdateStreamPriority(3, 1),
  85. "Stream 3 not registered");
  86. }
  87. TEST_F(PriorityWriteSchedulerTest, HasHigherPriorityReadyStream) {
  88. EXPECT_DFATAL(EXPECT_FALSE(scheduler_.HasHigherPriorityReadyStream(1)),
  89. "Stream 1 not registered");
  90. // Add ready streams of lower and equal priority.
  91. scheduler_.RegisterStream(1, 4);
  92. EXPECT_FALSE(scheduler_.HasHigherPriorityReadyStream(1));
  93. scheduler_.RegisterStream(2, 5);
  94. scheduler_.MarkStreamReady(2, false);
  95. EXPECT_FALSE(scheduler_.HasHigherPriorityReadyStream(1));
  96. scheduler_.RegisterStream(3, 4);
  97. scheduler_.MarkStreamReady(3, false);
  98. EXPECT_FALSE(scheduler_.HasHigherPriorityReadyStream(1));
  99. // Verify that registration of a stream with higher priority isn't
  100. // sufficient--it needs to be marked ready.
  101. scheduler_.RegisterStream(4, 3);
  102. EXPECT_FALSE(scheduler_.HasHigherPriorityReadyStream(1));
  103. scheduler_.MarkStreamReady(4, false);
  104. EXPECT_TRUE(scheduler_.HasHigherPriorityReadyStream(1));
  105. // Verify method is responsive to changes in priority.
  106. scheduler_.UpdateStreamPriority(1, 2);
  107. EXPECT_FALSE(scheduler_.HasHigherPriorityReadyStream(1));
  108. }
  109. TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyBack) {
  110. EXPECT_FALSE(scheduler_.HasReadyStreams());
  111. EXPECT_DFATAL(scheduler_.MarkStreamReady(1, false),
  112. "Stream 1 not registered");
  113. EXPECT_FALSE(scheduler_.HasReadyStreams());
  114. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  115. "No ready streams available");
  116. // Add a bunch of ready streams to tail of per-priority lists.
  117. // Expected order: (P2) 4, (P3) 1, 2, 3, (P5) 5.
  118. scheduler_.RegisterStream(1, 3);
  119. scheduler_.MarkStreamReady(1, false);
  120. EXPECT_TRUE(scheduler_.HasReadyStreams());
  121. scheduler_.RegisterStream(2, 3);
  122. scheduler_.MarkStreamReady(2, false);
  123. scheduler_.RegisterStream(3, 3);
  124. scheduler_.MarkStreamReady(3, false);
  125. scheduler_.RegisterStream(4, 2);
  126. scheduler_.MarkStreamReady(4, false);
  127. scheduler_.RegisterStream(5, 5);
  128. scheduler_.MarkStreamReady(5, false);
  129. EXPECT_EQ(4, scheduler_.PopNextReadyStream());
  130. EXPECT_EQ(1, scheduler_.PopNextReadyStream());
  131. EXPECT_EQ(2, scheduler_.PopNextReadyStream());
  132. EXPECT_EQ(3, scheduler_.PopNextReadyStream());
  133. EXPECT_EQ(5, scheduler_.PopNextReadyStream());
  134. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  135. "No ready streams available");
  136. }
  137. TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyFront) {
  138. EXPECT_FALSE(scheduler_.HasReadyStreams());
  139. EXPECT_DFATAL(scheduler_.MarkStreamReady(1, true), "Stream 1 not registered");
  140. EXPECT_FALSE(scheduler_.HasReadyStreams());
  141. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  142. "No ready streams available");
  143. // Add a bunch of ready streams to head of per-priority lists.
  144. // Expected order: (P2) 4, (P3) 3, 2, 1, (P5) 5
  145. scheduler_.RegisterStream(1, 3);
  146. scheduler_.MarkStreamReady(1, true);
  147. EXPECT_TRUE(scheduler_.HasReadyStreams());
  148. scheduler_.RegisterStream(2, 3);
  149. scheduler_.MarkStreamReady(2, true);
  150. scheduler_.RegisterStream(3, 3);
  151. scheduler_.MarkStreamReady(3, true);
  152. scheduler_.RegisterStream(4, 2);
  153. scheduler_.MarkStreamReady(4, true);
  154. scheduler_.RegisterStream(5, 5);
  155. scheduler_.MarkStreamReady(5, true);
  156. EXPECT_EQ(4, scheduler_.PopNextReadyStream());
  157. EXPECT_EQ(3, scheduler_.PopNextReadyStream());
  158. EXPECT_EQ(2, scheduler_.PopNextReadyStream());
  159. EXPECT_EQ(1, scheduler_.PopNextReadyStream());
  160. EXPECT_EQ(5, scheduler_.PopNextReadyStream());
  161. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  162. "No ready streams available");
  163. }
  164. TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyBackAndFront) {
  165. scheduler_.RegisterStream(1, 4);
  166. scheduler_.RegisterStream(2, 3);
  167. scheduler_.RegisterStream(3, 3);
  168. scheduler_.RegisterStream(4, 3);
  169. scheduler_.RegisterStream(5, 4);
  170. scheduler_.RegisterStream(6, 1);
  171. // Add a bunch of ready streams to per-priority lists, with variety of adding
  172. // at head and tail.
  173. // Expected order: (P1) 6, (P3) 4, 2, 3, (P4) 1, 5
  174. scheduler_.MarkStreamReady(1, true);
  175. scheduler_.MarkStreamReady(2, true);
  176. scheduler_.MarkStreamReady(3, false);
  177. scheduler_.MarkStreamReady(4, true);
  178. scheduler_.MarkStreamReady(5, false);
  179. scheduler_.MarkStreamReady(6, true);
  180. EXPECT_EQ(6, scheduler_.PopNextReadyStream());
  181. EXPECT_EQ(4, scheduler_.PopNextReadyStream());
  182. EXPECT_EQ(2, scheduler_.PopNextReadyStream());
  183. EXPECT_EQ(3, scheduler_.PopNextReadyStream());
  184. EXPECT_EQ(1, scheduler_.PopNextReadyStream());
  185. EXPECT_EQ(5, scheduler_.PopNextReadyStream());
  186. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  187. "No ready streams available");
  188. }
  189. TEST_F(PriorityWriteSchedulerTest, MarkStreamNotReady) {
  190. // Verify ready state reflected in NumReadyStreams().
  191. scheduler_.RegisterStream(1, 1);
  192. EXPECT_EQ(0u, scheduler_.NumReadyStreams());
  193. scheduler_.MarkStreamReady(1, false);
  194. EXPECT_EQ(1u, scheduler_.NumReadyStreams());
  195. scheduler_.MarkStreamNotReady(1);
  196. EXPECT_EQ(0u, scheduler_.NumReadyStreams());
  197. // Empty pop should fail.
  198. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  199. "No ready streams available");
  200. // Tolerate redundant marking of a stream as not ready.
  201. scheduler_.MarkStreamNotReady(1);
  202. EXPECT_EQ(0u, scheduler_.NumReadyStreams());
  203. // Should only be able to mark registered streams.
  204. EXPECT_DFATAL(scheduler_.MarkStreamNotReady(3), "Stream 3 not registered");
  205. }
  206. TEST_F(PriorityWriteSchedulerTest, UnregisterRemovesStream) {
  207. scheduler_.RegisterStream(3, 4);
  208. scheduler_.MarkStreamReady(3, false);
  209. EXPECT_EQ(1u, scheduler_.NumReadyStreams());
  210. // Unregistering a stream should remove it from set of ready streams.
  211. scheduler_.UnregisterStream(3);
  212. EXPECT_EQ(0u, scheduler_.NumReadyStreams());
  213. EXPECT_DFATAL(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
  214. "No ready streams available");
  215. }
  216. TEST_F(PriorityWriteSchedulerTest, ShouldYield) {
  217. scheduler_.RegisterStream(1, 1);
  218. scheduler_.RegisterStream(4, 4);
  219. scheduler_.RegisterStream(5, 4);
  220. scheduler_.RegisterStream(7, 7);
  221. // Make sure we don't yield when the list is empty.
  222. EXPECT_FALSE(scheduler_.ShouldYield(1));
  223. // Add a low priority stream.
  224. scheduler_.MarkStreamReady(4, false);
  225. // 4 should not yield to itself.
  226. EXPECT_FALSE(scheduler_.ShouldYield(4));
  227. // 7 should yield as 4 is blocked and a higher priority.
  228. EXPECT_TRUE(scheduler_.ShouldYield(7));
  229. // 5 should yield to 4 as they are the same priority.
  230. EXPECT_TRUE(scheduler_.ShouldYield(5));
  231. // 1 should not yield as 1 is higher priority.
  232. EXPECT_FALSE(scheduler_.ShouldYield(1));
  233. // Add a second stream in that priority class.
  234. scheduler_.MarkStreamReady(5, false);
  235. // 4 and 5 are both blocked, but 4 is at the front so should not yield.
  236. EXPECT_FALSE(scheduler_.ShouldYield(4));
  237. EXPECT_TRUE(scheduler_.ShouldYield(5));
  238. }
  239. } // namespace
  240. } // namespace test
  241. } // namespace net