1 /* SPDX-FileCopyrightText: 2016-2020 - Sébastien Wilmet <swilmet@gnome.org>
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 */
4
5 #include "config.h"
6 #include <tepl/tepl.h>
7 #include <glib/gi18n-lib.h>
8 #include "tepl-test-utils.h"
9
10 static void
check_short_name(TeplFile * file,const gchar * expected_short_name)11 check_short_name (TeplFile *file,
12 const gchar *expected_short_name)
13 {
14 gchar *received_short_name;
15
16 received_short_name = tepl_file_get_short_name (file);
17 g_assert_cmpstr (received_short_name, ==, expected_short_name);
18 g_free (received_short_name);
19 }
20
21 static void
check_short_name_is_untitled_file_number(TeplFile * file,gint untitled_number)22 check_short_name_is_untitled_file_number (TeplFile *file,
23 gint untitled_number)
24 {
25 gchar *expected_short_name;
26
27 /* For the translation it needs to be the exact same string as in the
28 * TeplFile implementation, to be able to run the unit test with any
29 * locale.
30 */
31 expected_short_name = g_strdup_printf (_("Untitled File %d"), untitled_number);
32 check_short_name (file, expected_short_name);
33 g_free (expected_short_name);
34 }
35
36 static void
test_untitled_files(void)37 test_untitled_files (void)
38 {
39 TeplFile *file1;
40 TeplFile *file2;
41 TeplFile *file3;
42 GFile *location;
43
44 file1 = tepl_file_new ();
45 check_short_name_is_untitled_file_number (file1, 1);
46
47 file2 = tepl_file_new ();
48 check_short_name_is_untitled_file_number (file2, 2);
49
50 /* Release an untitled number by destroying a file. */
51 g_object_unref (file1);
52 check_short_name_is_untitled_file_number (file2, 2); // still the same.
53 file1 = tepl_file_new ();
54 check_short_name_is_untitled_file_number (file1, 1);
55
56 /* Release an untitled number by setting a location. */
57 location = g_file_new_for_path ("location");
58 tepl_file_set_location (file1, location);
59 check_short_name_is_untitled_file_number (file2, 2); // still the same.
60 file3 = tepl_file_new ();
61 check_short_name_is_untitled_file_number (file3, 1);
62
63 /* Reset location to NULL. */
64 tepl_file_set_location (file1, NULL);
65 check_short_name_is_untitled_file_number (file1, 3);
66
67 g_object_unref (file1);
68 g_object_unref (file2);
69 g_object_unref (file3);
70 g_object_unref (location);
71 }
72
73 static void
test_short_name(void)74 test_short_name (void)
75 {
76 TeplFile *file;
77 GFile *location;
78 TeplWaitSignalData *data;
79 GError *error = NULL;
80
81 location = g_file_new_build_filename (g_get_tmp_dir (), "tepl-test-file", NULL);
82
83 /* Get the fallback short-name, for a file that doesn't exist. */
84 g_file_delete (location, NULL, &error);
85 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
86 {
87 g_clear_error (&error);
88 }
89 g_assert_no_error (error);
90
91 file = tepl_file_new ();
92 data = _tepl_test_utils_wait_signal_setup (G_OBJECT (file), "notify::short-name");
93 tepl_file_set_location (file, location);
94 _tepl_test_utils_wait_signal (data);
95 check_short_name (file, "tepl-test-file");
96 g_object_unref (file);
97
98 /* Get the display-name for a local file (so the file must exist). */
99 _tepl_test_utils_set_file_content (location, "file content");
100
101 file = tepl_file_new ();
102 data = _tepl_test_utils_wait_signal_setup (G_OBJECT (file), "notify::short-name");
103 tepl_file_set_location (file, location);
104 _tepl_test_utils_wait_signal (data);
105 check_short_name (file, "tepl-test-file");
106 g_object_unref (file);
107 g_object_unref (location);
108
109 /* Test the special case for a remote location that has no parent GFile. */
110 location = g_file_new_for_uri ("https://swilmet.be");
111 file = tepl_file_new ();
112 data = _tepl_test_utils_wait_signal_setup (G_OBJECT (file), "notify::short-name");
113 tepl_file_set_location (file, location);
114 _tepl_test_utils_wait_signal (data);
115 check_short_name (file, "https://swilmet.be");
116 g_object_unref (file);
117 g_object_unref (location);
118
119 // It's not really important if the trailing slash is still present or
120 // not in the short-name, but test it anyway. The important thing is to
121 // have the https://swilmet.be prefix, with an optional trailing slash.
122 location = g_file_new_for_uri ("https://swilmet.be/");
123 file = tepl_file_new ();
124 data = _tepl_test_utils_wait_signal_setup (G_OBJECT (file), "notify::short-name");
125 tepl_file_set_location (file, location);
126 _tepl_test_utils_wait_signal (data);
127 check_short_name (file, "https://swilmet.be/");
128 g_object_unref (file);
129 g_object_unref (location);
130 }
131
132 #if 0
133 static void
134 sleep_for_one_second (void)
135 {
136 g_usleep (G_USEC_PER_SEC);
137 }
138
139 static void
140 load_cb (GObject *source_object,
141 GAsyncResult *result,
142 gpointer user_data)
143 {
144 TeplFileLoader *loader = TEPL_FILE_LOADER (source_object);
145 GError *error = NULL;
146
147 tepl_file_loader_load_finish (loader, result, &error);
148 g_assert_no_error (error);
149
150 gtk_main_quit ();
151 }
152
153 static void
154 load (TeplBuffer *buffer)
155 {
156 TeplFile *file;
157 TeplFileLoader *loader;
158
159 file = tepl_buffer_get_file (buffer);
160
161 loader = tepl_file_loader_new (buffer, file);
162 tepl_file_loader_load_async (loader,
163 G_PRIORITY_DEFAULT,
164 NULL, /* cancellable */
165 NULL, NULL, NULL, /* progress cb */
166 load_cb,
167 NULL);
168
169 gtk_main ();
170 g_object_unref (loader);
171 }
172
173 static void
174 save_cb (GObject *source_object,
175 GAsyncResult *result,
176 gpointer user_data)
177 {
178 TeplFileSaver *saver = TEPL_FILE_SAVER (source_object);
179 gboolean expect_externally_modified_error = GPOINTER_TO_INT (user_data);
180 GError *error = NULL;
181
182 tepl_file_saver_save_finish (saver, result, &error);
183 if (expect_externally_modified_error)
184 {
185 g_assert_true (g_error_matches (error,
186 TEPL_FILE_SAVER_ERROR,
187 TEPL_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED));
188 g_clear_error (&error);
189 }
190 else
191 {
192 g_assert_no_error (error);
193 }
194
195 gtk_main_quit ();
196 }
197
198 static void
199 save (TeplBuffer *buffer,
200 gboolean expect_externally_modified_error)
201 {
202 TeplFile *file;
203 TeplFileSaver *saver;
204
205 file = tepl_buffer_get_file (buffer);
206
207 saver = tepl_file_saver_new (buffer, file);
208 tepl_file_saver_save_async (saver,
209 G_PRIORITY_DEFAULT,
210 NULL, /* cancellable */
211 NULL, NULL, NULL, /* progress cb */
212 save_cb,
213 GINT_TO_POINTER (expect_externally_modified_error));
214
215 gtk_main ();
216
217 if (expect_externally_modified_error)
218 {
219 expect_externally_modified_error = FALSE;
220
221 tepl_file_saver_set_flags (saver, TEPL_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME);
222 tepl_file_saver_save_async (saver,
223 G_PRIORITY_DEFAULT,
224 NULL, /* cancellable */
225 NULL, NULL, NULL, /* progress cb */
226 save_cb,
227 GINT_TO_POINTER (expect_externally_modified_error));
228
229 gtk_main ();
230 }
231
232 g_object_unref (saver);
233 }
234
235 static void
236 save_as (TeplBuffer *buffer,
237 GFile *new_location)
238 {
239 TeplFile *file;
240 TeplFileSaver *saver;
241 gboolean expect_externally_modified_error = FALSE;
242
243 file = tepl_buffer_get_file (buffer);
244
245 saver = tepl_file_saver_new_with_target (buffer, file, new_location);
246 tepl_file_saver_save_async (saver,
247 G_PRIORITY_DEFAULT,
248 NULL, /* cancellable */
249 NULL, NULL, NULL, /* progress cb */
250 save_cb,
251 GINT_TO_POINTER (expect_externally_modified_error));
252
253 gtk_main ();
254 g_object_unref (saver);
255 }
256
257 static void
258 test_externally_modified (void)
259 {
260 TeplBuffer *buffer;
261 TeplFile *file;
262 gchar *path;
263 gchar *new_path;
264 GFile *location;
265 GFile *new_location;
266 GError *error = NULL;
267
268 buffer = tepl_buffer_new ();
269 file = tepl_buffer_get_file (buffer);
270
271 /* With NULL location */
272 g_assert_true (!tepl_file_is_externally_modified (file));
273 tepl_file_check_file_on_disk (file);
274 g_assert_true (!tepl_file_is_externally_modified (file));
275
276 /* Set location, but not yet loaded or saved */
277 path = g_build_filename (g_get_tmp_dir (), "tepl-test-file", NULL);
278 g_file_set_contents (path, "a", -1, &error);
279 g_assert_no_error (error);
280
281 location = g_file_new_for_path (path);
282 tepl_file_set_location (file, location);
283 g_assert_true (!tepl_file_is_externally_modified (file));
284 tepl_file_check_file_on_disk (file);
285 g_assert_true (!tepl_file_is_externally_modified (file));
286
287 /* Load */
288 load (buffer);
289 g_assert_true (!tepl_file_is_externally_modified (file));
290 tepl_file_check_file_on_disk (file);
291 g_assert_true (!tepl_file_is_externally_modified (file));
292
293 /* Save */
294 save (buffer, FALSE);
295 g_assert_true (!tepl_file_is_externally_modified (file));
296 tepl_file_check_file_on_disk (file);
297 g_assert_true (!tepl_file_is_externally_modified (file));
298
299 /* Modify externally and then save.
300 * Sleep one second to force the timestamp/etag to change.
301 */
302 sleep_for_one_second ();
303 g_file_set_contents (path, "b", -1, &error);
304 g_assert_no_error (error);
305 tepl_file_check_file_on_disk (file);
306 g_assert_true (tepl_file_is_externally_modified (file));
307
308 save (buffer, TRUE);
309 g_assert_true (!tepl_file_is_externally_modified (file));
310 tepl_file_check_file_on_disk (file);
311 g_assert_true (!tepl_file_is_externally_modified (file));
312
313 /* Modify externally and then load */
314 sleep_for_one_second ();
315 g_file_set_contents (path, "c", -1, &error);
316 g_assert_no_error (error);
317 tepl_file_check_file_on_disk (file);
318 g_assert_true (tepl_file_is_externally_modified (file));
319
320 load (buffer);
321 g_assert_true (!tepl_file_is_externally_modified (file));
322 tepl_file_check_file_on_disk (file);
323 g_assert_true (!tepl_file_is_externally_modified (file));
324
325 /* Modify externally and then save as */
326 sleep_for_one_second ();
327 g_file_set_contents (path, "d", -1, &error);
328 g_assert_no_error (error);
329 tepl_file_check_file_on_disk (file);
330 g_assert_true (tepl_file_is_externally_modified (file));
331
332 new_path = g_build_filename (g_get_tmp_dir (), "tepl-test-file-2", NULL);
333 g_file_set_contents (new_path, "e", -1, &error);
334 g_assert_no_error (error);
335
336 new_location = g_file_new_for_path (new_path);
337 save_as (buffer, new_location);
338 g_assert_true (g_file_equal (new_location, tepl_file_get_location (file)));
339 g_assert_true (!tepl_file_is_externally_modified (file));
340 tepl_file_check_file_on_disk (file);
341 g_assert_true (!tepl_file_is_externally_modified (file));
342
343 /* Modify externally and then save as to same location */
344 sleep_for_one_second ();
345 g_file_set_contents (new_path, "f", -1, &error);
346 g_assert_no_error (error);
347 tepl_file_check_file_on_disk (file);
348 g_assert_true (tepl_file_is_externally_modified (file));
349
350 g_assert_true (g_file_equal (new_location, tepl_file_get_location (file)));
351 save_as (buffer, new_location);
352 g_assert_true (!tepl_file_is_externally_modified (file));
353 tepl_file_check_file_on_disk (file);
354 g_assert_true (!tepl_file_is_externally_modified (file));
355
356 /* Cleanup */
357 g_file_delete (location, NULL, &error);
358 g_assert_no_error (error);
359 g_file_delete (new_location, NULL, &error);
360 g_assert_no_error (error);
361
362 g_free (path);
363 g_free (new_path);
364 g_object_unref (location);
365 g_object_unref (new_location);
366 g_object_unref (buffer);
367 }
368 #endif
369
370 int
main(int argc,char ** argv)371 main (int argc,
372 char **argv)
373 {
374 gtk_test_init (&argc, &argv);
375
376 g_test_add_func ("/file/untitled_files", test_untitled_files);
377 g_test_add_func ("/file/short_name", test_short_name);
378
379 #if 0
380 g_test_add_func ("/file/externally_modified", test_externally_modified);
381 #endif
382
383 return g_test_run ();
384 }
385