(root)/
glib-2.79.0/
glib/
tests/
gpoll.c
       1  /* Unit test for W32 version of g_poll()
       2   *
       3   * Copyright © 2017 Руслан Ижбулатов <lrn1986@gmail.com>
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General Public License
      18   * along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   */
      20  
      21  #include <glib.h>
      22  #include <winsock2.h>
      23  
      24  #define NUM_POLLEES 999
      25  #define NUM_POLLFDS 1000
      26  
      27  #define ASYNC_CONNECT_OK(r) (r == 0 || (r < 0 && GetLastError () == WSAEWOULDBLOCK))
      28  
      29  #define REPEAT 1
      30  
      31  static void
      32  init_networking (void)
      33  {
      34    WSADATA wsadata;
      35  
      36    if (WSAStartup (MAKEWORD (2, 0), &wsadata) != 0)
      37      g_error ("Windows Sockets could not be initialized");
      38  }
      39  
      40  static void
      41  prepare_fds (SOCKET  sockets[],
      42               GPollFD fds[],
      43               int     num_pollees)
      44  {
      45    gint i;
      46  
      47    for (i = 0; i < num_pollees; i++)
      48      {
      49        fds[i].fd = (gintptr) WSACreateEvent ();
      50        g_assert (WSAEventSelect (sockets[i], (HANDLE) fds[i].fd, FD_READ | FD_CLOSE) == 0);
      51      }
      52  }
      53  
      54  static void
      55  reset_fds (GPollFD fds[],
      56             int     num_pollees)
      57  {
      58    gint i;
      59  
      60    for (i = 0; i < num_pollees; i++)
      61      {
      62        WSAResetEvent ((HANDLE) fds[i].fd);
      63        fds[i].events =  G_IO_IN | G_IO_OUT | G_IO_ERR;
      64        fds[i].revents = 0;
      65      }
      66  }
      67  
      68  static void
      69  reset_fds_msg (GPollFD fds[],
      70                 int     num_pollfds)
      71  {
      72    fds[num_pollfds - 1].fd = G_WIN32_MSG_HANDLE;
      73    fds[num_pollfds - 1].events = G_IO_IN;
      74    fds[num_pollfds - 1].revents = 0;
      75  }
      76  
      77  static void
      78  check_fds (SOCKET  sockets[],
      79             GPollFD fds[],
      80             int     num_pollees)
      81  {
      82    gint i;
      83  
      84    for (i = 0; i < num_pollees; i++)
      85      {
      86        if (fds[i].revents != 0)
      87          {
      88            WSANETWORKEVENTS events;
      89            g_assert (WSAEnumNetworkEvents (sockets[i], 0, &events) == 0);
      90  
      91            fds[i].revents = 0;
      92            if (events.lNetworkEvents & (FD_READ | FD_ACCEPT))
      93              fds[i].revents |= G_IO_IN;
      94  
      95            if (events.lNetworkEvents & FD_WRITE)
      96              fds[i].revents |= G_IO_OUT;
      97            else
      98              {
      99                /* We have called WSAEnumNetworkEvents() above but it didn't
     100                 * set FD_WRITE.
     101                 */
     102                if (events.lNetworkEvents & FD_CONNECT)
     103                  {
     104                    if (events.iErrorCode[FD_CONNECT_BIT] == 0)
     105                      fds[i].revents |= G_IO_OUT;
     106                    else
     107                      fds[i].revents |= (G_IO_HUP | G_IO_ERR);
     108                  }
     109                if (fds[i].revents == 0 && (events.lNetworkEvents & (FD_CLOSE)))
     110                  fds[i].revents |= G_IO_HUP;
     111              }
     112          }
     113      }
     114  }
     115  
     116  static void
     117  prepare_sockets (SOCKET  sockets[],
     118                   SOCKET  opp_sockets[],
     119                   GPollFD fds[],
     120                   int     num_pollees)
     121  {
     122    gint i;
     123    SOCKET server;
     124    struct sockaddr_in sa;
     125    unsigned long ul = 1;
     126    int sa_size;
     127    int r;
     128  
     129    server = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
     130    g_assert (server != INVALID_SOCKET);
     131  
     132    memset(&sa, 0, sizeof sa);
     133  
     134    sa.sin_family = AF_INET;
     135    sa.sin_port = 0;
     136    sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
     137    sa_size = sizeof (sa);
     138  
     139    g_assert (bind (server, (const struct sockaddr *) &sa, sa_size) == 0);
     140    g_assert (getsockname (server, (struct sockaddr *) &sa, &sa_size) == 0);
     141    g_assert (listen (server, 1) == 0);
     142  
     143    for (i = 0; i < num_pollees; i++)
     144      {
     145        opp_sockets[i] = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
     146        g_assert (opp_sockets[i] != INVALID_SOCKET);
     147        g_assert (ioctlsocket (opp_sockets[i], FIONBIO, &ul) == 0);
     148  
     149        r = connect (opp_sockets[i], (const struct sockaddr *) &sa, sizeof (sa));
     150        g_assert (ASYNC_CONNECT_OK (r));
     151  
     152        sockets[i] = accept (server, NULL, NULL);
     153        g_assert (sockets[i] != INVALID_SOCKET);
     154        g_assert (ioctlsocket (sockets[i], FIONBIO, &ul) == 0);
     155      }
     156  
     157    closesocket (server);
     158  }
     159  
     160  static void
     161  cleanup_sockets (SOCKET sockets[],
     162                   SOCKET opp_sockets[],
     163                   int    num_pollees)
     164  {
     165    gint i;
     166  
     167    for (i = 0; i < num_pollees; i++)
     168      {
     169        closesocket (sockets[i]);
     170        closesocket (opp_sockets[i]);
     171      }
     172  }
     173  
     174  static void
     175  bucketize (gint64 val,
     176             gint   buckets[],
     177             gint64 bucket_limits[],
     178             gint   count)
     179  {
     180    gint i;
     181  
     182    if (val > bucket_limits[count - 1])
     183      {
     184        buckets[count - 1] += 1;
     185        return;
     186      }
     187  
     188    for (i = count - 1; i > 0; i--)
     189      if (val < bucket_limits[i] && val >= bucket_limits[i - 1])
     190        {
     191          buckets[i] += 1;
     192          return;
     193        }
     194  
     195    buckets[0] += 1;
     196  }
     197  
     198  static void
     199  print_buckets (gint   buckets[],
     200                 gint64 bucket_limits[],
     201                 gint   count)
     202  {
     203    gint i;
     204  
     205    for (i = 0; i < count; i++)
     206      if (i < count - 1)
     207        g_printerr ("%-4lld-%4lld|", i == 0 ? 0 : bucket_limits[i - 1], bucket_limits[i] - 1);
     208      else
     209        g_printerr ("  >= %-4lld|", bucket_limits[i - 1]);
     210  
     211    g_printerr ("\n");
     212  
     213    for (i = 0; i < count; i++)
     214      {
     215        gint len;
     216        gint padding;
     217        gint j;
     218        if (buckets[i] < 10)
     219          len = 1;
     220        else if (buckets[i] < 100)
     221          len = 2;
     222        else if (buckets[i] < 1000)
     223          len = 3;
     224        else
     225          len = 4;
     226        padding = 9 - len;
     227        for (j = 0; j < padding / 2; j++)
     228          g_printerr (" ");
     229        if (buckets[i] != 0)
     230          g_printerr ("%*d", len, buckets[i]);
     231        else
     232          g_printerr (" ");
     233        for (j = padding / 2; j < padding; j++)
     234          g_printerr (" ");
     235        g_printerr (" ");
     236      }
     237  
     238    g_printerr ("\n\n");
     239  }
     240  
     241  static void
     242  test_gpoll (void)
     243  {
     244    SOCKET sockets[NUM_POLLEES];
     245    GPollFD fds[NUM_POLLFDS];
     246    SOCKET opp_sockets[NUM_POLLEES];
     247    gint i;
     248    gint activatable;
     249    gint64 times[REPEAT][2];
     250  #define BUCKET_COUNT 25
     251    gint64 bucket_limits[BUCKET_COUNT] = {3, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 100, 120, 150, 180, 220, 280, 350, 450, 600, 800, 1000};
     252    gint   buckets[BUCKET_COUNT];
     253    gint64 times_avg = 0, times_min = G_MAXINT64, times_max = 0;
     254  
     255    prepare_sockets (sockets, opp_sockets, fds, NUM_POLLEES);
     256    prepare_fds (sockets, fds, NUM_POLLEES);
     257  
     258    times_avg = 0;
     259    times_min = G_MAXINT64;
     260    times_max = 0;
     261    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     262  
     263    for (i = 0; i < REPEAT; i++)
     264      {
     265        gint r;
     266        gint64 diff;
     267  
     268        reset_fds (fds, NUM_POLLEES);
     269        reset_fds_msg (fds, NUM_POLLFDS);
     270        times[i][0] = g_get_monotonic_time ();
     271        r = g_poll (fds, NUM_POLLFDS, 0);
     272        times[i][1] = g_get_monotonic_time ();
     273        g_assert (r == 0);
     274        diff = times[i][1] - times[i][0];
     275        if (times_min > diff)
     276          times_min = diff;
     277        if (times_max < diff)
     278          times_max = diff;
     279        times_avg += diff;
     280        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     281      }
     282  
     283    times_avg /= NUM_POLLEES;
     284    g_printerr ("\nempty poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg);
     285    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     286  
     287    times_avg = 0;
     288    times_min = G_MAXINT64;
     289    times_max = 0;
     290    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     291  
     292    activatable = 0;
     293  
     294    for (i = 0; i < REPEAT; i++)
     295      {
     296        gint r, s, v, t;
     297        gint64 diff;
     298        MSG msg;
     299        gboolean found_app;
     300  
     301        reset_fds (fds, NUM_POLLEES);
     302        reset_fds_msg (fds, NUM_POLLFDS);
     303        s = send (opp_sockets[activatable], (const char *) &t, 1, 0);
     304        g_assert (PostMessage (NULL, WM_APP, 1, 2));
     305        /* This is to ensure that all sockets catch up, otherwise some might not poll active */
     306        g_usleep (G_USEC_PER_SEC / 1000);
     307  
     308        times[i][0] = g_get_monotonic_time ();
     309        r = g_poll (fds, NUM_POLLFDS, 1000);
     310        times[i][1] = g_get_monotonic_time ();
     311  
     312        check_fds (sockets, fds, NUM_POLLEES);
     313        v = recv (sockets[activatable], (char *) &t, 1, 0);
     314        found_app = FALSE;
     315        while (!found_app && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     316          if (msg.message == WM_APP && msg.wParam == 1 && msg.lParam == 2)
     317            found_app = TRUE;
     318        g_assert (s == 1);
     319        g_assert (r == 2);
     320        g_assert (v == 1);
     321        g_assert (found_app);
     322  
     323        reset_fds (fds, NUM_POLLEES);
     324        reset_fds_msg (fds, NUM_POLLFDS);
     325        r = g_poll (fds, NUM_POLLFDS, 0);
     326        check_fds (sockets, fds, NUM_POLLEES);
     327        g_assert (r == 0);
     328        diff = times[i][1] - times[i][0];
     329        if (times_min > diff)
     330          times_min = diff;
     331        if (times_max < diff)
     332          times_max = diff;
     333        times_avg += diff;
     334        activatable = (activatable + 1) % NUM_POLLEES;
     335        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     336      }
     337  
     338    times_avg /= NUM_POLLEES;
     339    g_printerr ("1-socket + msg poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg);
     340    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     341  
     342    times_avg = 0;
     343    times_min = G_MAXINT64;
     344    times_max = 0;
     345    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     346  
     347    activatable = 0;
     348  
     349    for (i = 0; i < REPEAT; i++)
     350      {
     351        gint r, s, v, t;
     352        gint64 diff;
     353  
     354        reset_fds (fds, NUM_POLLEES);
     355        reset_fds_msg (fds, NUM_POLLFDS);
     356        s = send (opp_sockets[activatable], (const char *) &t, 1, 0);
     357  
     358        g_usleep (G_USEC_PER_SEC / 1000);
     359  
     360        times[i][0] = g_get_monotonic_time ();
     361        r = g_poll (fds, NUM_POLLFDS, 1000);
     362        times[i][1] = g_get_monotonic_time ();
     363  
     364        check_fds (sockets, fds, NUM_POLLEES);
     365        v = recv (sockets[activatable], (char *) &t, 1, 0);
     366        g_assert (s == 1);
     367        g_assert (r == 1);
     368        g_assert (v == 1);
     369  
     370        reset_fds (fds, NUM_POLLEES);
     371        reset_fds_msg (fds, NUM_POLLFDS);
     372        r = g_poll (fds, NUM_POLLFDS, 0);
     373        check_fds (sockets, fds, NUM_POLLEES);
     374        g_assert (r == 0);
     375  
     376        diff = times[i][1] - times[i][0];
     377        if (times_min > diff)
     378          times_min = diff;
     379        if (times_max < diff)
     380          times_max = diff;
     381        times_avg += diff;
     382        activatable = (activatable + 1) % NUM_POLLEES;
     383        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     384      }
     385  
     386    times_avg /= NUM_POLLEES;
     387    g_printerr ("1-socket poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg);
     388    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     389  
     390    times_avg = 0;
     391    times_min = G_MAXINT64;
     392    times_max = 0;
     393    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     394  
     395    for (i = 0; i < REPEAT; i++)
     396      {
     397        gint r, s, v, t;
     398        gint64 diff;
     399        gint j;
     400  
     401        reset_fds (fds, NUM_POLLEES);
     402        reset_fds_msg (fds, NUM_POLLFDS);
     403        s = v = 0;
     404  
     405        for (j = 0; j < NUM_POLLEES / 2; j++)
     406          s += send (opp_sockets[j], (const char *) &t, 1, 0) == 1 ? 1 : 0;
     407  
     408        g_usleep (G_USEC_PER_SEC / 1000);
     409  
     410        times[i][0] = g_get_monotonic_time ();
     411        r = g_poll (fds, NUM_POLLFDS, 1000);
     412        times[i][1] = g_get_monotonic_time ();
     413        check_fds (sockets, fds, NUM_POLLEES);
     414        for (j = 0; j < NUM_POLLEES / 2; j++)
     415          v += recv (sockets[j], (char *) &t, 1, 0) == 1 ? 1 : 0;
     416        g_assert (s == NUM_POLLEES / 2);
     417        g_assert (r == NUM_POLLEES / 2);
     418        g_assert (v == NUM_POLLEES / 2);
     419  
     420        reset_fds (fds, NUM_POLLEES);
     421        reset_fds_msg (fds, NUM_POLLFDS);
     422        r = g_poll (fds, NUM_POLLFDS, 0);
     423        check_fds (sockets, fds, NUM_POLLEES);
     424        g_assert (r == 0);
     425  
     426        diff = times[i][1] - times[i][0];
     427        if (times_min > diff)
     428          times_min = diff;
     429        if (times_max < diff)
     430          times_max = diff;
     431        times_avg += diff;
     432        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     433      }
     434  
     435    times_avg /= NUM_POLLEES;
     436    g_printerr ("half-socket poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg);
     437    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     438  
     439    times_avg = 0;
     440    times_min = G_MAXINT64;
     441    times_max = 0;
     442    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     443  
     444    for (i = 0; i < REPEAT; i++)
     445      {
     446        gint r, s, v, t;
     447        gint64 diff;
     448        gint j;
     449        MSG msg;
     450        gboolean found_app;
     451  
     452        reset_fds (fds, NUM_POLLEES);
     453        reset_fds_msg (fds, NUM_POLLFDS);
     454        s = v = 0;
     455  
     456        for (j = 0; j < NUM_POLLEES / 2; j++)
     457          s += send (opp_sockets[j], (const char *) &t, 1, 0) == 1 ? 1 : 0;
     458        g_assert (PostMessage (NULL, WM_APP, 1, 2));
     459  
     460        /* This is to ensure that all sockets catch up, otherwise some might not poll active */
     461        g_usleep (G_USEC_PER_SEC / 1000);
     462  
     463        times[i][0] = g_get_monotonic_time ();
     464        r = g_poll (fds, NUM_POLLFDS, 1000);
     465        times[i][1] = g_get_monotonic_time ();
     466        check_fds (sockets, fds, NUM_POLLEES);
     467        for (j = 0; j < NUM_POLLEES / 2; j++)
     468          v += recv (sockets[j], (char *) &t, 1, 0) == 1 ? 1 : 0;
     469        found_app = FALSE;
     470        while (!found_app && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     471          if (msg.message == WM_APP && msg.wParam == 1 && msg.lParam == 2)
     472            found_app = TRUE;
     473        g_assert (s == NUM_POLLEES / 2);
     474        g_assert (r == NUM_POLLEES / 2 + 1);
     475        g_assert (v == NUM_POLLEES / 2);
     476        g_assert (found_app);
     477  
     478        reset_fds (fds, NUM_POLLEES);
     479        reset_fds_msg (fds, NUM_POLLFDS);
     480        r = g_poll (fds, NUM_POLLFDS, 0);
     481        check_fds (sockets, fds, NUM_POLLEES);
     482        g_assert (r == 0);
     483  
     484        diff = times[i][1] - times[i][0];
     485        if (times_min > diff)
     486          times_min = diff;
     487        if (times_max < diff)
     488          times_max = diff;
     489        times_avg += diff;
     490        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     491      }
     492  
     493    times_avg /= NUM_POLLEES;
     494    g_printerr ("half-socket + msg poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg);
     495    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     496  
     497    times_avg = 0;
     498    times_min = G_MAXINT64;
     499    times_max = 0;
     500    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     501  
     502    for (i = 0; i < REPEAT; i++)
     503      {
     504        gint r, s, v, t;
     505        gint64 diff;
     506        gint j;
     507  
     508        reset_fds (fds, NUM_POLLEES);
     509        reset_fds_msg (fds, NUM_POLLFDS);
     510        s = v = 0;
     511  
     512        for (j = 0; j < NUM_POLLEES; j++)
     513          s += send (opp_sockets[j], (const char *) &t, 1, 0) == 1 ? 1 : 0;
     514  
     515        g_usleep (G_USEC_PER_SEC / 1000);
     516  
     517        times[i][0] = g_get_monotonic_time ();
     518        r = g_poll (fds, NUM_POLLFDS, 1000);
     519        times[i][1] = g_get_monotonic_time ();
     520        check_fds (sockets, fds, NUM_POLLEES);
     521        for (j = 0; j < NUM_POLLEES; j++)
     522          v += recv (sockets[j], (char *) &t, 1, 0) == 1 ? 1 : 0;
     523        g_assert (s == NUM_POLLEES);
     524        g_assert (r == NUM_POLLEES);
     525        g_assert (v == NUM_POLLEES);
     526  
     527        reset_fds (fds, NUM_POLLEES);
     528        reset_fds_msg (fds, NUM_POLLFDS);
     529        r = g_poll (fds, NUM_POLLFDS, 0);
     530        check_fds (sockets, fds, NUM_POLLEES);
     531        g_assert (r == 0);
     532  
     533        diff = times[i][1] - times[i][0];
     534        if (times_min > diff)
     535          times_min = diff;
     536        if (times_max < diff)
     537          times_max = diff;
     538        times_avg += diff;
     539        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     540      }
     541  
     542    times_avg /= NUM_POLLEES;
     543    g_printerr ("%d-socket poll time: \n%4lldns - %4lldns, average %4lldns\n", NUM_POLLEES, times_min, times_max, times_avg);
     544    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     545  
     546    activatable = 0;
     547    times_avg = 0;
     548    times_min = G_MAXINT64;
     549    times_max = 0;
     550    memset (buckets, 0, sizeof (gint) * BUCKET_COUNT);
     551  
     552    for (i = 0; i < REPEAT; i++)
     553      {
     554        gint r, s, v, t;
     555        gint64 diff;
     556        gint j;
     557        MSG msg;
     558        gboolean found_app;
     559  
     560        reset_fds (fds, NUM_POLLEES);
     561        reset_fds_msg (fds, NUM_POLLFDS);
     562        s = v = 0;
     563  
     564        for (j = 0; j < activatable; j++)
     565          s += send (opp_sockets[j], (const char *) &t, 1, 0) == 1 ? 1 : 0;
     566        g_assert (PostMessage (NULL, WM_APP, 1, 2));
     567  
     568        g_usleep (G_USEC_PER_SEC / 1000);
     569  
     570        times[i][0] = g_get_monotonic_time ();
     571        r = g_poll (fds, NUM_POLLFDS, 1000);
     572        times[i][1] = g_get_monotonic_time ();
     573        check_fds (sockets, fds, NUM_POLLEES);
     574        for (j = 0; j < activatable; j++)
     575          v += recv (sockets[j], (char *) &t, 1, 0) == 1 ? 1 : 0;
     576        found_app = FALSE;
     577        while (!found_app && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     578          if (msg.message == WM_APP && msg.wParam == 1 && msg.lParam == 2)
     579            found_app = TRUE;
     580        g_assert (s == activatable);
     581        g_assert (r == activatable + 1);
     582        g_assert (v == activatable);
     583        g_assert (found_app);
     584  
     585        reset_fds (fds, NUM_POLLEES);
     586        reset_fds_msg (fds, NUM_POLLFDS);
     587        r = g_poll (fds, NUM_POLLFDS, 0);
     588        check_fds (sockets, fds, NUM_POLLEES);
     589        g_assert (r == 0);
     590  
     591        diff = times[i][1] - times[i][0];
     592        if (times_min > diff)
     593          times_min = diff;
     594        if (times_max < diff)
     595          times_max = diff;
     596        times_avg += diff;
     597        bucketize (diff, buckets, bucket_limits, BUCKET_COUNT);
     598        activatable = (activatable + 1) % NUM_POLLEES;
     599      }
     600  
     601    times_avg /= NUM_POLLEES;
     602    g_printerr ("variable socket number + msg poll time: \n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg);
     603    print_buckets (buckets, bucket_limits, BUCKET_COUNT);
     604  
     605    cleanup_sockets (sockets, opp_sockets, NUM_POLLEES);
     606  }
     607  
     608  int
     609  main (int   argc,
     610        char *argv[])
     611  {
     612    int result;
     613    GMainContext *ctx;
     614  
     615    g_test_init (&argc, &argv, NULL);
     616    init_networking ();
     617    ctx = g_main_context_new ();
     618  
     619    g_test_add_func ("/gpoll/gpoll", test_gpoll);
     620  
     621    result = g_test_run ();
     622  
     623    g_main_context_unref (ctx);
     624  
     625    return result;
     626  }