(root)/
glib-2.79.0/
glib/
tests/
protocol.c
       1  /* This file is part of GLib
       2   *
       3   * Copyright (C) 2010  Sven Herzberg
       4   *
       5   * SPDX-License-Identifier: LicenseRef-old-glib-tests
       6   *
       7   * This work is provided "as is"; redistribution and modification
       8   * in whole or in part, in any medium, physical or electronic is
       9   * permitted without restriction.
      10   *
      11   * This work is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      14   *
      15   * In no event shall the authors or contributors be liable for any
      16   * direct, indirect, incidental, special, exemplary, or consequential
      17   * damages (including, but not limited to, procurement of substitute
      18   * goods or services; loss of use, data, or profits; or business
      19   * interruption) however caused and on any theory of liability, whether
      20   * in contract, strict liability, or tort (including negligence or
      21   * otherwise) arising in any way out of the use of this software, even
      22   * if advised of the possibility of such damage.
      23   */
      24  
      25  #include <errno.h>  /* errno */
      26  #include <glib.h>
      27  #ifdef G_OS_UNIX
      28  #include <unistd.h> /* pipe() */
      29  #endif
      30  #ifdef G_OS_WIN32
      31  #include <io.h>
      32  #include <fcntl.h>
      33  #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
      34  #endif
      35  
      36  static const char *argv0;
      37  
      38  static void
      39  debug (void)
      40  {
      41    if (g_test_subprocess ())
      42      g_debug ("this is a regular g_debug() from the test suite");
      43  }
      44  
      45  static void
      46  info (void)
      47  {
      48    if (g_test_subprocess ())
      49      g_info ("this is a regular g_info from the test suite");
      50  }
      51  
      52  static void
      53  message (void)
      54  {
      55    if (g_test_subprocess ())
      56      g_message ("this is a regular g_message() from the test suite");
      57  }
      58  
      59  static void
      60  warning (void)
      61  {
      62    if (g_test_subprocess ())
      63      g_warning ("this is a regular g_warning() from the test suite");
      64  }
      65  
      66  static void
      67  critical (void)
      68  {
      69    if (g_test_subprocess ())
      70      g_critical ("this is a regular g_critical() from the test suite");
      71  }
      72  
      73  static void
      74  error (void)
      75  {
      76    if (g_test_subprocess ())
      77      g_error ("this is a regular g_error() from the test suite");
      78  }
      79  
      80  static void
      81  gtest_message (void)
      82  {
      83    if (g_test_subprocess ())
      84      g_test_message ("this is a regular g_test_message() from the test suite");
      85  }
      86  
      87  static gboolean
      88  test_message_cb1 (GIOChannel  * channel,
      89                    GIOCondition  condition,
      90                    gpointer      user_data)
      91  {
      92    GIOStatus  status;
      93    guchar     buf[512];
      94    gsize      read_bytes = 0;
      95   
      96    g_assert_cmpuint (condition, ==, G_IO_IN);
      97  
      98    for (status = g_io_channel_read_chars (channel, (gchar*)buf, sizeof (buf), &read_bytes, NULL);
      99         status == G_IO_STATUS_NORMAL;
     100         status = g_io_channel_read_chars (channel, (gchar*)buf, sizeof (buf), &read_bytes, NULL))
     101      {
     102        g_test_log_buffer_push (user_data, read_bytes, buf);
     103      }
     104  
     105    if (status == G_IO_STATUS_EOF)
     106      return FALSE;
     107    else
     108      g_assert_cmpuint (status, ==, G_IO_STATUS_AGAIN);
     109  
     110    return TRUE;
     111  }
     112  
     113  static void
     114  test_message_cb2 (GPid      pid,
     115                    gint      status,
     116                    gpointer  user_data)
     117  {
     118    g_spawn_close_pid (pid);
     119  
     120    g_main_loop_quit (user_data);
     121  }
     122  
     123  static void
     124  test_message (void)
     125  {
     126    gchar* argv[] = {
     127            (gchar*)argv0,
     128            NULL,
     129            "--GTestSubprocess",
     130            "-p", "/glib/testing/protocol/gtest-message",
     131            "-p", "/glib/testing/protocol/message",
     132            "-p", "/glib/testing/protocol/debug",
     133            NULL
     134    };
     135    GTestLogBuffer* tlb;
     136    GTestLogMsg   * msg;
     137    GIOChannel    * channel;
     138    GMainLoop     * loop;
     139    GError        * error = NULL;
     140    gulong          child_source;
     141    GPid            pid = 0;
     142    int             pipes[2];
     143    int             passed = 0;
     144    int             messages = 0;
     145    const char    * line_term;
     146    int             line_term_len;
     147  
     148    if (0 > pipe (pipes))
     149      {
     150        int errsv = errno;
     151        g_error ("error creating pipe: %s", g_strerror (errsv));
     152      }
     153  
     154    argv[1] = g_strdup_printf ("--GTestLogFD=%u", pipes[1]);
     155  
     156    if (!g_spawn_async (NULL,
     157                        argv, NULL,
     158                        G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
     159                        G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
     160                        NULL, NULL, &pid,
     161                        &error))
     162      {
     163        g_error ("error spawning the test: %s", error->message);
     164      }
     165  
     166    close (pipes[1]);
     167    tlb = g_test_log_buffer_new ();
     168    loop = g_main_loop_new (NULL, FALSE);
     169  
     170  #ifdef G_OS_WIN32
     171    channel = g_io_channel_win32_new_fd (pipes[0]);
     172  #else
     173    channel = g_io_channel_unix_new (pipes[0]);
     174  #endif
     175    g_io_channel_set_close_on_unref (channel, TRUE);
     176    g_io_channel_set_encoding (channel, NULL, NULL);
     177    g_io_channel_set_buffered (channel, FALSE);
     178    g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
     179    g_assert (g_io_channel_get_line_term (channel, NULL) == NULL);
     180    g_io_channel_set_line_term (channel, "\n", 1);
     181    line_term = g_io_channel_get_line_term (channel, &line_term_len);
     182    g_assert_cmpint (*line_term, ==, '\n');
     183    g_assert_cmpint (line_term_len, ==, 1);
     184  
     185    g_assert (g_io_channel_get_close_on_unref (channel));
     186    g_assert (g_io_channel_get_encoding (channel) == NULL);
     187    g_assert (!g_io_channel_get_buffered (channel));
     188  
     189    g_io_add_watch (channel, G_IO_IN, test_message_cb1, tlb);
     190    child_source = g_child_watch_add (pid, test_message_cb2, loop);
     191  
     192    g_main_loop_run (loop);
     193  
     194    test_message_cb1 (channel, G_IO_IN, tlb);
     195  
     196    g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "Source ID*");
     197    g_assert (!g_source_remove (child_source));
     198    g_test_assert_expected_messages ();
     199    g_io_channel_unref (channel);
     200  
     201    for (msg = g_test_log_buffer_pop (tlb);
     202         msg;
     203         msg = g_test_log_buffer_pop (tlb))
     204      {
     205        switch (msg->log_type)
     206          {
     207          case G_TEST_LOG_START_BINARY:
     208          case G_TEST_LOG_START_CASE:
     209          case G_TEST_LOG_START_SUITE:
     210          case G_TEST_LOG_STOP_SUITE:
     211            /* ignore */
     212            break;
     213          case G_TEST_LOG_STOP_CASE:
     214            passed++;
     215            break;
     216          case G_TEST_LOG_MESSAGE:
     217            {
     218              gchar const* known_messages[] = {
     219                      "this is a regular g_test_message() from the test suite",
     220                      "GLib-MESSAGE: this is a regular g_message() from the test suite",
     221                      "GLib-DEBUG: this is a regular g_debug() from the test suite"
     222              };
     223              g_assert_cmpint (messages, <, G_N_ELEMENTS (known_messages));
     224              g_assert_cmpstr (msg->strings[0], ==, known_messages[messages]);
     225              messages++;
     226            }
     227            break;
     228          case G_TEST_LOG_ERROR:
     229            g_assert_not_reached ();
     230            break;
     231          default:
     232            g_error ("unexpected log message type: %s", g_test_log_type_name (msg->log_type));
     233          }
     234         g_test_log_msg_free (msg);
     235      }
     236  
     237    g_assert_cmpint (passed, ==, 3);
     238    g_assert_cmpint (messages, ==, 3);
     239  
     240    g_free (argv[1]);
     241    g_main_loop_unref (loop);
     242    g_test_log_buffer_free (tlb);
     243  }
     244  
     245  static void
     246  test_error (void)
     247  {
     248    gchar* tests[] = {
     249            "/glib/testing/protocol/warning",
     250            "/glib/testing/protocol/critical",
     251            "/glib/testing/protocol/error"
     252    };
     253    gsize i;
     254    int             messages = 0;
     255  
     256    for (i = 0; i < G_N_ELEMENTS (tests); i++)
     257      {
     258        gchar* argv[] = {
     259                (gchar*)argv0,
     260                NULL,
     261                "--GTestSubprocess",
     262                "-p", tests[i],
     263                NULL
     264        };
     265        GTestLogBuffer* tlb;
     266        GTestLogMsg   * msg;
     267        GIOChannel    * channel;
     268        GMainLoop     * loop;
     269        GError        * error = NULL;
     270        gulong          child_source;
     271        GPid            pid = 0;
     272        int             pipes[2];
     273  
     274        if (0 > pipe (pipes))
     275          {
     276            int errsv = errno;
     277            g_error ("error creating pipe: %s", g_strerror (errsv));
     278          }
     279  
     280        argv[1] = g_strdup_printf ("--GTestLogFD=%u", pipes[1]);
     281  
     282        if (!g_spawn_async (NULL,
     283                            argv, NULL,
     284                            G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
     285                            G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
     286                            NULL, NULL, &pid,
     287                            &error))
     288          {
     289            g_error ("error spawning the test: %s", error->message);
     290          }
     291  
     292        close (pipes[1]);
     293        tlb = g_test_log_buffer_new ();
     294        loop = g_main_loop_new (NULL, FALSE);
     295  
     296  #ifdef G_OS_WIN32
     297        channel = g_io_channel_win32_new_fd (pipes[0]);
     298  #else
     299        channel = g_io_channel_unix_new (pipes[0]);
     300  #endif
     301        g_io_channel_set_close_on_unref (channel, TRUE);
     302        g_io_channel_set_encoding (channel, NULL, NULL);
     303        g_io_channel_set_buffered (channel, FALSE);
     304        g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
     305  
     306        g_io_add_watch (channel, G_IO_IN, test_message_cb1, tlb);
     307        child_source = g_child_watch_add (pid, test_message_cb2, loop);
     308  
     309        g_main_loop_run (loop);
     310  
     311        test_message_cb1 (channel, G_IO_IN, tlb);
     312  
     313        g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "Source ID*");
     314        g_assert (!g_source_remove (child_source));
     315        g_test_assert_expected_messages ();
     316        g_io_channel_unref (channel);
     317  
     318        for (msg = g_test_log_buffer_pop (tlb);
     319             msg;
     320             msg = g_test_log_buffer_pop (tlb))
     321          {
     322            switch (msg->log_type)
     323              {
     324              case G_TEST_LOG_START_BINARY:
     325              case G_TEST_LOG_START_CASE:
     326              case G_TEST_LOG_START_SUITE:
     327              case G_TEST_LOG_STOP_SUITE:
     328                /* ignore */
     329                break;
     330              case G_TEST_LOG_STOP_CASE:
     331              case G_TEST_LOG_MESSAGE:
     332                g_assert_not_reached ();
     333                break;
     334              case G_TEST_LOG_ERROR:
     335                  {
     336                    gchar const* known_messages[] = {
     337                            "GLib-FATAL-WARNING: this is a regular g_warning() from the test suite",
     338                            "GLib-FATAL-CRITICAL: this is a regular g_critical() from the test suite",
     339                            "GLib-FATAL-ERROR: this is a regular g_error() from the test suite"
     340                    };
     341                    g_assert_cmpint (messages, <, G_N_ELEMENTS (known_messages));
     342                    g_assert_cmpstr (msg->strings[0], ==, known_messages[messages]);
     343                    messages++;
     344                  }
     345                break;
     346              default:
     347                g_error ("unexpected log message type: %s", g_test_log_type_name (msg->log_type));
     348              }
     349              g_test_log_msg_free (msg);
     350          }
     351  
     352        g_free (argv[1]);
     353        g_main_loop_unref (loop);
     354        g_test_log_buffer_free (tlb);
     355      }
     356  
     357    g_assert_cmpint (messages, ==, 3);
     358  }
     359  
     360  int
     361  main (int   argc,
     362        char**argv)
     363  {
     364    argv0 = argv[0];
     365  
     366    g_test_init (&argc, &argv, NULL);
     367  
     368    /* we use ourself as the testcase, these are the ones we need internally */
     369    g_test_add_func ("/glib/testing/protocol/debug", debug);
     370    g_test_add_func ("/glib/testing/protocol/info", info);
     371    g_test_add_func ("/glib/testing/protocol/message", message);
     372    g_test_add_func ("/glib/testing/protocol/warning", warning);
     373    g_test_add_func ("/glib/testing/protocol/critical", critical);
     374    g_test_add_func ("/glib/testing/protocol/error", error);
     375    g_test_add_func ("/glib/testing/protocol/gtest-message", gtest_message);
     376  
     377    /* these are the real tests */
     378    g_test_add_func ("/glib/testing/protocol/test-message", test_message);
     379    g_test_add_func ("/glib/testing/protocol/test-error", test_error);
     380  
     381    return g_test_run ();
     382  }
     383  
     384  /* vim:set et sw=2 cino=t0,f0,(0,{s,>2s,n-1s,^-1s,e2s: */