1 /* GLib testing framework examples and tests
2 * Copyright (C) 2008 Red Hat, Inc.
3 * Authors: Tomas Bzatek <tbzatek@redhat.com>
5 * This work is provided "as is"; redistribution and modification
6 * in whole or in part, in any medium, physical or electronic is
7 * permitted without restriction.
9 * This work is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * In no event shall the authors or contributors be liable for any
14 * direct, indirect, incidental, special, exemplary, or consequential
15 * damages (including, but not limited to, procurement of substitute
16 * goods or services; loss of use, data, or profits; or business
17 * interruption) however caused and on any theory of liability, whether
18 * in contract, strict liability, or tort (including negligence or
19 * otherwise) arising in any way out of the use of this software, even
20 * if advised of the possibility of such damage.
25 #include <glib/glib.h>
31 #include <glib/gstdio.h>
36 #define TEST_NAME "Prilis zlutoucky kun"
37 #define TEST_DISPLAY_NAME "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"
38 #define TEST_SIZE 0xFFFFFFF0
41 test_assigned_values (GFileInfo
*info
)
43 const char *name
, *display_name
, *mistake
;
47 /* Test for attributes presence */
48 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_NAME
) == TRUE
);
49 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
) == TRUE
);
50 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
) == TRUE
);
51 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME
) == FALSE
);
53 /* Retrieve data back and compare */
55 name
= g_file_info_get_attribute_byte_string (info
, G_FILE_ATTRIBUTE_STANDARD_NAME
);
56 display_name
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
);
57 mistake
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME
);
58 size
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
);
59 type
= g_file_info_get_file_type (info
);
61 g_assert_cmpstr (name
, ==, TEST_NAME
);
62 g_assert_cmpstr (display_name
, ==, TEST_DISPLAY_NAME
);
63 g_assert (mistake
== NULL
);
64 g_assert_cmpint (size
, ==, TEST_SIZE
);
65 g_assert_cmpstr (name
, ==, g_file_info_get_name (info
));
66 g_assert_cmpstr (display_name
, ==, g_file_info_get_display_name (info
));
67 g_assert_cmpint (size
, ==, g_file_info_get_size (info
) );
68 g_assert_cmpint (type
, ==, G_FILE_TYPE_DIRECTORY
);
74 test_g_file_info (void)
80 GFileAttributeMatcher
*matcher
;
82 info
= g_file_info_new ();
84 /* Test for empty instance */
85 attr_list
= g_file_info_list_attributes (info
, NULL
);
86 g_assert (attr_list
!= NULL
);
87 g_assert (*attr_list
== NULL
);
88 g_strfreev (attr_list
);
90 g_file_info_set_attribute_byte_string (info
, G_FILE_ATTRIBUTE_STANDARD_NAME
, TEST_NAME
);
91 g_file_info_set_attribute_string (info
, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
, TEST_DISPLAY_NAME
);
92 g_file_info_set_attribute_uint64 (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
, TEST_SIZE
);
93 g_file_info_set_file_type (info
, G_FILE_TYPE_DIRECTORY
);
95 /* The attr list should not be empty now */
96 attr_list
= g_file_info_list_attributes (info
, NULL
);
97 g_assert (attr_list
!= NULL
);
98 g_assert (*attr_list
!= NULL
);
99 g_strfreev (attr_list
);
101 test_assigned_values (info
);
104 info_dup
= g_file_info_dup (info
);
105 g_assert (info_dup
!= NULL
);
106 test_assigned_values (info_dup
);
108 info_copy
= g_file_info_new ();
109 g_file_info_copy_into (info_dup
, info_copy
);
110 g_assert (info_copy
!= NULL
);
111 test_assigned_values (info_copy
);
113 /* Test remove attribute */
114 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
) == FALSE
);
115 g_file_info_set_attribute_int32 (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
, 10);
116 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
) == TRUE
);
118 g_assert (g_file_info_get_attribute_type (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
) == G_FILE_ATTRIBUTE_TYPE_INT32
);
119 g_assert (g_file_info_get_attribute_status (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
) != G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING
);
121 g_file_info_remove_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
);
122 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
) == FALSE
);
123 g_assert (g_file_info_get_attribute_type (info
, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER
) == G_FILE_ATTRIBUTE_TYPE_INVALID
);
125 matcher
= g_file_attribute_matcher_new (G_FILE_ATTRIBUTE_STANDARD_NAME
","
126 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
);
128 g_assert (g_file_attribute_matcher_matches (matcher
, G_FILE_ATTRIBUTE_STANDARD_NAME
) == TRUE
);
129 g_assert (g_file_attribute_matcher_matches_only (matcher
, G_FILE_ATTRIBUTE_STANDARD_NAME
) == FALSE
);
130 g_assert (g_file_attribute_matcher_matches (matcher
, G_FILE_ATTRIBUTE_STANDARD_SIZE
) == FALSE
);
132 g_file_info_set_attribute_mask (info
, matcher
);
133 g_file_attribute_matcher_unref (matcher
);
135 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
) == FALSE
);
136 g_assert (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_NAME
) == TRUE
);
138 g_object_unref (info
);
139 g_object_unref (info_dup
);
140 g_object_unref (info_copy
);
145 test_internal_enhanced_stdio (void)
150 wchar_t *tmp_dir_root_w
;
157 GStatBuf statbuf_p0
, statbuf_p1
, statbuf_ps
;
158 GFile
*gf_p0
, *gf_p1
, *gf_ps
;
159 GFileInfo
*fi_p0
, *fi_p1
, *fi_ps
;
160 guint64 size_p0
, alsize_p0
, size_ps
, alsize_ps
;
163 volatile guint64 time_p0
;
165 wchar_t *programdata_dir_w
;
166 wchar_t *users_dir_w
;
167 static const GUID folder_id_programdata
=
168 { 0x62AB5D82, 0xFDC1, 0x4DC3, { 0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97 } };
169 static const GUID folder_id_users
=
170 { 0x0762D272, 0xC50A, 0x4BB0, { 0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80 } };
172 programdata_dir_w
= NULL
;
173 SHGetKnownFolderPath (&folder_id_programdata
, 0, NULL
, &programdata_dir_w
);
176 SHGetKnownFolderPath (&folder_id_users
, 0, NULL
, &users_dir_w
);
178 if (programdata_dir_w
!= NULL
&& users_dir_w
!= NULL
)
183 GFile
*gf_programdata
, *gf_allusers
;
184 GFileInfo
*fi_programdata
, *fi_allusers
, *fi_allusers_target
;
185 GFileType ft_allusers
;
186 GFileType ft_allusers_target
;
187 GFileType ft_programdata
;
188 gboolean allusers_is_symlink
;
189 const gchar
*id_allusers
;
190 const gchar
*id_allusers_target
;
191 const gchar
*id_programdata
;
192 const gchar
*allusers_target
;
195 programdata
= g_utf16_to_utf8 (programdata_dir_w
, -1, NULL
, NULL
, NULL
);
196 g_assert_nonnull (programdata
);
198 users_dir
= g_utf16_to_utf8 (users_dir_w
, -1, NULL
, NULL
, NULL
);
199 g_assert_nonnull (users_dir
);
200 /* "C:/Users/All Users" is a known directory symlink
201 * for "C:/ProgramData".
203 allusers
= g_build_filename (users_dir
, "All Users", NULL
);
204 g_assert_nonnull (allusers
);
206 /* We don't test g_stat() and g_lstat() on these directories,
207 * because it is pointless - there's no way to tell that these
208 * functions behave correctly in this case
209 * (st_ino is useless, so we can't tell apart g_stat() and g_lstat()
210 * results; st_mode is also useless as it does not support S_ISLNK;
211 * and these directories have no interesting properties other
212 * than [not] being symlinks).
214 gf_programdata
= g_file_new_for_path (programdata
);
215 gf_allusers
= g_file_new_for_path (allusers
);
217 fi_programdata
= g_file_query_info (gf_programdata
,
218 G_FILE_ATTRIBUTE_ID_FILE
","
219 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
220 G_FILE_QUERY_INFO_NONE
,
223 fi_allusers_target
= g_file_query_info (gf_allusers
,
224 G_FILE_ATTRIBUTE_ID_FILE
","
225 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
226 G_FILE_QUERY_INFO_NONE
,
229 fi_allusers
= g_file_query_info (gf_allusers
,
230 G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET
","
231 G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK
","
232 G_FILE_ATTRIBUTE_ID_FILE
","
233 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
234 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
,
237 g_assert (g_file_info_has_attribute (fi_programdata
, G_FILE_ATTRIBUTE_ID_FILE
));
238 g_assert (g_file_info_has_attribute (fi_programdata
, G_FILE_ATTRIBUTE_STANDARD_TYPE
));
240 g_assert (g_file_info_has_attribute (fi_allusers_target
, G_FILE_ATTRIBUTE_ID_FILE
));
241 g_assert (g_file_info_has_attribute (fi_allusers_target
, G_FILE_ATTRIBUTE_STANDARD_TYPE
));
243 g_assert (g_file_info_has_attribute (fi_allusers
, G_FILE_ATTRIBUTE_ID_FILE
));
244 g_assert (g_file_info_has_attribute (fi_allusers
, G_FILE_ATTRIBUTE_STANDARD_TYPE
));
245 g_assert (g_file_info_has_attribute (fi_allusers
, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK
));
246 g_assert (g_file_info_has_attribute (fi_allusers
, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET
));
248 ft_allusers
= g_file_info_get_file_type (fi_allusers
);
249 ft_allusers_target
= g_file_info_get_file_type (fi_allusers_target
);
250 ft_programdata
= g_file_info_get_file_type (fi_programdata
);
252 g_assert (ft_allusers
== G_FILE_TYPE_SYMBOLIC_LINK
);
253 g_assert (ft_allusers_target
== G_FILE_TYPE_DIRECTORY
);
254 g_assert (ft_programdata
== G_FILE_TYPE_DIRECTORY
);
256 allusers_is_symlink
= g_file_info_get_attribute_boolean (fi_allusers
, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK
);
258 g_assert_true (allusers_is_symlink
);
260 id_allusers
= g_file_info_get_attribute_string (fi_allusers
, G_FILE_ATTRIBUTE_ID_FILE
);
261 id_allusers_target
= g_file_info_get_attribute_string (fi_allusers_target
, G_FILE_ATTRIBUTE_ID_FILE
);
262 id_programdata
= g_file_info_get_attribute_string (fi_programdata
, G_FILE_ATTRIBUTE_ID_FILE
);
264 g_assert_cmpstr (id_allusers_target
, ==, id_programdata
);
265 g_assert_cmpstr (id_allusers
, !=, id_programdata
);
267 allusers_target
= g_file_info_get_symlink_target (fi_allusers
);
269 g_assert_true (g_str_has_suffix (allusers_target
, "ProgramData"));
271 g_object_unref (fi_allusers
);
272 g_object_unref (fi_allusers_target
);
273 g_object_unref (fi_programdata
);
274 g_object_unref (gf_allusers
);
275 g_object_unref (gf_programdata
);
279 g_free (programdata
);
282 if (programdata_dir_w
)
283 CoTaskMemFree (programdata_dir_w
);
286 CoTaskMemFree (users_dir_w
);
288 tmp_dir
= g_dir_make_tmp ("glib_stdio_testXXXXXX", NULL
);
289 g_assert_nonnull (tmp_dir
);
291 /* Technically, this isn't necessary - we already assume NTFS, because of
292 * symlink support, and NTFS also supports sparse files. Still, given
293 * the amount of unusual I/O APIs called in this test, checking for
294 * sparse file support of the filesystem where temp directory is
295 * doesn't seem to be out of place.
298 tmp_dir_root
= g_strdup (tmp_dir
);
299 /* We need "C:\\" or "C:/", with a trailing [back]slash */
300 for (c
= tmp_dir_root
; c
&& c
[0] && c
[1]; c
++)
306 tmp_dir_root_w
= g_utf8_to_utf16 (tmp_dir_root
, -1, NULL
, NULL
, NULL
);
307 g_assert_nonnull (tmp_dir_root_w
);
308 g_free (tmp_dir_root
);
309 g_assert_true (GetVolumeInformationW (tmp_dir_root_w
, NULL
, 0, NULL
, NULL
, &fsflags
, NULL
, 0));
310 g_free (tmp_dir_root_w
);
311 try_sparse
= (fsflags
& FILE_SUPPORTS_SPARSE_FILES
) == FILE_SUPPORTS_SPARSE_FILES
;
313 p0
= g_build_filename (tmp_dir
, "zool", NULL
);
314 p1
= g_build_filename (tmp_dir
, "looz", NULL
);
315 ps
= g_build_filename (tmp_dir
, "sparse", NULL
);
319 FILE_SET_SPARSE_BUFFER ssb
;
320 FILE_ZERO_DATA_INFORMATION zdi
;
324 f
= g_fopen (ps
, "wb");
325 g_assert_nonnull (f
);
327 h
= (HANDLE
) _get_osfhandle (fileno (f
));
328 g_assert (h
!= INVALID_HANDLE_VALUE
);
330 ssb
.SetSparse
= TRUE
;
331 g_assert_true (DeviceIoControl (h
,
334 NULL
, 0, NULL
, NULL
));
336 /* Make it a sparse file that starts with 4GBs of zeros */
337 zdi
.FileOffset
.QuadPart
= 0;
338 zdi
.BeyondFinalZero
.QuadPart
= 0xFFFFFFFFULL
+ 1;
339 g_assert_true (DeviceIoControl (h
,
342 NULL
, 0, NULL
, NULL
));
344 /* Let's not keep this seemingly 4GB monster around
345 * longer than we absolutely need to. Do all operations
346 * without assertions, then remove the file immediately.
348 _fseeki64 (f
, 0xFFFFFFFFULL
, SEEK_SET
);
349 fprintf (f
, "Hello 4GB World!");
353 memset (&statbuf_ps
, 0, sizeof (statbuf_ps
));
355 g_stat (ps
, &statbuf_ps
);
357 gf_ps
= g_file_new_for_path (ps
);
359 fi_ps
= g_file_query_info (gf_ps
,
360 G_FILE_ATTRIBUTE_STANDARD_SIZE
","
361 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
,
362 G_FILE_QUERY_INFO_NONE
,
367 g_assert (g_file_info_has_attribute (fi_ps
, G_FILE_ATTRIBUTE_STANDARD_SIZE
));
368 g_assert (g_file_info_has_attribute (fi_ps
, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
));
370 size_ps
= g_file_info_get_attribute_uint64 (fi_ps
, G_FILE_ATTRIBUTE_STANDARD_SIZE
);
371 alsize_ps
= g_file_info_get_attribute_uint64 (fi_ps
, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
);
373 /* allocated size should small (usually - size of the FS cluster,
374 * let's assume it's less than 1 gigabyte),
375 * size should be more than 4 gigabytes,
376 * st_size should not exceed its 0xFFFFFFFF 32-bit limit,
377 * and should be nonzero (this also detects a failed g_stat() earlier).
379 g_assert_cmpuint (alsize_ps
, <, 0x40000000);
380 g_assert_cmpuint (size_ps
, >, G_GUINT64_CONSTANT (0xFFFFFFFF));
381 g_assert_cmpuint (statbuf_ps
.st_size
, >, 0);
382 g_assert_cmpuint (statbuf_ps
.st_size
, <=, 0xFFFFFFFF);
384 g_object_unref (fi_ps
);
385 g_object_unref (gf_ps
);
388 /* Wa-a-ay past 02/07/2106 @ 6:28am (UTC),
389 * which is the date corresponding to 0xFFFFFFFF + 1.
390 * This is easier to check than Y2038 (0x80000000 + 1),
391 * since there's no need to worry about signedness this way.
399 st
.wMilliseconds
= 0;
401 g_assert_true (SystemTimeToFileTime (&st
, &ft
));
403 f
= g_fopen (p0
, "w");
404 g_assert_nonnull (f
);
406 h
= (HANDLE
) _get_osfhandle (fileno (f
));
407 g_assert (h
!= INVALID_HANDLE_VALUE
);
412 g_assert_true (SetFileTime (h
, &ft
, &ft
, &ft
));
416 f
= g_fopen (p1
, "w");
417 g_assert_nonnull (f
);
421 memset (&statbuf_p0
, 0, sizeof (statbuf_p0
));
422 memset (&statbuf_p1
, 0, sizeof (statbuf_p1
));
424 g_assert_cmpint (g_stat (p0
, &statbuf_p0
), ==, 0);
425 g_assert_cmpint (g_stat (p1
, &statbuf_p1
), ==, 0);
427 gf_p0
= g_file_new_for_path (p0
);
428 gf_p1
= g_file_new_for_path (p1
);
430 fi_p0
= g_file_query_info (gf_p0
,
431 G_FILE_ATTRIBUTE_STANDARD_SIZE
","
432 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
","
433 G_FILE_ATTRIBUTE_ID_FILE
","
434 G_FILE_ATTRIBUTE_TIME_MODIFIED
,
435 G_FILE_QUERY_INFO_NONE
,
438 fi_p1
= g_file_query_info (gf_p1
,
439 G_FILE_ATTRIBUTE_STANDARD_SIZE
","
440 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
","
441 G_FILE_ATTRIBUTE_ID_FILE
","
442 G_FILE_ATTRIBUTE_TIME_MODIFIED
,
443 G_FILE_QUERY_INFO_NONE
,
446 g_assert (g_file_info_has_attribute (fi_p0
, G_FILE_ATTRIBUTE_STANDARD_SIZE
));
447 g_assert (g_file_info_has_attribute (fi_p0
, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
));
448 g_assert (g_file_info_has_attribute (fi_p0
, G_FILE_ATTRIBUTE_ID_FILE
));
449 g_assert (g_file_info_has_attribute (fi_p0
, G_FILE_ATTRIBUTE_TIME_MODIFIED
));
451 g_assert (g_file_info_has_attribute (fi_p1
, G_FILE_ATTRIBUTE_STANDARD_SIZE
));
452 g_assert (g_file_info_has_attribute (fi_p1
, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
));
453 g_assert (g_file_info_has_attribute (fi_p1
, G_FILE_ATTRIBUTE_ID_FILE
));
454 g_assert (g_file_info_has_attribute (fi_p1
, G_FILE_ATTRIBUTE_TIME_MODIFIED
));
456 size_p0
= g_file_info_get_attribute_uint64 (fi_p0
, G_FILE_ATTRIBUTE_STANDARD_SIZE
);
457 alsize_p0
= g_file_info_get_attribute_uint64 (fi_p0
, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE
);
459 /* size should be 1, allocated size should be something else
460 * (could be 0 or the size of the FS cluster, but never 1).
462 g_assert_cmpuint (size_p0
, ==, statbuf_p0
.st_size
);
463 g_assert_cmpuint (size_p0
, ==, 1);
464 g_assert_cmpuint (alsize_p0
, !=, size_p0
);
466 id_p0
= g_file_info_get_attribute_string (fi_p0
, G_FILE_ATTRIBUTE_ID_FILE
);
467 id_p1
= g_file_info_get_attribute_string (fi_p1
, G_FILE_ATTRIBUTE_ID_FILE
);
469 /* st_ino from W32 stat() is useless for file identification.
470 * It will be either 0, or it will be the same for both files.
472 g_assert (statbuf_p0
.st_ino
== statbuf_p1
.st_ino
);
473 g_assert_cmpstr (id_p0
, !=, id_p1
);
475 time_p0
= g_file_info_get_attribute_uint64 (fi_p0
, G_FILE_ATTRIBUTE_TIME_MODIFIED
);
477 /* Check that GFileInfo doesn't suffer from Y2106 problem.
478 * Don't check stat(), as its contents may vary depending on
479 * the host platform architecture
480 * (time fields are 32-bit on 32-bit Windows,
481 * and 64-bit on 64-bit Windows, usually),
482 * so it *can* pass this test in some cases.
484 g_assert (time_p0
> G_GUINT64_CONSTANT (0xFFFFFFFF));
486 g_object_unref (fi_p0
);
487 g_object_unref (fi_p1
);
488 g_object_unref (gf_p0
);
489 g_object_unref (gf_p1
);
503 g_test_init (&argc
, &argv
, NULL
);
505 g_test_add_func ("/g-file-info/test_g_file_info", test_g_file_info
);
507 g_test_add_func ("/g-file-info/internal-enhanced-stdio", test_internal_enhanced_stdio
);