Update free port logic.
authorBrian Aker <brian@tangent.org>
Sun, 19 Feb 2012 21:13:07 +0000 (13:13 -0800)
committerBrian Aker <brian@tangent.org>
Sun, 19 Feb 2012 21:13:07 +0000 (13:13 -0800)
libtest/port.cc
libtest/port.h
libtest/server_container.cc
libtest/unittest.cc
tests/failure.cc
tests/memstat.cc

index c1f2f94551cad8bdb24fc2a742c331141dc03053..152d8360be12d51e4d09409c0be7c97520cb921a 100644 (file)
 
 using namespace libtest;
 
+struct socket_st {
+  std::vector<int> fd;
+
+  ~socket_st()
+  {
+    for(std::vector<int>::iterator iter= fd.begin(); iter != fd.end(); iter++)
+    {
+      close(*iter);
+    }
+  }
+};
+
+static socket_st all_socket_fd;
+
 static in_port_t global_port= 0;
-static in_port_t global_max_port= 0;
 
 namespace libtest {
 
 in_port_t default_port()
 {
-  return global_port;
-}
-void set_default_port(in_port_t port)
-{
-  global_port= port;
-}
-
-in_port_t max_port()
-{
-  return global_max_port;
-}
-void set_max_port(in_port_t port)
-{
-  if (port > global_max_port)
+  if (global_port == 0)
   {
-    global_max_port= port;
+    global_port= get_free_port();
   }
 
-  global_max_port= port;
+  return global_port;
 }
 
 in_port_t get_free_port()
 {
   in_port_t ret_port= in_port_t(0);
-  int sd;
-  if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1)
+
+  int retries= 1024;
+
+  while (retries--)
   {
-    int optval= 1;
-    if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1)
+    int sd;
+    if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1)
     {
-      struct sockaddr_in sin;
-      sin.sin_port= 0;
-      sin.sin_addr.s_addr= 0;
-      sin.sin_addr.s_addr= INADDR_ANY;
-      sin.sin_family= AF_INET;
-
-      if (bind(sd, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) != -1)
+      int optval= 1;
+      if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1)
       {
-        socklen_t addrlen= sizeof(sin);
+        struct sockaddr_in sin;
+        sin.sin_port= 0;
+        sin.sin_addr.s_addr= 0;
+        sin.sin_addr.s_addr= INADDR_ANY;
+        sin.sin_family= AF_INET;
 
-        if (listen(sd, 100) != -1)
+        if (bind(sd, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) != -1)
         {
+          socklen_t addrlen= sizeof(sin);
+
           if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1)
           {
             ret_port= sin.sin_port;
+            Error << ret_port;
           }
         }
       }
+
+      all_socket_fd.fd.push_back(sd);
+    }
+
+    if (ret_port > 1024)
+    {
+      break;
     }
+  }
 
-    close(sd);
+  // We handle the case where if we max out retries, we still abort.
+  if (ret_port <= 1024)
+  {
+    abort();
   }
 
   return ret_port;
index d6fbcb25384151afc8034acd63902f302c10ae0f..a7accaec89d0884643cdf8f0c0380d510572a9b4 100644 (file)
@@ -31,15 +31,6 @@ namespace libtest {
 LIBTEST_API
 in_port_t default_port();
 
-LIBTEST_API
-void set_default_port(in_port_t port);
-
-LIBTEST_API
-in_port_t max_port();
-
-LIBTEST_API
-void set_max_port(in_port_t port);
-
 LIBTEST_API
 in_port_t get_free_port();
 
index 2c31796f3e141c64530df63aabf99b253725e862..528fcd1fab180e288f45f9e356051e428f85f1c0 100644 (file)
@@ -146,23 +146,6 @@ bool server_startup(server_startup_st& construct, const std::string& server_type
   Outn();
   (void)try_port;
 
-  set_max_port(try_port);
-
-  // Look to see if we are being provided ports to use
-  {
-    char variable_buffer[1024];
-    snprintf(variable_buffer, sizeof(variable_buffer), "LIBTEST_PORT_%lu", (unsigned long)construct.count());
-
-    char *var;
-    if ((var= getenv(variable_buffer)))
-    {
-      in_port_t tmp= in_port_t(atoi(var));
-
-      if (tmp > 0)
-        try_port= tmp;
-    }
-  }
-
   libtest::Server *server= NULL;
   if (0)
   { }
@@ -249,12 +232,6 @@ bool server_startup(server_startup_st& construct, const std::string& server_type
 
   construct.push_server(server);
 
-  if (default_port() == 0)
-  {
-    assert(server->has_port());
-    set_default_port(server->port());
-  }
-
   Outn();
 
   return true;
index 21dcbc74416bbc3d044ca8e7ef486bbc3be2e907..77326d1c3cca47ee0609ae8caf83061bcd95b55c 100644 (file)
@@ -510,6 +510,18 @@ static test_return_t get_free_port_TEST(void *)
 {
   in_port_t ret_port;
   test_true_hint((ret_port= get_free_port()), ret_port);
+  test_true(get_free_port() != default_port());
+  test_true(get_free_port() != get_free_port());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t default_port_TEST(void *)
+{
+  in_port_t ret_port= default_port();
+  test_compare(ret_port, libtest::default_port());
+  test_compare(ret_port, libtest::default_port());
+
   return TEST_SUCCESS;
 }
 
@@ -599,6 +611,7 @@ test_st cmdline_tests[] ={
 
 test_st get_free_port_TESTS[] ={
   {"get_free_port()", 0, get_free_port_TEST },
+  {"default_port()", 0, default_port_TEST },
   {0, 0, 0}
 };
 
index 1348e50cd05a8c4365c8ff31c85589d0bcd47a84..20c355d39dd16b72982d4575009a7882a42fbe69 100644 (file)
@@ -76,7 +76,7 @@ static test_return_t add_shutdown_servers(memcached_st *memc)
   while (memcached_server_count(memc) < 2)
   {
     const char *argv[1]= { "add_shutdown_server" };
-    in_port_t port= max_port() +1;
+    in_port_t port= libtest::get_free_port();
     test_true(global_framework->servers().start_socket_server("memcached", port, 1, argv));
     test_compare(MEMCACHED_SUCCESS, memcached_server_add(memc, "localhost", port));
   }
index c99836ac2146299f7213310ae0e2fe6c4b879359..2ffb26bded821fbb126baa4f0bdbf0cba5ed01ca 100644 (file)
@@ -73,7 +73,7 @@ static test_return_t help_test(void *)
 static test_return_t binary_TEST(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
+  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(libtest::default_port()));
   const char *args[]= { "--quiet", buffer, " --binary ", 0 };
 
   test_true(exec_cmdline(executable, args));
@@ -83,7 +83,7 @@ static test_return_t binary_TEST(void *)
 static test_return_t server_version_TEST(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
+  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(libtest::default_port()));
   const char *args[]= { "--quiet", buffer, " --server-version", 0 };
 
   test_true(exec_cmdline(executable, args));
@@ -93,7 +93,7 @@ static test_return_t server_version_TEST(void *)
 static test_return_t binary_server_version_TEST(void *)
 {
   char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(default_port()));
+  snprintf(buffer, sizeof(buffer), "--servers=localhost:%d", int(libtest::default_port()));
   const char *args[]= { "--quiet", buffer, " --binary --server-version", 0 };
 
   test_true(exec_cmdline(executable, args));
@@ -123,7 +123,7 @@ static void *world_create(server_startup_st& servers, test_return_t& error)
   }
 
   const char *argv[1]= { "memstat" };
-  if (not server_startup(servers, "memcached", libtest::get_free_port(), 1, argv))
+  if (server_startup(servers, "memcached", libtest::default_port(), 1, argv) == false)
   {
     error= TEST_FAILURE;
   }