Branch: refs/heads/master Author: Thomas Martitz kugel@rockbox.org Committer: Thomas Martitz kugel@rockbox.org Date: Fri, 20 Sep 2019 20:58:25 UTC Commit: 64a32db5e1d202b9055dd90dab335f7c2afa62c0 https://github.com/geany/geany/commit/64a32db5e1d202b9055dd90dab335f7c2afa62...
Log Message: ----------- tests: unit test for some util strv functions
We didn't use unit tests so far so I have picked up the glib testing framework. While there are better frameworks out there glib's it gets the job done and doesn't impose extra dependencies.
For upcoming fixes and refactorings to utils_strv_find_lcs and utils_strv_shorten_file_list I would like to make sure to not introduce regressions and unit tests are ideal for that.
A function to be tested must be exported by libgeany.so. Use GEANY_EXPORT_SYMBOL for that. It's not the same as GEANY_API_SYMBOL to avoid the impression that it's OK to use them in plugins. Also no doxygen comments for those.
I resurrected utils_strv_new() because it's convinient to have in the tests. The function has its own test suite since it's otherwise unused.
Modified Paths: -------------- src/utils.c src/utils.h tests/Makefile.am tests/test_utils.c
Modified: src/utils.c 15 lines changed, 7 insertions(+), 8 deletions(-) =================================================================== @@ -1308,12 +1308,10 @@ void utils_free_pointers(gsize arg_count, ...) }
-/* currently unused */ -#if 0 /* Creates a string array deep copy of a series of non-NULL strings. - * The first argument is nothing special. - * The list must be ended with NULL. - * If first is NULL, NULL is returned. */ + * The first argument is nothing special and must not be NULL. + * The list must be terminated with NULL. */ +GEANY_EXPORT_SYMBOL gchar **utils_strv_new(const gchar *first, ...) { gsize strvlen, i; @@ -1343,7 +1341,6 @@ gchar **utils_strv_new(const gchar *first, ...) strv[i] = NULL; return strv; } -#endif
/** @@ -2053,7 +2050,8 @@ gchar **utils_strv_join(gchar **first, gchar **second) * @return The common prefix that is part of all strings (maybe empty), or NULL if an empty list * was passed in. */ -static gchar *utils_strv_find_common_prefix(gchar **strv, gssize strv_len) +GEANY_EXPORT_SYMBOL +gchar *utils_strv_find_common_prefix(gchar **strv, gssize strv_len) { gsize num;
@@ -2087,7 +2085,8 @@ static gchar *utils_strv_find_common_prefix(gchar **strv, gssize strv_len) * * @return The common prefix that is part of all strings. */ -static gchar *utils_strv_find_lcs(gchar **strv, gssize strv_len) +GEANY_EXPORT_SYMBOL +gchar *utils_strv_find_lcs(gchar **strv, gssize strv_len) { gchar *first, *_sub, *sub; gsize num;
Modified: src/utils.h 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -300,6 +300,10 @@ gchar **utils_strv_new(const gchar *first, ...) G_GNUC_NULL_TERMINATED;
gchar **utils_strv_join(gchar **first, gchar **second) G_GNUC_WARN_UNUSED_RESULT;
+gchar *utils_strv_find_common_prefix(gchar **strv, gssize strv_len) G_GNUC_WARN_UNUSED_RESULT; + +gchar *utils_strv_find_lcs(gchar **strv, gssize strv_len) G_GNUC_WARN_UNUSED_RESULT; + gchar **utils_strv_shorten_file_list(gchar **file_names, gssize file_names_len);
GSList *utils_get_config_files(const gchar *subdir);
Modified: tests/Makefile.am 11 lines changed, 11 insertions(+), 0 deletions(-) =================================================================== @@ -1,2 +1,13 @@
SUBDIRS = ctags + +AM_CPPFLAGS = -DGEANY_PRIVATE -DG_LOG_DOMAIN=""Geany"" @GTK_CFLAGS@ @GTHREAD_CFLAGS@ +AM_CPPFLAGS += -I$(top_srcdir)/src + +AM_LDFLAGS = $(GTK_LIBS) $(GTHREAD_LIBS) $(INTLLIBS) -no-install + +check_PROGRAMS = test_utils + +test_utils_LDADD = $(top_builddir)/src/libgeany.la + +TESTS = $(check_PROGRAMS)
Modified: tests/test_utils.c 367 lines changed, 367 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,367 @@ + +#include "utils.h" + +#include "gtkcompat.h" + +#define UTIL_TEST_ADD(path, func) g_test_add_func("/utils/" path, func); + + +static void test_utils_strv_new(void) +{ + gchar **data; + + data = utils_strv_new("1", NULL); + g_assert_nonnull(data); + g_assert_cmpint(g_strv_length(data), ==, 1); + g_assert_cmpstr(data[0], ==, "1"); + g_strfreev(data); + + data = utils_strv_new("1", "2", "3", NULL); + g_assert_nonnull(data); + g_assert_cmpint(g_strv_length(data), ==, 3); + g_assert_cmpstr(data[0], ==, "1"); + g_assert_cmpstr(data[1], ==, "2"); + g_assert_cmpstr(data[2], ==, "3"); + g_strfreev(data); + + data = utils_strv_new("1", "", "", "4", NULL); + g_assert_nonnull(data); + g_assert_cmpint(g_strv_length(data), ==, 4); + g_assert_cmpstr(data[0], ==, "1"); + g_assert_cmpstr(data[1], ==, ""); + g_assert_cmpstr(data[2], ==, ""); + g_assert_cmpstr(data[3], ==, "4"); + g_strfreev(data); +} + +static void test_utils_strv_find_common_prefix(void) +{ + gchar **data, *s; + + s = utils_strv_find_common_prefix(NULL, 0); + g_assert_null(s); + + data = utils_strv_new("", NULL); + s = utils_strv_find_common_prefix(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("1", "2", "3", NULL); + s = utils_strv_find_common_prefix(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("abc", "amn", "axy", NULL); + s = utils_strv_find_common_prefix(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "a"); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("abc", "", "axy", NULL); + s = utils_strv_find_common_prefix(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("22", "23", "33", NULL); + s = utils_strv_find_common_prefix(data, 1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "22"); + g_free(s); + s = utils_strv_find_common_prefix(data, 2); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "2"); + g_free(s); + s = utils_strv_find_common_prefix(data, 3); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("/home/user/src/geany/src/stash.c", + "/home/user/src/geany/src/sidebar.c", + "/home/user/src/geany/src/sidebar.h", + "/home/user/src/geany/src/sidebar.h", + "/home/user/src/geany/src/main.c", + "/home/user/src/geany-plugins/addons/src/addons.c", + NULL); + s = utils_strv_find_common_prefix(data, 4); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/home/user/src/geany/src/s"); + g_free(s); + s = utils_strv_find_common_prefix(data, 5); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/home/user/src/geany/src/"); + g_free(s); + s = utils_strv_find_common_prefix(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/home/user/src/geany"); + g_free(s); + g_strfreev(data); +} + +void test_utils_strv_find_lcs(void) +{ + gchar **data, *s; + + s = utils_strv_find_lcs(NULL, 0); + g_assert_null(s); + + data = utils_strv_new("", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("1", "2", "3", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("abc", "amn", "axy", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "a"); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("abc", "", "axy", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("22", "23", "33", NULL); + s = utils_strv_find_lcs(data, 1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "22"); + g_free(s); + s = utils_strv_find_lcs(data, 2); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "2"); + g_free(s); + s = utils_strv_find_lcs(data, 3); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ""); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("/home/user/src/geany/src/stash.c", + "/home/user/src/geany/src/sidebar.c", + "/home/user/src/geany/src/sidebar.h", + "/home/user/src/geany/src/sidebar.h", + "/home/user/src/geany/src/main.c", + "/home/user/src/geany-plugins/addons/src/addons.c", + NULL); + s = utils_strv_find_lcs(data, 4); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/home/user/src/geany/src/s"); + g_free(s); + s = utils_strv_find_lcs(data, 5); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/home/user/src/geany/src/"); + g_free(s); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/home/user/src/geany"); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("/src/a/app-1.2.3/src/lib/module/source.c", + "/src/b/app-2.2.3/src/module/source.c", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/module/source.c"); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("/src/a/app-1.2.3/src/lib/module/", + "/src/b/app-2.2.3/src/module/", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, ".2.3/src/"); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("a123b", "b123c", "c123d", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "123"); + g_free(s); + g_strfreev(data); + + data = utils_strv_new("/usr/local/bin/geany", "/usr/bin/geany", "/home/user/src/geany/src/geany", NULL); + s = utils_strv_find_lcs(data, -1); + g_assert_nonnull(s); + g_assert_cmpstr(s, ==, "/geany"); + g_free(s); + g_strfreev(data); +} + + +/* g_strv_equal is too recent */ +static gboolean strv_eq(gchar **strv1, gchar **strv2) +{ + while(1) { + gchar *s1 = *strv1++; + gchar *s2 = *strv2++; + + if (!s1 && !s2) + return TRUE; + else if (s1 && !s2) + return FALSE; + else if (s2 && !s1) + return FALSE; + else if (!g_str_equal(s1, s2)) + return FALSE; + } +} + +void test_utils_strv_shorten_file_list(void) +{ + gchar **data, **expected, **result; + gchar *empty[] = { NULL }; + + result = utils_strv_shorten_file_list(NULL, 0); + expected = empty; + g_assert_true(strv_eq(result, expected)); + g_strfreev(result); + + data = utils_strv_new("", NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = data; + g_assert_true(strv_eq(result, expected)); + g_strfreev(result); + g_strfreev(data); + + data = utils_strv_new("1", "2", "3", NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = data; + g_assert_true(strv_eq(result, expected)); + g_strfreev(result); + g_strfreev(data); + + data = utils_strv_new("abc", "amn", "axy", NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = data; + g_assert_true(strv_eq(result, expected)); + g_strfreev(result); + g_strfreev(data); + + data = utils_strv_new("abc", "", "axy", NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = data; + g_assert_true(strv_eq(result, expected)); + g_strfreev(result); + g_strfreev(data); + + data = utils_strv_new("22", "23", "33", NULL); + result = utils_strv_shorten_file_list(data, 1); + expected = utils_strv_new("22", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(result); + result = utils_strv_shorten_file_list(data, 2); + expected = utils_strv_new("22", "23", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(result); + result = utils_strv_shorten_file_list(data, 3); + expected = utils_strv_new("22", "23", "33", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(result); + g_strfreev(data); + + data = utils_strv_new("/home/user/src/geany/src/stash.c", + "/home/user/src/geany/src/sidebar.c", + "/home/user/src/geany/src/sidebar.h", + "/home/user/src/geany/src/sidebar.h", + "/home/user/src/geany/src/main.c", + "/home/user/src/geany-plugins/addons/src/addons.c", + NULL); + result = utils_strv_shorten_file_list(data, 4); + expected = utils_strv_new("stash.c", "sidebar.c", "sidebar.h", "sidebar.h", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + result = utils_strv_shorten_file_list(data, 5); + expected = utils_strv_new("stash.c", "sidebar.c", "sidebar.h", "sidebar.h", "main.c", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + result = utils_strv_shorten_file_list(data, -1); + expected = utils_strv_new("geany/src/stash.c", "geany/src/sidebar.c", + "geany/src/sidebar.h", "geany/src/sidebar.h", "geany/src/main.c", + "geany-plugins/addons/src/addons.c", + NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(data); + + data = utils_strv_new("/home/user1/src/geany/src/stash.c", + "/home/user2/src/geany/src/sidebar.c", + "/home/user3/src/geany/src/sidebar.h", + "/home/user4/src/geany/src/sidebar.h", + "/home/user5/src/geany/src/main.c", + NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = utils_strv_new("user1/.../stash.c", + "user2/.../sidebar.c", + "user3/.../sidebar.h", + "user4/.../sidebar.h", + "user5/.../main.c", + NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(result); + g_strfreev(data); + + data = utils_strv_new("/aaa/bbb/cc/ccccc/ddddd", "/aaa/bbb/xxx/yyy/cc/ccccc/ddddd", NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = utils_strv_new("cc/.../ddddd", "xxx/yyy/cc/.../ddddd", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(result); + g_strfreev(data); + + /* This case shows a weakness. It would be better to elipsize "module". Instead, + * nothing is elipsized as the code determines ".2.3/src/" to be the + * longest common substring. Then it reduces it to directory components, so "src" remains. + * This is shorter than the threshold of 5 chars and consequently not elipsized + * + * Plain utils_strv_find_lcs() actually finds /module/source.c, + * but utils_strv_shorten_file_list() calls it without the file name part, so + * ".2.3/src/" is longer than "/module/". This is illustrated in the test + * test_utils_strv_find_lcs() + */ + data = utils_strv_new("/src/a/app-1.2.3/src/lib/module/source.c", + "/src/b/app-2.2.3/src/module/source.c", NULL); + result = utils_strv_shorten_file_list(data, -1); + expected = utils_strv_new("a/app-1.2.3/src/lib/module/source.c", + "b/app-2.2.3/src/module/source.c", NULL); + g_assert_true(strv_eq(result, expected)); + g_strfreev(expected); + g_strfreev(result); + g_strfreev(data); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + UTIL_TEST_ADD("strv_join", test_utils_strv_new); + UTIL_TEST_ADD("strv_find_common_prefix", test_utils_strv_find_common_prefix); + UTIL_TEST_ADD("strv_find_lcs", test_utils_strv_find_lcs); + UTIL_TEST_ADD("strv_shorten_file_list", test_utils_strv_shorten_file_list); + + return g_test_run(); +}
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).