(root)/
glib-2.79.0/
glib/
tests/
markup-collect.c
       1  /* 
       2   * Copyright © 2007 Ryan Lortie
       3   * 
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This program is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   * 
      11   * See the included COPYING file for more information.
      12   */
      13  
      14  #include <stdlib.h>
      15  #include <string.h>
      16  #include <glib.h>
      17  
      18  static void
      19  start (GMarkupParseContext  *context,
      20         const char           *element_name,
      21         const char          **attribute_names,
      22         const char          **attribute_values,
      23         gpointer              user_data,
      24         GError              **error)
      25  {
      26    GString *string = user_data;
      27    gboolean result;
      28  
      29  #define collect(...) \
      30    g_markup_collect_attributes (element_name, attribute_names, \
      31                                 attribute_values, error, __VA_ARGS__, \
      32                                 G_MARKUP_COLLECT_INVALID)
      33  #define BOOL    G_MARKUP_COLLECT_BOOLEAN
      34  #define OPTBOOL G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL
      35  #define TRI     G_MARKUP_COLLECT_TRISTATE
      36  #define STR     G_MARKUP_COLLECT_STRING
      37  #define STRDUP  G_MARKUP_COLLECT_STRDUP
      38  #define OPTSTR  G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL
      39  #define OPTDUP  G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL
      40  #define n(x)    ((x)?(x):"(null)")
      41  
      42    if (strcmp (element_name, "bool") == 0)
      43      {
      44        gboolean mb = 2, ob = 2, tri = 2;
      45  
      46        result = collect (BOOL,    "mb", &mb,
      47                          OPTBOOL, "ob", &ob,
      48                          TRI,     "tri", &tri);
      49  
      50        g_assert (result ||
      51                  (mb == FALSE && ob == FALSE && tri != TRUE && tri != FALSE));
      52  
      53        if (tri != FALSE && tri != TRUE)
      54          tri = -1;
      55  
      56        g_string_append_printf (string, "<bool(%d) %d %d %d>",
      57                                result, mb, ob, tri);
      58      }
      59  
      60    else if (strcmp (element_name, "str") == 0)
      61      {
      62        const char *cm, *co;
      63        char *am, *ao;
      64  
      65        result = collect (STR,    "cm", &cm,
      66                          STRDUP, "am", &am,
      67                          OPTDUP, "ao", &ao,
      68                          OPTSTR, "co", &co);
      69  
      70        g_assert (result ||
      71                  (cm == NULL && am == NULL && ao == NULL && co == NULL));
      72  
      73        g_string_append_printf (string, "<str(%d) %s %s %s %s>",
      74                                result, n (cm), n (am), n (ao), n (co));
      75  
      76        g_free (am);
      77        g_free (ao);
      78      }
      79  }
      80  
      81  static GMarkupParser parser = { start, NULL, NULL, NULL, NULL };
      82  
      83  struct test
      84  {
      85    const char   *document;
      86    const char   *result;
      87    GMarkupError  error_code;
      88    const char   *error_info;
      89  };
      90  
      91  static struct test tests[] =
      92  {
      93    { "<bool mb='y'>", "<bool(1) 1 0 -1>",
      94      G_MARKUP_ERROR_PARSE, "'bool'" },
      95  
      96    { "<bool mb='false'/>", "<bool(1) 0 0 -1>", 0, NULL },
      97    { "<bool mb='true'/>", "<bool(1) 1 0 -1>", 0, NULL },
      98    { "<bool mb='t' ob='f' tri='1'/>", "<bool(1) 1 0 1>", 0, NULL },
      99    { "<bool mb='y' ob='n' tri='0'/>", "<bool(1) 1 0 0>", 0, NULL },
     100  
     101    { "<bool mb='y' my:attr='q'><my:tag/></bool>", "<bool(1) 1 0 -1>", 0, NULL },
     102    { "<bool mb='y' my:attr='q'><my:tag>some <b>text</b> is in here</my:tag></bool>",
     103      "<bool(1) 1 0 -1>", 0, NULL },
     104  
     105    { "<bool ob='y'/>", "<bool(0) 0 0 -1>",
     106      G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'mb'" },
     107  
     108    { "<bool mb='y' mb='y'/>", "<bool(0) 0 0 -1>",
     109      G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" },
     110  
     111    { "<bool mb='y' tri='y' tri='n'/>", "<bool(0) 0 0 -1>",
     112      G_MARKUP_ERROR_INVALID_CONTENT, "'tri'" },
     113  
     114    { "<str cm='x' am='y'/>", "<str(1) x y (null) (null)>", 0, NULL },
     115  
     116    { "<str am='x' co='y'/>", "<str(0) (null) (null) (null) (null)>",
     117      G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'cm'" },
     118  
     119    { "<str am='x'/>", "<str(0) (null) (null) (null) (null)>",
     120      G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'cm'" },
     121  
     122    { "<str am='x' cm='x' am='y'/>", "<str(0) (null) (null) (null) (null)>",
     123      G_MARKUP_ERROR_INVALID_CONTENT, "'am'" },
     124  
     125    { "<str am='x' qm='y' cm='x'/>", "<str(0) (null) (null) (null) (null)>",
     126      G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "'qm'" },
     127  
     128    { "<str am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' cm='x'/>", "<str(0) (null) (null) (null) (null)>",
     129      G_MARKUP_ERROR_INVALID_CONTENT, "'am'" },
     130  
     131    { "<str cm='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x'/>", "<str(0) (null) (null) (null) (null)>",
     132      G_MARKUP_ERROR_INVALID_CONTENT, "'am'" },
     133  
     134    { "<str a='x' b='x' c='x' d='x' e='x' f='x' g='x' h='x' i='x' j='x' k='x' l='x' m='x' n='x' o='x' p='x' q='x' r='x' s='x' t='x' u='x' v='x' w='x' x='x' y='x' z='x' aa='x' bb='x' cc='x' dd='x' ee='x' ff='x' gg='x' hh='x' ii='x' jj='x' kk='x' ll='x' mm='x' nn='x' oo='x' pp='x' qq='x' rr='x' ss='x' tt='x' uu='x' vv='x' ww='x' xx='x' yy='x' zz='x' am='x' cm='x'/>",
     135      "<str(0) (null) (null) (null) (null)>",
     136      G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "'a'" },
     137  
     138    { "<bool mb='ja'/>", "<bool(0) 0 0 -1>",
     139      G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" },
     140  
     141    { "<bool mb='nein'/>", "<bool(0) 0 0 -1>",
     142      G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" }
     143  };
     144  
     145  static void
     146  test_collect (gconstpointer d)
     147  {
     148    const struct test *test = d;
     149  
     150    GMarkupParseContext *ctx;
     151    GError *error = NULL;
     152    GString *string;
     153    gboolean result;
     154  
     155    string = g_string_new ("");
     156    ctx = g_markup_parse_context_new (&parser, G_MARKUP_IGNORE_QUALIFIED, string, NULL);
     157    result = g_markup_parse_context_parse (ctx,
     158                                           test->document,
     159                                           -1, &error);
     160    if (result)
     161      result = g_markup_parse_context_end_parse (ctx, &error);
     162  
     163    if (result)
     164      {
     165        g_assert_no_error (error);
     166        g_assert_cmpint (test->error_code, ==, 0);
     167        g_assert_cmpstr (test->result, ==, string->str);
     168      }
     169    else
     170      {
     171        g_assert_error (error, G_MARKUP_ERROR, (gint) test->error_code);
     172      }
     173  
     174    g_markup_parse_context_free (ctx);
     175    g_string_free (string, TRUE);
     176    g_clear_error (&error);
     177  }
     178  
     179  #define XML "<element a='1' b='2' c='3'/>"
     180  
     181  static void
     182  start_element (GMarkupParseContext  *context,
     183                 const gchar          *element_name,
     184                 const gchar         **attribute_names,
     185                 const gchar         **attribute_values,
     186                 gpointer              user_data,
     187                 GError              **error)
     188  {
     189    /* Omitting "c" attribute intentionally to trigger crash. */
     190    g_markup_collect_attributes (element_name,
     191                                 attribute_names,
     192                                 attribute_values,
     193                                 error,
     194                                 G_MARKUP_COLLECT_STRING, "a", NULL,
     195                                 G_MARKUP_COLLECT_STRING, "b", NULL,
     196                                 G_MARKUP_COLLECT_INVALID);
     197  }
     198  
     199  static GMarkupParser cleanup_parser = {
     200    start_element, NULL, NULL, NULL, NULL
     201  };
     202  
     203  static void
     204  test_cleanup (void)
     205  {
     206    GMarkupParseContext *context;
     207  
     208    if (!g_test_undefined ())
     209      return;
     210  
     211    context = g_markup_parse_context_new (&cleanup_parser,
     212                                          G_MARKUP_DEFAULT_FLAGS, NULL,
     213                                          NULL);
     214    g_markup_parse_context_parse (context, XML, -1, NULL);
     215  
     216    g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
     217                           "g_markup_parse_context_end_parse: assertion 'context->state != STATE_ERROR' failed");
     218    g_markup_parse_context_end_parse (context, NULL);
     219    g_test_assert_expected_messages ();
     220  
     221    g_markup_parse_context_free (context);
     222  }
     223  
     224  int
     225  main (int argc, char **argv)
     226  {
     227    gsize i;
     228    gchar *path;
     229  
     230    g_test_init (&argc, &argv, NULL);
     231  
     232    for (i = 0; i < G_N_ELEMENTS (tests); i++)
     233      {
     234        path = g_strdup_printf ("/markup/collect/%" G_GSIZE_FORMAT, i);
     235        g_test_add_data_func (path, &tests[i], test_collect);
     236        g_free (path);
     237      }
     238  
     239    g_test_add_func ("/markup/collect/cleanup", test_cleanup);
     240  
     241    return g_test_run ();
     242  }