(root)/
harfbuzz-8.3.0/
test/
api/
hb-test.h
       1  /*
       2   * Copyright © 2011  Google, Inc.
       3   *
       4   *  This is part of HarfBuzz, a text shaping library.
       5   *
       6   * Permission is hereby granted, without written agreement and without
       7   * license or royalty fees, to use, copy, modify, and distribute this
       8   * software and its documentation for any purpose, provided that the
       9   * above copyright notice and the following two paragraphs appear in
      10   * all copies of this software.
      11   *
      12   * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
      13   * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
      14   * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
      15   * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
      16   * DAMAGE.
      17   *
      18   * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
      19   * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      20   * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
      21   * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
      22   * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      23   *
      24   * Google Author(s): Behdad Esfahbod
      25   */
      26  
      27  #ifndef HB_TEST_H
      28  #define HB_TEST_H
      29  
      30  #include <hb-config.hh>
      31  
      32  #include <hb-glib.h>
      33  
      34  #include <stdlib.h>
      35  #include <string.h>
      36  #include <stdio.h>
      37  
      38  HB_BEGIN_DECLS
      39  
      40  /* Just in case */
      41  #undef G_DISABLE_ASSERT
      42  
      43  #define HB_UNUSED	G_GNUC_UNUSED
      44  
      45  /* Misc */
      46  
      47  /* This is too ugly to be public API, but quite handy. */
      48  #define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
      49  				  ((const char *) s)[1], \
      50  				  ((const char *) s)[2], \
      51  				  ((const char *) s)[3]))
      52  
      53  #define HB_FACE_ADD_TABLE(face, tag, data) \
      54  	do { \
      55  	  hb_blob_t *blob = hb_blob_create_or_fail ((data), \
      56  						    sizeof (data), \
      57  						    HB_MEMORY_MODE_READONLY, \
      58  						    NULL, NULL); \
      59  	  hb_face_builder_add_table ((face), \
      60  				     HB_TAG_CHAR4(tag), \
      61  				     blob); \
      62  	  hb_blob_destroy (blob); \
      63  	} while (0)
      64  
      65  static inline const char *
      66  srcdir (void)
      67  {
      68    static const char *s;
      69  
      70    if (!s) {
      71      s = getenv ("srcdir");
      72  
      73  #ifdef SRCDIR
      74      if (!s || !s[0])
      75        s = SRCDIR;
      76  #endif
      77  
      78      if (!s || !s[0])
      79        s = ".";
      80    }
      81  
      82    return s;
      83  }
      84  
      85  
      86  /* Helpers */
      87  
      88  static inline void
      89  hb_test_init (int *argc, char ***argv)
      90  {
      91    g_test_init (argc, argv, NULL);
      92  }
      93  
      94  static inline int
      95  hb_test_run (void)
      96  {
      97    return g_test_run ();
      98  }
      99  
     100  /* Bugzilla helpers */
     101  
     102  static inline void
     103  hb_test_bug (const char *uri_base, unsigned int number)
     104  {
     105    char *s = g_strdup_printf ("%u", number);
     106  
     107    g_test_bug_base (uri_base);
     108    g_test_bug (s);
     109  
     110    g_free (s);
     111  }
     112  
     113  static inline void
     114  hb_test_bug_freedesktop (unsigned int number)
     115  {
     116    hb_test_bug ("https://bugs.freedesktop.org/", number);
     117  }
     118  
     119  static inline void
     120  hb_test_bug_gnome (unsigned int number)
     121  {
     122    hb_test_bug ("https://bugzilla.gnome.org/", number);
     123  }
     124  
     125  static inline void
     126  hb_test_bug_mozilla (unsigned int number)
     127  {
     128    hb_test_bug ("https://bugzilla.mozilla.org/", number);
     129  }
     130  
     131  static inline void
     132  hb_test_bug_redhat (unsigned int number)
     133  {
     134    hb_test_bug ("https://bugzilla.redhat.com/", number);
     135  }
     136  
     137  
     138  /* Wrap glib test functions to simplify.  Should have been in glib already. */
     139  
     140  /* Drops the "test_" prefix and converts '_' to '/'.
     141   * Essentially builds test path from function name. */
     142  static inline char *
     143  hb_test_normalize_path (const char *path)
     144  {
     145    char *s, *p;
     146  
     147    g_assert (0 == strncmp (path, "test_", 5));
     148    path += 4;
     149  
     150    s = g_strdup (path);
     151    for (p = s; *p; p++)
     152      if (*p == '_')
     153        *p = '/';
     154  
     155    return s;
     156  }
     157  
     158  
     159  #if GLIB_CHECK_VERSION(2,25,12)
     160  typedef GTestFunc        hb_test_func_t;
     161  typedef GTestDataFunc    hb_test_data_func_t;
     162  typedef GTestFixtureFunc hb_test_fixture_func_t;
     163  #else
     164  typedef void (*hb_test_func_t)         (void);
     165  typedef void (*hb_test_data_func_t)    (gconstpointer user_data);
     166  typedef void (*hb_test_fixture_func_t) (void);
     167  #endif
     168  
     169  #if !GLIB_CHECK_VERSION(2,30,0)
     170  #define g_test_fail() g_error("Test failed")
     171  #endif
     172  #ifndef g_assert_true
     173  #define g_assert_true g_assert
     174  #endif
     175  #ifndef g_assert_cmpmem
     176  #define g_assert_cmpmem(m1, l1, m2, l2) g_assert_true (l1 == l2 && memcmp (m1, m2, l1) == 0)
     177  #endif
     178  
     179  static inline void hb_test_assert_blobs_equal (hb_blob_t *expected_blob, hb_blob_t *actual_blob)
     180  {
     181    unsigned int expected_length, actual_length;
     182    const char *raw_expected = hb_blob_get_data (expected_blob, &expected_length);
     183    const char *raw_actual = hb_blob_get_data (actual_blob, &actual_length);
     184    g_assert_cmpint(expected_length, ==, actual_length);
     185    if (memcmp (raw_expected, raw_actual, expected_length) != 0)
     186    {
     187      for (unsigned int i = 0; i < expected_length; i++)
     188      {
     189        int expected = *(raw_expected + i);
     190        int actual = *(raw_actual + i);
     191        if (expected != actual) fprintf(stderr, "+%u %02x != %02x\n", i, expected, actual);
     192        else fprintf(stderr, "+%u %02x\n", i, expected);
     193      }
     194    }
     195    g_assert_cmpint(0, ==, memcmp(raw_expected, raw_actual, expected_length));
     196  }
     197  
     198  static inline void
     199  hb_test_add_func (const char *test_path,
     200  		  hb_test_func_t   test_func)
     201  {
     202    char *normal_path = hb_test_normalize_path (test_path);
     203    g_test_add_func (normal_path, test_func);
     204    g_free (normal_path);
     205  }
     206  #define hb_test_add(Func) hb_test_add_func (#Func, Func)
     207  
     208  static inline void
     209  hb_test_add_func_flavor (const char *test_path,
     210  			 const char *flavor,
     211  			 hb_test_func_t   test_func)
     212  {
     213    char *path = g_strdup_printf ("%s/%s", test_path, flavor);
     214    hb_test_add_func (path, test_func);
     215    g_free (path);
     216  }
     217  #define hb_test_add_flavor(Flavor, Func) hb_test_add_func (#Func, Flavor, Func)
     218  
     219  static inline void
     220  hb_test_add_data_func (const char          *test_path,
     221  		       gconstpointer        test_data,
     222  		       hb_test_data_func_t  test_func)
     223  {
     224    char *normal_path = hb_test_normalize_path (test_path);
     225    g_test_add_data_func (normal_path, test_data, test_func);
     226    g_free (normal_path);
     227  }
     228  #define hb_test_add_data(UserData, Func) hb_test_add_data_func (#Func, UserData, Func)
     229  
     230  static inline void
     231  hb_test_add_data_func_flavor (const char          *test_path,
     232  			      const char          *flavor,
     233  			      gconstpointer        test_data,
     234  			      hb_test_data_func_t  test_func)
     235  {
     236    char *path = g_strdup_printf ("%s/%s", test_path, flavor);
     237    hb_test_add_data_func (path, test_data, test_func);
     238    g_free (path);
     239  }
     240  #define hb_test_add_data_flavor(UserData, Flavor, Func) hb_test_add_data_func_flavor (#Func, Flavor, UserData, Func)
     241  
     242  
     243  static inline void
     244  hb_test_add_vtable (const char             *test_path,
     245  		    gsize                   data_size,
     246  		    gconstpointer           test_data,
     247  		    hb_test_fixture_func_t  data_setup,
     248  		    hb_test_fixture_func_t  data_test,
     249  		    hb_test_fixture_func_t  data_teardown)
     250  {
     251    char *normal_path = hb_test_normalize_path (test_path);
     252    g_test_add_vtable (normal_path, data_size, test_data, data_setup, data_test, data_teardown);
     253    g_free (normal_path);
     254  }
     255  #define hb_test_add_fixture(FixturePrefix, UserData, Func) \
     256  G_STMT_START { \
     257    typedef G_PASTE (FixturePrefix, _t) Fixture; \
     258    void (*add_vtable) (const char*, gsize, gconstpointer, \
     259  		      void (*) (Fixture*, gconstpointer), \
     260  		      void (*) (Fixture*, gconstpointer), \
     261  		      void (*) (Fixture*, gconstpointer)) \
     262  	= (void (*) (const gchar *, gsize, gconstpointer, \
     263  		     void (*) (Fixture*, gconstpointer), \
     264  		     void (*) (Fixture*, gconstpointer), \
     265  		     void (*) (Fixture*, gconstpointer))) hb_test_add_vtable; \
     266    add_vtable (#Func, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
     267  	      G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \
     268  } G_STMT_END
     269  
     270  static inline void
     271  hb_test_add_vtable_flavor (const char             *test_path,
     272  			   const char             *flavor,
     273  			   gsize                   data_size,
     274  			   gconstpointer           test_data,
     275  			   hb_test_fixture_func_t  data_setup,
     276  			   hb_test_fixture_func_t  data_test,
     277  			   hb_test_fixture_func_t  data_teardown)
     278  {
     279    char *path = g_strdup_printf ("%s/%s", test_path, flavor);
     280    hb_test_add_vtable (path, data_size, test_data, data_setup, data_test, data_teardown);
     281    g_free (path);
     282  }
     283  #define hb_test_add_fixture_flavor(FixturePrefix, UserData, Flavor, Func) \
     284  G_STMT_START { \
     285    typedef G_PASTE (FixturePrefix, _t) Fixture; \
     286    void (*add_vtable) (const char*, const char *, gsize, gconstpointer, \
     287  		      void (*) (Fixture*, gconstpointer), \
     288  		      void (*) (Fixture*, gconstpointer), \
     289  		      void (*) (Fixture*, gconstpointer)) \
     290  	= (void (*) (const gchar *, const char *, gsize, gconstpointer, \
     291  		     void (*) (Fixture*, gconstpointer), \
     292  		     void (*) (Fixture*, gconstpointer), \
     293  		     void (*) (Fixture*, gconstpointer))) hb_test_add_vtable_flavor; \
     294    add_vtable (#Func, Flavor, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
     295  	      G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \
     296  } G_STMT_END
     297  
     298  
     299  static inline hb_face_t *
     300  hb_test_open_font_file (const char *font_path)
     301  {
     302  #if GLIB_CHECK_VERSION(2,37,2)
     303    char *path = g_test_build_filename (G_TEST_DIST, font_path, NULL);
     304  #else
     305    char *path = g_strdup (font_path);
     306  #endif
     307  
     308    hb_blob_t *blob = hb_blob_create_from_file_or_fail (path);
     309    hb_face_t *face;
     310    if (!blob)
     311      g_error ("Font %s not found.", path);
     312  
     313    face = hb_face_create (blob, 0);
     314    hb_blob_destroy (blob);
     315  
     316    g_free (path);
     317  
     318    return face;
     319  }
     320  
     321  HB_END_DECLS
     322  
     323  #endif /* HB_TEST_H */