Add reprioritization to socket pools.

BUG=600839
BUG=166689

Review-Url: https://codereview.chromium.org/1898133002
Cr-Commit-Position: refs/heads/master@{#451185}
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 7b9bffa3..b201809 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -532,6 +532,12 @@
     base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
   }
 
+  void SetPriority(const std::string& group_name,
+                   ClientSocketHandle* handle,
+                   RequestPriority priority) override {
+    base_.SetPriority(group_name, handle, priority);
+  }
+
   void CancelRequest(const std::string& group_name,
                      ClientSocketHandle* handle) override {
     base_.CancelRequest(group_name, handle);
@@ -734,6 +740,8 @@
   std::vector<std::unique_ptr<TestSocketRequest>>* requests() {
     return test_base_.requests();
   }
+  // Only counts the requests that get sockets asynchronously;
+  // synchronous completions are not registered by this count.
   size_t completion_count() const { return test_base_.completion_count(); }
 
   TestNetLog net_log_;
@@ -988,6 +996,107 @@
   EXPECT_EQ(ClientSocketPoolTest::kIndexOutOfBounds, GetOrderOfRequest(9));
 }
 
+// Test reprioritizing a request before completion doesn't interfere with
+// its completion.
+TEST_F(ClientSocketPoolBaseTest, ReprioritizeOne) {
+  CreatePool(kDefaultMaxSockets, 1);
+
+  EXPECT_THAT(StartRequest("a", LOWEST), IsError(OK));
+  EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
+  EXPECT_TRUE(request(0)->handle()->socket());
+  EXPECT_FALSE(request(1)->handle()->socket());
+
+  request(1)->handle()->SetPriority(MEDIUM);
+
+  ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE);
+
+  EXPECT_TRUE(request(1)->handle()->socket());
+}
+
+// Reprioritize a request up past another one and make sure that changes the
+// completion order.
+TEST_F(ClientSocketPoolBaseTest, ReprioritizeUpReorder) {
+  CreatePool(kDefaultMaxSockets, 1);
+
+  EXPECT_THAT(StartRequest("a", LOWEST), IsError(OK));
+  EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
+  EXPECT_THAT(StartRequest("a", LOWEST), IsError(ERR_IO_PENDING));
+  EXPECT_TRUE(request(0)->handle()->socket());
+  EXPECT_FALSE(request(1)->handle()->socket());
+  EXPECT_FALSE(request(2)->handle()->socket());
+
+  request(2)->handle()->SetPriority(HIGHEST);
+
+  ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+
+  EXPECT_EQ(1, GetOrderOfRequest(1));
+  EXPECT_EQ(3, GetOrderOfRequest(2));
+  EXPECT_EQ(2, GetOrderOfRequest(3));
+}
+
+// Reprioritize a request without changing relative priorities and check
+// that the order doesn't change.
+TEST_F(ClientSocketPoolBaseTest, ReprioritizeUpNoReorder) {
+  CreatePool(kDefaultMaxSockets, 1);
+
+  EXPECT_THAT(StartRequest("a", LOWEST), IsError(OK));
+  EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
+  EXPECT_THAT(StartRequest("a", LOW), IsError(ERR_IO_PENDING));
+  EXPECT_TRUE(request(0)->handle()->socket());
+  EXPECT_FALSE(request(1)->handle()->socket());
+  EXPECT_FALSE(request(2)->handle()->socket());
+
+  request(2)->handle()->SetPriority(MEDIUM);
+
+  ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+
+  EXPECT_EQ(1, GetOrderOfRequest(1));
+  EXPECT_EQ(2, GetOrderOfRequest(2));
+  EXPECT_EQ(3, GetOrderOfRequest(3));
+}
+
+// Reprioritize a request past down another one and make sure that changes the
+// completion order.
+TEST_F(ClientSocketPoolBaseTest, ReprioritizeDownReorder) {
+  CreatePool(kDefaultMaxSockets, 1);
+
+  EXPECT_THAT(StartRequest("a", LOWEST), IsError(OK));
+  EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
+  EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
+  EXPECT_TRUE(request(0)->handle()->socket());
+  EXPECT_FALSE(request(1)->handle()->socket());
+  EXPECT_FALSE(request(2)->handle()->socket());
+
+  request(1)->handle()->SetPriority(LOW);
+
+  ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+
+  EXPECT_EQ(1, GetOrderOfRequest(1));
+  EXPECT_EQ(3, GetOrderOfRequest(2));
+  EXPECT_EQ(2, GetOrderOfRequest(3));
+}
+
+// Reprioritize a request to the same level as another and confirm it is
+// put after the old request.
+TEST_F(ClientSocketPoolBaseTest, ReprioritizeResetFIFO) {
+  CreatePool(kDefaultMaxSockets, 1);
+
+  EXPECT_THAT(StartRequest("a", LOWEST), IsError(OK));
+  EXPECT_THAT(StartRequest("a", HIGHEST), IsError(ERR_IO_PENDING));
+  EXPECT_THAT(StartRequest("a", MEDIUM), IsError(ERR_IO_PENDING));
+  EXPECT_TRUE(request(0)->handle()->socket());
+  EXPECT_FALSE(request(1)->handle()->socket());
+  EXPECT_FALSE(request(2)->handle()->socket());
+
+  request(1)->handle()->SetPriority(MEDIUM);
+
+  ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+
+  EXPECT_EQ(1, GetOrderOfRequest(1));
+  EXPECT_EQ(3, GetOrderOfRequest(2));
+  EXPECT_EQ(2, GetOrderOfRequest(3));
+}
+
 TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
   base::HistogramTester histograms;
   CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);