brpc_socket_map_unittest.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. // brpc - A framework to host and access services throughout Baidu.
  18. // Date: Sun Jul 13 15:04:18 CST 2014
  19. #include <gtest/gtest.h>
  20. #include <gflags/gflags.h>
  21. #include "brpc/socket.h"
  22. #include "brpc/socket_map.h"
  23. #include "brpc/reloadable_flags.h"
  24. namespace brpc {
  25. DECLARE_int32(idle_timeout_second);
  26. DECLARE_int32(defer_close_second);
  27. DECLARE_int32(max_connection_pool_size);
  28. } // namespace brpc
  29. namespace {
  30. butil::EndPoint g_endpoint;
  31. brpc::SocketMapKey g_key(g_endpoint);
  32. void* worker(void*) {
  33. const int ROUND = 2;
  34. const int COUNT = 1000;
  35. brpc::SocketId id;
  36. for (int i = 0; i < ROUND * 2; ++i) {
  37. for (int j = 0; j < COUNT; ++j) {
  38. if (i % 2 == 0) {
  39. EXPECT_EQ(0, brpc::SocketMapInsert(g_key, &id));
  40. } else {
  41. brpc::SocketMapRemove(g_key);
  42. }
  43. }
  44. }
  45. return NULL;
  46. }
  47. class SocketMapTest : public ::testing::Test{
  48. protected:
  49. SocketMapTest(){};
  50. virtual ~SocketMapTest(){};
  51. virtual void SetUp(){};
  52. virtual void TearDown(){};
  53. };
  54. TEST_F(SocketMapTest, idle_timeout) {
  55. const int TIMEOUT = 1;
  56. const int NTHREAD = 10;
  57. brpc::FLAGS_defer_close_second = TIMEOUT;
  58. pthread_t tids[NTHREAD];
  59. for (int i = 0; i < NTHREAD; ++i) {
  60. ASSERT_EQ(0, pthread_create(&tids[i], NULL, worker, NULL));
  61. }
  62. for (int i = 0; i < NTHREAD; ++i) {
  63. ASSERT_EQ(0, pthread_join(tids[i], NULL));
  64. }
  65. brpc::SocketId id;
  66. // Socket still exists since it has not reached timeout yet
  67. ASSERT_EQ(0, brpc::SocketMapFind(g_key, &id));
  68. usleep(TIMEOUT * 1000000L + 1100000L);
  69. // Socket should be removed after timeout
  70. ASSERT_EQ(-1, brpc::SocketMapFind(g_key, &id));
  71. brpc::FLAGS_defer_close_second = TIMEOUT * 10;
  72. ASSERT_EQ(0, brpc::SocketMapInsert(g_key, &id));
  73. brpc::SocketMapRemove(g_key);
  74. ASSERT_EQ(0, brpc::SocketMapFind(g_key, &id));
  75. // Change `FLAGS_idle_timeout_second' to 0 to disable checking
  76. brpc::FLAGS_defer_close_second = 0;
  77. usleep(1100000L);
  78. // And then Socket should be removed
  79. ASSERT_EQ(-1, brpc::SocketMapFind(g_key, &id));
  80. brpc::SocketId main_id;
  81. ASSERT_EQ(0, brpc::SocketMapInsert(g_key, &main_id));
  82. brpc::FLAGS_idle_timeout_second = TIMEOUT;
  83. brpc::SocketUniquePtr main_ptr;
  84. brpc::SocketUniquePtr ptr;
  85. ASSERT_EQ(0, brpc::Socket::Address(main_id, &main_ptr));
  86. ASSERT_EQ(0, main_ptr->GetPooledSocket(&ptr));
  87. ASSERT_TRUE(main_ptr.get());
  88. main_ptr.reset();
  89. id = ptr->id();
  90. ptr->ReturnToPool();
  91. ptr.reset(NULL);
  92. usleep(TIMEOUT * 1000000L + 2000000L);
  93. // Pooled connection should be `ReleaseAdditionalReference',
  94. // which destroyed the Socket. As a result `GetSocketFromPool'
  95. // should return a new one
  96. ASSERT_EQ(0, brpc::Socket::Address(main_id, &main_ptr));
  97. ASSERT_EQ(0, main_ptr->GetPooledSocket(&ptr));
  98. ASSERT_TRUE(main_ptr.get());
  99. main_ptr.reset();
  100. ASSERT_NE(id, ptr->id());
  101. brpc::SocketMapRemove(g_key);
  102. }
  103. TEST_F(SocketMapTest, max_pool_size) {
  104. const int MAXSIZE = 5;
  105. const int TOTALSIZE = MAXSIZE + 5;
  106. brpc::FLAGS_max_connection_pool_size = MAXSIZE;
  107. brpc::SocketId main_id;
  108. ASSERT_EQ(0, brpc::SocketMapInsert(g_key, &main_id));
  109. brpc::SocketUniquePtr ptrs[TOTALSIZE];
  110. for (int i = 0; i < TOTALSIZE; ++i) {
  111. brpc::SocketUniquePtr main_ptr;
  112. ASSERT_EQ(0, brpc::Socket::Address(main_id, &main_ptr));
  113. ASSERT_EQ(0, main_ptr->GetPooledSocket(&ptrs[i]));
  114. ASSERT_TRUE(main_ptr.get());
  115. main_ptr.reset();
  116. }
  117. for (int i = 0; i < TOTALSIZE; ++i) {
  118. ASSERT_EQ(0, ptrs[i]->ReturnToPool());
  119. }
  120. std::vector<brpc::SocketId> ids;
  121. brpc::SocketUniquePtr main_ptr;
  122. ASSERT_EQ(0, brpc::Socket::Address(main_id, &main_ptr));
  123. main_ptr->ListPooledSockets(&ids);
  124. EXPECT_EQ(MAXSIZE, (int)ids.size());
  125. // The last few Sockets should be `SetFailed' by `ReturnSocketToPool'
  126. for (int i = MAXSIZE; i < TOTALSIZE; ++i) {
  127. EXPECT_TRUE(ptrs[i]->Failed());
  128. }
  129. }
  130. } //namespace
  131. int main(int argc, char* argv[]) {
  132. butil::str2endpoint("127.0.0.1:12345", &g_key.peer.addr);
  133. testing::InitGoogleTest(&argc, argv);
  134. return RUN_ALL_TESTS();
  135. }