Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2025 Khalid Abu Shawarib.
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * Author: Khalid Abu Shawarib <kas@gnome.org>
7 : : */
8 : :
9 : : #include <gio/gio.h>
10 : :
11 : : static void
12 : 2 : create_files (const GStrv hier)
13 : : {
14 : 2 : g_mkdir_with_parents (g_get_home_dir (), 0700);
15 : :
16 : 10 : for (guint i = 0; hier[i] != NULL; i++)
17 : : {
18 : 8 : GFile *file = g_file_new_build_filename (g_get_home_dir (), hier[i], NULL);
19 : 12 : gboolean is_directory = g_str_has_suffix (hier[i], G_DIR_SEPARATOR_S);
20 : :
21 : 8 : if (is_directory)
22 : 4 : g_file_make_directory (file, NULL, NULL);
23 : : else
24 : : {
25 : 4 : GFileOutputStream *stream = g_file_create (file, G_FILE_CREATE_NONE, NULL, NULL);
26 : :
27 : 4 : g_object_unref (stream);
28 : : }
29 : :
30 : 8 : g_assert_true (g_file_query_exists (file, NULL));
31 : :
32 : 8 : g_object_unref (file);
33 : 4 : }
34 : 2 : }
35 : :
36 : : static GStrv
37 : 12 : prefix_filenames (const gchar *const strings[],
38 : : const gchar *prefix)
39 : : {
40 : 12 : GStrvBuilder *builder = g_strv_builder_new ();
41 : :
42 : 36 : for (guint i = 0; strings[i] != NULL; i++)
43 : 24 : g_strv_builder_take (builder, g_build_filename (prefix, strings[i], NULL));
44 : :
45 : 12 : return g_strv_builder_unref_to_strv (builder);
46 : : }
47 : :
48 : : static int
49 : 32 : strcmp_data (const void *a,
50 : : const void *b,
51 : : void *user_data)
52 : : {
53 : 32 : return strcmp (*((const char * const *) a), *((const char * const *) b));
54 : : }
55 : :
56 : : #define assert_cmpstrv_unsorted(a1, a2) \
57 : : G_STMT_START { \
58 : : const char **_a1 = (const char **) (a1); \
59 : : const char **_a2 = (const char **) (a2); \
60 : : g_sort_array (_a1, g_strv_length ((char **) _a1), sizeof (*_a1), strcmp_data, NULL); \
61 : : g_sort_array (_a2, g_strv_length ((char **) _a2), sizeof (*_a2), strcmp_data, NULL); \
62 : : g_assert_cmpstrv (_a1, _a2); \
63 : : } G_STMT_END
64 : :
65 : : typedef struct
66 : : {
67 : : const gchar *string;
68 : : const gchar *all_completion_suffix;
69 : : const gchar *dirs_completion_suffix;
70 : : const gchar *const all_completions[5];
71 : : const gchar *const dirs_completions[5];
72 : : } FilenameCompleterTestCase;
73 : :
74 : : static void
75 : 2 : run_test_cases (const FilenameCompleterTestCase test_cases[],
76 : : guint len)
77 : : {
78 : 2 : const gchar *base_path = g_get_home_dir ();
79 : :
80 : 8 : for (guint i = 0; i < len; i++)
81 : : {
82 : 6 : GFilenameCompleter *all_completer = g_filename_completer_new ();
83 : 6 : GFilenameCompleter *dirs_completer = g_filename_completer_new ();
84 : : gchar *completion_suffix;
85 : : GStrv all_results_completions, all_expected_completions;
86 : : GStrv dirs_results_completions, dirs_expected_completions;
87 : 6 : gchar *path_to_complete = g_build_filename (base_path, test_cases[i].string, NULL);
88 : 6 : GMainLoop *loop = g_main_loop_new (NULL, FALSE);
89 : :
90 : : /* dirs_only = FALSE */
91 : 9 : g_signal_connect_swapped (all_completer, "got-completion-data",
92 : 3 : G_CALLBACK (g_main_loop_quit), loop);
93 : 6 : g_filename_completer_set_dirs_only (all_completer, FALSE);
94 : 6 : g_strfreev (g_filename_completer_get_completions (all_completer, path_to_complete));
95 : :
96 : 6 : g_main_loop_run (loop);
97 : :
98 : 6 : all_expected_completions = prefix_filenames (test_cases[i].all_completions, base_path);
99 : 6 : all_results_completions = g_filename_completer_get_completions (all_completer, path_to_complete);
100 : 25 : assert_cmpstrv_unsorted (all_expected_completions, all_results_completions);
101 : 6 : g_strfreev (all_expected_completions);
102 : 6 : g_strfreev (all_results_completions);
103 : :
104 : 9 : completion_suffix = g_filename_completer_get_completion_suffix (all_completer,
105 : 3 : path_to_complete);
106 : 6 : g_assert_cmpstr (test_cases[i].all_completion_suffix, ==, completion_suffix);
107 : 6 : g_free (completion_suffix);
108 : :
109 : : /* dirs_only = TRUE */
110 : 9 : g_signal_connect_swapped (dirs_completer, "got-completion-data",
111 : 3 : G_CALLBACK (g_main_loop_quit), loop);
112 : 6 : g_filename_completer_set_dirs_only (dirs_completer, TRUE);
113 : 6 : g_strfreev (g_filename_completer_get_completions (dirs_completer, path_to_complete));
114 : :
115 : 6 : g_main_loop_run (loop);
116 : :
117 : 6 : dirs_expected_completions = prefix_filenames (test_cases[i].dirs_completions, base_path);
118 : 6 : dirs_results_completions = g_filename_completer_get_completions (dirs_completer, path_to_complete);
119 : 17 : assert_cmpstrv_unsorted (dirs_expected_completions, dirs_results_completions);
120 : :
121 : 6 : g_strfreev (dirs_expected_completions);
122 : 6 : g_strfreev (dirs_results_completions);
123 : :
124 : 9 : completion_suffix = g_filename_completer_get_completion_suffix (dirs_completer,
125 : 3 : path_to_complete);
126 : 6 : g_assert_cmpstr (test_cases[i].dirs_completion_suffix, ==, completion_suffix);
127 : 6 : g_free (completion_suffix);
128 : :
129 : 6 : g_object_unref (all_completer);
130 : 6 : g_object_unref (dirs_completer);
131 : 6 : g_free (path_to_complete);
132 : 6 : g_main_loop_unref (loop);
133 : 3 : }
134 : 2 : }
135 : :
136 : : static void
137 : 2 : test_completions (void)
138 : : {
139 : 2 : const GStrv files_hier = (char *[]){
140 : : "file_1",
141 : : "file_2",
142 : : "folder_1" G_DIR_SEPARATOR_S,
143 : : "folder_2" G_DIR_SEPARATOR_S,
144 : : NULL
145 : : };
146 : 2 : const FilenameCompleterTestCase test_cases[] = {
147 : : {
148 : : "f",
149 : : "",
150 : : "older_",
151 : : { "file_1",
152 : : "file_2",
153 : : "folder_1" G_DIR_SEPARATOR_S,
154 : : "folder_2" G_DIR_SEPARATOR_S,
155 : : NULL },
156 : : { "folder_1" G_DIR_SEPARATOR_S,
157 : : "folder_2" G_DIR_SEPARATOR_S,
158 : : NULL },
159 : : },
160 : :
161 : : {
162 : : "fi",
163 : : "le_",
164 : : NULL,
165 : : { "file_1",
166 : : "file_2",
167 : : NULL },
168 : : { NULL },
169 : : },
170 : :
171 : : {
172 : : "fo",
173 : : "lder_",
174 : : "lder_",
175 : : { "folder_1" G_DIR_SEPARATOR_S,
176 : : "folder_2" G_DIR_SEPARATOR_S,
177 : : NULL },
178 : : { "folder_1" G_DIR_SEPARATOR_S,
179 : : "folder_2" G_DIR_SEPARATOR_S,
180 : : NULL },
181 : : },
182 : : };
183 : :
184 : 2 : create_files (files_hier);
185 : :
186 : 2 : run_test_cases (test_cases, G_N_ELEMENTS (test_cases));
187 : 2 : }
188 : :
189 : : int
190 : 2 : main (int argc, char *argv[])
191 : : {
192 : 2 : g_setenv ("LC_ALL", "C", TRUE);
193 : :
194 : 2 : g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
195 : :
196 : 2 : g_test_add_func ("/filenamecompleter/basic", test_completions);
197 : :
198 : 2 : return g_test_run ();
199 : : }
|