Files
zoitechat/src/fe-gtk/tests/test-emoji-font.c

175 lines
5.2 KiB
C
Raw Normal View History

/* Shared headless font coverage and ordinary text regression tests.
* Distributed under GPL-2.0-or-later; see COPYING. */
#include "../emoji-font.h"
#include "../../common/emoji-data.h"
#include <pango/pangofc-fontmap.h>
2026-09-10 19:55:33 -06:00
#include <pango/pangofc-font.h>
static GHashTable *font_checksums;
static char *bundled_checksum;
static const char *
font_checksum (const char *path)
{
const char *cached = g_hash_table_lookup (font_checksums, path);
char *contents, *checksum;
gsize length;
if (cached)
return cached;
g_assert_true (g_file_get_contents (path, &contents, &length, NULL));
checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
(const guchar *) contents, length);
g_free (contents);
g_hash_table_insert (font_checksums, g_strdup (path), checksum);
return checksum;
}
static void
assert_bundled_font (PangoFont *font, gboolean expected)
{
FcPattern *pattern;
FcChar8 *path;
const char *checksum;
/* Pango can describe a face by its embedded name rather than its
* Fontconfig alias. Verify the resolved file's bytes, not that name.
* Cache by filename so catalog coverage does not reread the font for
* every glyph. An older system Noto must still fail this assertion. */
g_assert_true (PANGO_IS_FC_FONT (font));
#if PANGO_VERSION_CHECK(1, 48, 0)
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
#else
pattern = PANGO_FC_FONT (font)->font_pattern;
#endif
g_assert_cmpint (FcPatternGetString (pattern, FC_FILE, 0, &path), ==, FcResultMatch);
checksum = font_checksum ((const char *) path);
if (expected)
g_assert_cmpstr (checksum, ==, bundled_checksum);
else
g_assert_cmpstr (checksum, !=, bundled_checksum);
}
static void
test_font_catalog (void)
{
PangoFontMap *map = emoji_font_get_map ();
PangoContext *context;
PangoLayout *layout;
PangoFontDescription *desc;
gsize i;
int tone;
g_assert_nonnull (map);
context = pango_font_map_create_context (map);
g_assert_true (PANGO_IS_FC_FONT_MAP (map));
layout = pango_layout_new (context);
desc = pango_font_description_from_string (ZOITECHAT_EMOJI_FAMILY " 15");
pango_layout_set_font_description (layout, desc);
for (i = 0; i < emoji_data_count (); i++)
{
const EmojiEntry *entry = emoji_data_entry (i);
for (tone = 0; tone < (entry->tone_set < 0 ? 1 : EMOJI_TONE_COUNT); tone++)
{
PangoLayoutIter *iter;
pango_layout_set_text (layout, emoji_entry_sequence_for_tone (entry, tone), -1);
g_assert_cmpint (pango_layout_get_unknown_glyphs_count (layout), ==, 0);
iter = pango_layout_get_iter (layout);
do
{
PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter);
if (run)
{
2026-09-10 19:55:33 -06:00
assert_bundled_font (run->item->analysis.font, TRUE);
}
} while (pango_layout_iter_next_run (iter));
pango_layout_iter_free (iter);
}
}
pango_font_description_free (desc);
g_object_unref (layout);
g_object_unref (context);
}
static void
test_plain_text_font (void)
{
PangoFontMap *map = emoji_font_get_map ();
PangoContext *context;
PangoLayout *layout;
PangoLayoutIter *iter;
PangoFontDescription *desc;
g_assert_nonnull (map);
context = pango_font_map_create_context (map);
layout = pango_layout_new (context);
pango_layout_set_text (layout, "/join #channel 0123456789 *", -1);
desc = pango_font_description_from_string ("Monospace 12");
pango_layout_set_font_description (layout, desc);
iter = pango_layout_get_iter (layout);
do
{
PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter);
if (run)
{
2026-09-10 19:55:33 -06:00
assert_bundled_font (run->item->analysis.font, FALSE);
}
} while (pango_layout_iter_next_run (iter));
pango_layout_iter_free (iter);
pango_font_description_free (desc);
g_object_unref (layout);
g_object_unref (context);
}
static void
test_implicit_emoji_font (void)
{
PangoFontMap *map = emoji_font_get_map ();
PangoContext *context = pango_font_map_create_context (map);
PangoLayout *layout = pango_layout_new (context);
PangoFontDescription *desc = pango_font_description_from_string ("Monospace 12");
const char *samples[] = { "\360\237\230\200", "#\357\270\217\342\203\243", "\360\237\253\252" };
gsize i;
pango_layout_set_font_description (layout, desc);
for (i = 0; i < G_N_ELEMENTS (samples); i++)
{
PangoLayoutIter *iter;
pango_layout_set_text (layout, samples[i], -1);
g_assert_cmpint (pango_layout_get_unknown_glyphs_count (layout), ==, 0);
iter = pango_layout_get_iter (layout);
do
{
PangoLayoutRun *run = pango_layout_iter_get_run_readonly (iter);
if (run)
{
2026-09-10 19:55:33 -06:00
assert_bundled_font (run->item->analysis.font, TRUE);
}
} while (pango_layout_iter_next_run (iter));
pango_layout_iter_free (iter);
}
pango_font_description_free (desc);
g_object_unref (layout);
g_object_unref (context);
}
int
main (int argc, char **argv)
{
2026-09-10 19:55:33 -06:00
const char *path;
int result;
g_test_init (&argc, &argv, NULL);
2026-09-10 19:55:33 -06:00
path = g_getenv ("ZOITECHAT_EMOJI_FONT");
g_assert_nonnull (path);
font_checksums = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
bundled_checksum = g_strdup (font_checksum (path));
g_test_add_func ("/emoji-font/catalog", test_font_catalog);
g_test_add_func ("/emoji-font/plain-text", test_plain_text_font);
g_test_add_func ("/emoji-font/implicit-emoji", test_implicit_emoji_font);
2026-09-10 19:55:33 -06:00
result = g_test_run ();
g_free (bundled_checksum);
g_hash_table_destroy (font_checksums);
return result;
}