[geany/geany] 64a32d: tests: unit test for some util strv functions

Thomas Martitz git-noreply at xxxxx
Fri Sep 20 20:58:25 UTC 2019


Branch:      refs/heads/master
Author:      Thomas Martitz <kugel at rockbox.org>
Committer:   Thomas Martitz <kugel at rockbox.org>
Date:        Fri, 20 Sep 2019 20:58:25 UTC
Commit:      64a32db5e1d202b9055dd90dab335f7c2afa62c0
             https://github.com/geany/geany/commit/64a32db5e1d202b9055dd90dab335f7c2afa62c0

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).


More information about the Commits mailing list