PageRenderTime 5ms CodeModel.GetById 5ms app.highlight 89ms RepoModel.GetById 1ms app.codeStats 0ms

/3rd-party/glib-2.16.6/gio/tests/live-g-file.c

https://bitbucket.org/super119/plu2youku
C | 1099 lines | 877 code | 155 blank | 67 comment | 239 complexity | 86cdf83696e7d7ecd8910bc2b6583ae9 MD5 | raw file
   1/* GLib testing framework examples and tests
   2 * Copyright (C) 2008 Red Hat, Inc.
   3 * Authors: Tomas Bzatek <tbzatek@redhat.com>
   4 *
   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.
   8 *
   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.
  12 *
  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.
  21 */
  22
  23#include <glib/gtestutils.h>
  24#include <glib/glib.h>
  25#include <gio/gio.h>
  26#include <stdlib.h>
  27#include <string.h>
  28
  29#define PATTERN_FILE_SIZE	0x10000
  30#define TEST_HANDLE_SPECIAL	TRUE
  31
  32enum StructureExtraFlags
  33{
  34  TEST_DELETE_NORMAL = 1 << 0,
  35  TEST_DELETE_TRASH = 1 << 1,
  36  TEST_DELETE_NON_EMPTY = 1 << 2,
  37  TEST_DELETE_FAILURE = 1 << 3,
  38  TEST_NOT_EXISTS = 1 << 4,
  39  TEST_ENUMERATE_FILE = 1 << 5,
  40  TEST_NO_ACCESS = 1 << 6,
  41  TEST_COPY = 1 << 7,
  42  TEST_MOVE = 1 << 8,
  43  TEST_COPY_ERROR_RECURSE = 1 << 9,
  44  TEST_ALREADY_EXISTS = 1 << 10,
  45  TEST_TARGET_IS_FILE = 1 << 11,
  46  TEST_CREATE = 1 << 12,
  47  TEST_REPLACE = 1 << 13,
  48  TEST_APPEND = 1 << 14,
  49  TEST_OPEN = 1 << 15,
  50  TEST_OVERWRITE = 1 << 16,
  51  TEST_INVALID_SYMLINK = 1 << 17,
  52};
  53
  54struct StructureItem
  55{
  56  const char *filename;
  57  const char *link_to;
  58  GFileType file_type;
  59  GFileCreateFlags create_flags;
  60  guint32 mode;
  61  gboolean handle_special;
  62  enum StructureExtraFlags extra_flags;
  63};
  64
  65#define TEST_DIR_NO_ACCESS		"dir_no-access"
  66#define TEST_DIR_NO_WRITE		"dir_no-write"
  67#define TEST_DIR_TARGET			"dir-target"
  68#define TEST_NAME_NOT_EXISTS	"not_exists"
  69#define TEST_TARGET_FILE		"target-file"
  70
  71
  72static const struct StructureItem sample_struct[] = {
  73/*	 filename				link	file_type				create_flags		mode | handle_special | extra_flags              */
  74    {"dir1",				NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_DELETE_NON_EMPTY | TEST_REPLACE | TEST_OPEN},
  75    {"dir1/subdir",			NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_NONE, 0, 0, TEST_COPY	| TEST_COPY_ERROR_RECURSE | TEST_APPEND},
  76    {"dir2",				NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_MOVE | TEST_CREATE},
  77    {TEST_DIR_TARGET,		NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_COPY_ERROR_RECURSE},
  78    {TEST_DIR_NO_ACCESS,	NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_PRIVATE, S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP + S_IROTH + S_IWOTH, 0, TEST_NO_ACCESS | TEST_OPEN},
  79    {TEST_DIR_NO_WRITE,		NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_PRIVATE, S_IRUSR + S_IXUSR + S_IRGRP + S_IXGRP + S_IROTH + S_IXOTH, 0, 0},
  80    {TEST_TARGET_FILE,		NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OPEN},
  81	{"normal_file",			NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_CREATE | TEST_OVERWRITE},
  82	{"normal_file-symlink",	"normal_file",	G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_COPY | TEST_OPEN},
  83    {"executable_file",		NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, S_IRWXU + S_IRWXG + S_IRWXO, 0, TEST_DELETE_TRASH | TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_REPLACE},
  84    {"private_file",		NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_PRIVATE, 0, 0, TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_APPEND},
  85    {"normal_file2",		NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OVERWRITE | TEST_REPLACE},
  86    {"readonly_file",		NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, S_IRUSR + S_IRGRP + S_IROTH, 0, TEST_DELETE_NORMAL | TEST_OPEN},
  87    {"UTF_p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88",
  88    						NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_CREATE | TEST_OPEN | TEST_OVERWRITE},
  89    {"dir_p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88",
  90    						NULL,	G_FILE_TYPE_DIRECTORY,	G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_CREATE},
  91    {"pattern_file",		NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_COPY | TEST_OPEN | TEST_APPEND},
  92    {TEST_NAME_NOT_EXISTS,	NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_NORMAL | TEST_NOT_EXISTS | TEST_COPY | TEST_OPEN},
  93    {TEST_NAME_NOT_EXISTS,	NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_TRASH | TEST_NOT_EXISTS | TEST_MOVE},
  94    {"not_exists2",			NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_CREATE},
  95    {"not_exists3",			NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_REPLACE},
  96    {"not_exists4",			NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_APPEND},
  97    {"dir_no-execute/file",	NULL,	G_FILE_TYPE_REGULAR,	G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_NORMAL | TEST_DELETE_FAILURE | TEST_NOT_EXISTS | TEST_OPEN},
  98	{"lost_symlink",		"nowhere",	G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_DELETE_NORMAL | TEST_OPEN | TEST_INVALID_SYMLINK},
  99  };
 100
 101static gboolean write_test;
 102static gboolean verbose;
 103static gboolean posix_compat;
 104
 105#define log(msg...) if (verbose)  g_print (msg)
 106
 107static GFile *
 108create_empty_file (GFile * parent, const char *filename,
 109		   GFileCreateFlags create_flags)
 110{
 111  GFile *child;
 112  gboolean res;
 113  GError *error;
 114  GFileOutputStream *outs;
 115
 116  child = g_file_get_child (parent, filename);
 117  g_assert (child != NULL);
 118
 119  error = NULL;
 120  outs = g_file_replace (child, NULL, FALSE, create_flags, NULL, &error);
 121  g_assert (error == NULL);
 122  g_assert (outs != NULL);
 123  error = NULL;
 124  res = g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error);
 125  g_object_unref (outs);
 126  return child;
 127}
 128
 129static GFile *
 130create_empty_dir (GFile * parent, const char *filename)
 131{
 132  GFile *child;
 133  gboolean res;
 134  GError *error;
 135
 136  child = g_file_get_child (parent, filename);
 137  g_assert (child != NULL);
 138  error = NULL;
 139  res = g_file_make_directory (child, NULL, &error);
 140  g_assert_cmpint (res, ==, TRUE);
 141  g_assert (error == NULL);
 142  return child;
 143}
 144
 145static GFile *
 146create_symlink (GFile * parent, const char *filename, const char *points_to)
 147{
 148  GFile *child;
 149  gboolean res;
 150  GError *error;
 151
 152  child = g_file_get_child (parent, filename);
 153  g_assert (child != NULL);
 154  error = NULL;
 155  res = g_file_make_symbolic_link (child, points_to, NULL, &error);
 156  g_assert_cmpint (res, ==, TRUE);
 157  g_assert (error == NULL);
 158  return child;
 159}
 160
 161static void
 162test_create_structure (gconstpointer test_data)
 163{
 164  GFile *root;
 165  GFile *child;
 166  gboolean res;
 167  GError *error;
 168  GFileOutputStream *outs;
 169  GDataOutputStream *outds;
 170  int i;
 171  struct StructureItem item;
 172
 173  g_assert (test_data != NULL);
 174  log ("\n  Going to create testing structure in '%s'...\n",
 175       (char *) test_data);
 176
 177  root = g_file_new_for_commandline_arg ((char *) test_data);
 178  g_assert (root != NULL);
 179
 180  /*  create root directory  */
 181  res = g_file_make_directory (root, NULL, NULL);
 182  /*  don't care about errors here  */
 183
 184  /*  create any other items  */
 185  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 186    {
 187      item = sample_struct[i];
 188      if ((item.handle_special)
 189	  || ((!posix_compat)
 190	      && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)))
 191	continue;
 192
 193      child = NULL;
 194      switch (item.file_type)
 195	{
 196	case G_FILE_TYPE_REGULAR:
 197	  log ("    Creating file '%s'...\n", item.filename);
 198	  child = create_empty_file (root, item.filename, item.create_flags);
 199	  break;
 200	case G_FILE_TYPE_DIRECTORY:
 201	  log ("    Creating directory '%s'...\n", item.filename);
 202	  child = create_empty_dir (root, item.filename);
 203	  break;
 204	case G_FILE_TYPE_SYMBOLIC_LINK:
 205	  log ("    Creating symlink '%s' --> '%s'...\n", item.filename,
 206	       item.link_to);
 207	  child = create_symlink (root, item.filename, item.link_to);
 208	  break;
 209	default:
 210	  break;
 211	}
 212      g_assert (child != NULL);
 213
 214      if ((item.mode > 0) && (posix_compat))
 215	{
 216	  error = NULL;
 217	  res =
 218	    g_file_set_attribute_uint32 (child, G_FILE_ATTRIBUTE_UNIX_MODE,
 219					 item.mode,
 220					 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
 221					 NULL, &error);
 222	  g_assert_cmpint (res, ==, TRUE);
 223	  g_assert (error == NULL);
 224	}
 225
 226      g_object_unref (child);
 227    }
 228
 229  /*  create a pattern file  */
 230  log ("    Creating pattern file...");
 231  child = g_file_get_child (root, "pattern_file");
 232  g_assert (child != NULL);
 233
 234  error = NULL;
 235  outs =
 236    g_file_replace (child, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error);
 237  g_assert (error == NULL);
 238
 239  g_assert (outs != NULL);
 240  outds = g_data_output_stream_new (G_OUTPUT_STREAM (outs));
 241  g_assert (outds != NULL);
 242  for (i = 0; i < PATTERN_FILE_SIZE; i++)
 243    {
 244      error = NULL;
 245      res = g_data_output_stream_put_byte (outds, i % 256, NULL, &error);
 246      g_assert (error == NULL);
 247    }
 248  error = NULL;
 249  res = g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error);
 250  g_assert (error == NULL);
 251  g_object_unref (outds);
 252  g_object_unref (outs);
 253  g_object_unref (child);
 254  log (" done.\n");
 255
 256  g_object_unref (root);
 257}
 258
 259static GFile *
 260file_exists (GFile * parent, const char *filename, gboolean * result)
 261{
 262  GFile *child;
 263  gboolean res;
 264
 265  if (result)
 266    *result = FALSE;
 267
 268  child = g_file_get_child (parent, filename);
 269  g_assert (child != NULL);
 270  res = g_file_query_exists (child, NULL);
 271  if (result)
 272    *result = res;
 273
 274  return child;
 275}
 276
 277static void
 278test_attributes (struct StructureItem item, GFileInfo * info)
 279{
 280  GFileType ftype;
 281  guint32 mode;
 282  const char *name, *display_name, *edit_name, *copy_name, *symlink_target;
 283  gboolean utf8_valid;
 284  gboolean has_attr;
 285  gboolean is_symlink;
 286  gboolean can_read, can_write;
 287
 288  /*  standard::type  */
 289  has_attr = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
 290  g_assert_cmpint (has_attr, ==, TRUE);
 291  ftype = g_file_info_get_file_type (info);
 292  g_assert_cmpint (ftype, !=, G_FILE_TYPE_UNKNOWN);
 293  g_assert_cmpint (ftype, ==, item.file_type);
 294
 295  /*  unix::mode  */
 296  if ((item.mode > 0) && (posix_compat))
 297    {
 298      mode =
 299	g_file_info_get_attribute_uint32 (info,
 300					  G_FILE_ATTRIBUTE_UNIX_MODE) & 0xFFF;
 301      g_assert_cmpint (mode, ==, item.mode);
 302    }
 303
 304  /*  access::can-read  */
 305  if (item.file_type != G_FILE_TYPE_SYMBOLIC_LINK)
 306    {
 307      can_read =
 308	g_file_info_get_attribute_boolean (info,
 309					   G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
 310      g_assert_cmpint (can_read, ==, TRUE);
 311    }
 312
 313  /*  access::can-write  */
 314  if ((write_test) && ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE))
 315    {
 316      can_write =
 317	g_file_info_get_attribute_boolean (info,
 318					   G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
 319      g_assert_cmpint (can_write, ==, TRUE);
 320    }
 321
 322  /*  standard::name  */
 323  name = g_file_info_get_name (info);
 324  g_assert (name != NULL);
 325
 326  /*  standard::display-name  */
 327  display_name = g_file_info_get_display_name (info);
 328  g_assert (display_name != NULL);
 329  utf8_valid = g_utf8_validate (display_name, -1, NULL);
 330  g_assert_cmpint (utf8_valid, ==, TRUE);
 331
 332  /*  standard::edit-name  */
 333  edit_name = g_file_info_get_edit_name (info);
 334  if (edit_name)
 335    {
 336      utf8_valid = g_utf8_validate (edit_name, -1, NULL);
 337      g_assert_cmpint (utf8_valid, ==, TRUE);
 338    }
 339
 340  /*  standard::copy-name  */
 341  copy_name =
 342    g_file_info_get_attribute_string (info,
 343				      G_FILE_ATTRIBUTE_STANDARD_COPY_NAME);
 344  if (copy_name)
 345    {
 346      utf8_valid = g_utf8_validate (copy_name, -1, NULL);
 347      g_assert_cmpint (utf8_valid, ==, TRUE);
 348    }
 349
 350  /*  standard::is-symlink  */
 351  if (posix_compat)
 352    {
 353      is_symlink = g_file_info_get_is_symlink (info);
 354      g_assert_cmpint (is_symlink, ==,
 355		       item.file_type == G_FILE_TYPE_SYMBOLIC_LINK);
 356    }
 357
 358  /*  standard::symlink-target  */
 359  if ((item.file_type == G_FILE_TYPE_SYMBOLIC_LINK) && (posix_compat))
 360    {
 361      symlink_target = g_file_info_get_symlink_target (info);
 362      g_assert_cmpstr (symlink_target, ==, item.link_to);
 363    }
 364}
 365
 366static void
 367test_initial_structure (gconstpointer test_data)
 368{
 369  GFile *root;
 370  GFile *child;
 371  gboolean res;
 372  GError *error;
 373  GFileInputStream *ins;
 374  int i;
 375  GFileInfo *info;
 376  guint32 size;
 377  guchar *buffer;
 378  gssize read, total_read;
 379  struct StructureItem item;
 380
 381
 382  g_assert (test_data != NULL);
 383  log ("\n  Testing sample structure in '%s'...\n", (char *) test_data);
 384
 385  root = g_file_new_for_commandline_arg ((char *) test_data);
 386  g_assert (root != NULL);
 387  res = g_file_query_exists (root, NULL);
 388  g_assert_cmpint (res, ==, TRUE);
 389
 390  /*  test the structure  */
 391  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 392    {
 393      item = sample_struct[i];
 394      if (((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
 395	  || (item.handle_special))
 396	continue;
 397
 398      log ("    Testing file '%s'...\n", item.filename);
 399
 400      child = file_exists (root, item.filename, &res);
 401      g_assert (child != NULL);
 402      g_assert_cmpint (res, ==, TRUE);
 403
 404      error = NULL;
 405      info =
 406	g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
 407			   NULL, &error);
 408      g_assert (error == NULL);
 409      g_assert (info != NULL);
 410
 411      test_attributes (item, info);
 412
 413      g_object_unref (child);
 414    }
 415
 416  /*  read and test the pattern file  */
 417  log ("    Testing pattern file...\n");
 418  child = file_exists (root, "pattern_file", &res);
 419  g_assert (child != NULL);
 420  g_assert_cmpint (res, ==, TRUE);
 421
 422  error = NULL;
 423  info =
 424    g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
 425		       &error);
 426  g_assert (error == NULL);
 427  g_assert (info != NULL);
 428  size = g_file_info_get_size (info);
 429  g_assert_cmpint (size, ==, PATTERN_FILE_SIZE);
 430
 431  error = NULL;
 432  ins = g_file_read (child, NULL, &error);
 433  g_assert (ins != NULL);
 434  g_assert (error == NULL);
 435
 436  buffer = g_malloc (PATTERN_FILE_SIZE);
 437  total_read = 0;
 438
 439  while (total_read < PATTERN_FILE_SIZE)
 440    {
 441      error = NULL;
 442      read =
 443	g_input_stream_read (G_INPUT_STREAM (ins), buffer + total_read,
 444			     PATTERN_FILE_SIZE, NULL, &error);
 445      g_assert (error == NULL);
 446      total_read += read;
 447      log ("      read %d bytes, total = %d of %d.\n", read, total_read,
 448	   PATTERN_FILE_SIZE);
 449    }
 450  g_assert_cmpint (total_read, ==, PATTERN_FILE_SIZE);
 451
 452  error = NULL;
 453  res = g_input_stream_close (G_INPUT_STREAM (ins), NULL, &error);
 454  g_assert (error == NULL);
 455  g_assert_cmpint (res, ==, TRUE);
 456
 457  for (i = 0; i < PATTERN_FILE_SIZE; i++)
 458    g_assert_cmpint (*(buffer + i), ==, i % 256);
 459
 460  g_object_unref (ins);
 461  g_object_unref (child);
 462  g_free (buffer);
 463  g_object_unref (root);
 464}
 465
 466static void
 467traverse_recurse_dirs (GFile * parent, GFile * root)
 468{
 469  gboolean res;
 470  GError *error;
 471  GFileEnumerator *enumerator;
 472  GFileInfo *info;
 473  GFile *descend;
 474  char *relative_path;
 475  int i;
 476  gboolean found;
 477
 478  g_assert (root != NULL);
 479
 480  error = NULL;
 481  enumerator =
 482    g_file_enumerate_children (parent, "*",
 483			       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
 484			       &error);
 485  g_assert (enumerator != NULL);
 486  g_assert (error == NULL);
 487
 488  error = NULL;
 489  info = g_file_enumerator_next_file (enumerator, NULL, &error);
 490  while ((info) && (!error))
 491    {
 492      descend = g_file_get_child (parent, g_file_info_get_name (info));
 493      g_assert (descend != NULL);
 494      relative_path = g_file_get_relative_path (root, descend);
 495      g_assert (relative_path != NULL);
 496
 497      found = FALSE;
 498      for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 499	{
 500	  if (strcmp (sample_struct[i].filename, relative_path) == 0)
 501	    {
 502	      /*  test the attributes again  */
 503	      test_attributes (sample_struct[i], info);
 504
 505	      found = TRUE;
 506	      break;
 507	    }
 508	}
 509      g_assert_cmpint (found, ==, TRUE);
 510
 511      log ("  Found file %s, relative to root: %s\n",
 512	   g_file_info_get_display_name (info), relative_path);
 513
 514      if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
 515	traverse_recurse_dirs (descend, root);
 516
 517      g_object_unref (descend);
 518      error = NULL;
 519      info = g_file_enumerator_next_file (enumerator, NULL, &error);
 520    }
 521  g_assert (error == NULL);
 522
 523  error = NULL;
 524  res = g_file_enumerator_close (enumerator, NULL, &error);
 525  g_assert_cmpint (res, ==, TRUE);
 526  g_assert (error == NULL);
 527}
 528
 529static void
 530test_traverse_structure (gconstpointer test_data)
 531{
 532  GFile *root;
 533  gboolean res;
 534
 535  g_assert (test_data != NULL);
 536  log ("\n  Traversing through the sample structure in '%s'...\n",
 537       (char *) test_data);
 538
 539  root = g_file_new_for_commandline_arg ((char *) test_data);
 540  g_assert (root != NULL);
 541  res = g_file_query_exists (root, NULL);
 542  g_assert_cmpint (res, ==, TRUE);
 543
 544  traverse_recurse_dirs (root, root);
 545
 546  g_object_unref (root);
 547}
 548
 549
 550
 551
 552static void
 553test_enumerate (gconstpointer test_data)
 554{
 555  GFile *root, *child;
 556  gboolean res;
 557  GError *error;
 558  GFileEnumerator *enumerator;
 559  GFileInfo *info;
 560  int i;
 561  struct StructureItem item;
 562
 563
 564  g_assert (test_data != NULL);
 565  log ("\n  Test enumerate '%s'...\n", (char *) test_data);
 566
 567  root = g_file_new_for_commandline_arg ((char *) test_data);
 568  g_assert (root != NULL);
 569  res = g_file_query_exists (root, NULL);
 570  g_assert_cmpint (res, ==, TRUE);
 571
 572
 573  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 574    {
 575      item = sample_struct[i];
 576      if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
 577	continue;
 578
 579      if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
 580	  (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS)
 581	   && posix_compat)
 582	  || ((item.extra_flags & TEST_ENUMERATE_FILE) ==
 583	      TEST_ENUMERATE_FILE))
 584	{
 585	  log ("    Testing file '%s'\n", item.filename);
 586	  child = g_file_get_child (root, item.filename);
 587	  g_assert (child != NULL);
 588	  error = NULL;
 589	  enumerator =
 590	    g_file_enumerate_children (child, "*",
 591				       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
 592				       NULL, &error);
 593
 594	  if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS)
 595	    {
 596	      g_assert (enumerator == NULL);
 597	      g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_FOUND);
 598	    }
 599	  if ((item.extra_flags & TEST_ENUMERATE_FILE) == TEST_ENUMERATE_FILE)
 600	    {
 601	      g_assert (enumerator == NULL);
 602	      g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_DIRECTORY);
 603	    }
 604	  if ((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS)
 605	    {
 606	      g_assert (enumerator != NULL);
 607
 608	      error = NULL;
 609	      info = g_file_enumerator_next_file (enumerator, NULL, &error);
 610	      g_assert (info == NULL);
 611	      g_assert (error == NULL);
 612	      /*  no items should be found, no error should be logged  */
 613	    }
 614
 615	  if (error)
 616	    g_error_free (error);
 617
 618	  if (enumerator)
 619	    {
 620	      error = NULL;
 621	      res = g_file_enumerator_close (enumerator, NULL, &error);
 622	      g_assert_cmpint (res, ==, TRUE);
 623	      g_assert (error == NULL);
 624	    }
 625	  g_object_unref (child);
 626	}
 627    }
 628  g_object_unref (root);
 629}
 630
 631static void
 632do_copy_move (GFile * root, struct StructureItem item, const char *target_dir,
 633	      enum StructureExtraFlags extra_flags)
 634{
 635  GFile *dst_dir, *src_file, *dst_file;
 636  gboolean res;
 637  GError *error;
 638
 639  log ("    do_copy_move: '%s' --> '%s'\n", item.filename, target_dir);
 640
 641  dst_dir = g_file_get_child (root, target_dir);
 642  g_assert (dst_dir != NULL);
 643  src_file = g_file_get_child (root, item.filename);
 644  g_assert (src_file != NULL);
 645  dst_file = g_file_get_child (dst_dir, item.filename);
 646  g_assert (dst_file != NULL);
 647
 648  error = NULL;
 649  if ((item.extra_flags & TEST_COPY) == TEST_COPY)
 650    res =
 651      g_file_copy (src_file, dst_file,
 652		   G_FILE_COPY_NOFOLLOW_SYMLINKS |
 653		   ((extra_flags ==
 654		     TEST_OVERWRITE) ? G_FILE_COPY_OVERWRITE :
 655		    G_FILE_COPY_NONE), NULL, NULL, NULL, &error);
 656  else
 657    res =
 658      g_file_move (src_file, dst_file, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL,
 659		   NULL, NULL, &error);
 660
 661  if (error)
 662    log ("       res = %d, error code %d = %s\n", res, error->code,
 663	 error->message);
 664
 665  /*  copying file/directory to itself (".")  */
 666  if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) &&
 667      (extra_flags == TEST_ALREADY_EXISTS))
 668    {
 669      g_assert_cmpint (res, ==, FALSE);
 670      g_assert_cmpint (error->code, ==, G_IO_ERROR_EXISTS);
 671    }
 672  /*  target file is a file, overwrite is not set  */
 673  else if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) &&
 674	   (extra_flags == TEST_TARGET_IS_FILE))
 675    {
 676      g_assert_cmpint (res, ==, FALSE);
 677      if (item.file_type == G_FILE_TYPE_DIRECTORY)
 678	g_assert_cmpint (error->code, ==, G_IO_ERROR_WOULD_RECURSE);
 679      else
 680	g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_DIRECTORY);
 681    }
 682  /*  source file is directory  */
 683  else if ((item.extra_flags & TEST_COPY_ERROR_RECURSE) ==
 684	   TEST_COPY_ERROR_RECURSE)
 685    {
 686      g_assert_cmpint (res, ==, FALSE);
 687      g_assert_cmpint (error->code, ==, G_IO_ERROR_WOULD_RECURSE);
 688    }
 689  /*  source or target path doesn't exist  */
 690  else if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
 691	   (extra_flags == TEST_NOT_EXISTS))
 692    {
 693      g_assert_cmpint (res, ==, FALSE);
 694      g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_FOUND);
 695    }
 696  /*  source or target path permission denied  */
 697  else if (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) ||
 698	   (extra_flags == TEST_NO_ACCESS))
 699    {
 700      g_assert_cmpint (res, ==, FALSE);
 701      g_assert_cmpint (error->code, ==, G_IO_ERROR_PERMISSION_DENIED);
 702    }
 703  /*  no error should be found, all exceptions defined above  */
 704  else
 705    {
 706      g_assert_cmpint (res, ==, TRUE);
 707      g_assert (error == NULL);
 708    }
 709
 710  if (error)
 711    g_error_free (error);
 712
 713
 714  g_object_unref (dst_dir);
 715  g_object_unref (src_file);
 716  g_object_unref (dst_file);
 717}
 718
 719static void
 720test_copy_move (gconstpointer test_data)
 721{
 722  GFile *root;
 723  gboolean res;
 724  int i;
 725  struct StructureItem item;
 726
 727  log ("\n");
 728
 729  g_assert (test_data != NULL);
 730  root = g_file_new_for_commandline_arg ((char *) test_data);
 731  g_assert (root != NULL);
 732  res = g_file_query_exists (root, NULL);
 733  g_assert_cmpint (res, ==, TRUE);
 734
 735
 736  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 737    {
 738      item = sample_struct[i];
 739
 740      if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
 741	continue;
 742
 743      if (((item.extra_flags & TEST_COPY) == TEST_COPY) ||
 744	  ((item.extra_flags & TEST_MOVE) == TEST_MOVE))
 745	{
 746	  /*  test copy/move to a directory, expecting no errors if source files exist  */
 747	  do_copy_move (root, item, TEST_DIR_TARGET, 0);
 748
 749	  /*  some files have been already moved so we can't count with them in the tests  */
 750	  if ((item.extra_flags & TEST_COPY) == TEST_COPY)
 751	    {
 752	      /*  test overwrite for flagged files  */
 753	      if ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE)
 754		{
 755		  do_copy_move (root, item, TEST_DIR_TARGET, TEST_OVERWRITE);
 756		}
 757	      /*  source = target, should return G_IO_ERROR_EXISTS  */
 758	      do_copy_move (root, item, ".", TEST_ALREADY_EXISTS);
 759	      /*  target is file  */
 760	      do_copy_move (root, item, TEST_TARGET_FILE,
 761			    TEST_TARGET_IS_FILE);
 762	      /*  target path is invalid  */
 763	      do_copy_move (root, item, TEST_NAME_NOT_EXISTS,
 764			    TEST_NOT_EXISTS);
 765
 766	      /*  tests on POSIX-compatible filesystems  */
 767	      if (posix_compat)
 768		{
 769		  /*  target directory is not accessible (no execute flag)  */
 770		  do_copy_move (root, item, TEST_DIR_NO_ACCESS,
 771				TEST_NO_ACCESS);
 772		  /*  target directory is readonly  */
 773		  do_copy_move (root, item, TEST_DIR_NO_WRITE,
 774				TEST_NO_ACCESS);
 775		}
 776	    }
 777	}
 778    }
 779  g_object_unref (root);
 780}
 781
 782static void
 783test_create (gconstpointer test_data)
 784{
 785  GFile *root, *child;
 786  gboolean res;
 787  GError *error;
 788  int i;
 789  struct StructureItem item;
 790  GFileOutputStream *os;
 791
 792  g_assert (test_data != NULL);
 793  log ("\n");
 794
 795  root = g_file_new_for_commandline_arg ((char *) test_data);
 796  g_assert (root != NULL);
 797  res = g_file_query_exists (root, NULL);
 798  g_assert_cmpint (res, ==, TRUE);
 799
 800  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 801    {
 802      item = sample_struct[i];
 803
 804      if (((item.extra_flags & TEST_CREATE) == TEST_CREATE) ||
 805	  ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE) ||
 806	  ((item.extra_flags & TEST_APPEND) == TEST_APPEND))
 807	{
 808	  log ("  test_create: '%s'\n", item.filename);
 809
 810	  child = g_file_get_child (root, item.filename);
 811	  g_assert (child != NULL);
 812	  error = NULL;
 813	  os = NULL;
 814
 815	  if ((item.extra_flags & TEST_CREATE) == TEST_CREATE)
 816	    os = g_file_create (child, item.create_flags, NULL, &error);
 817	  else if ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE)
 818	    os =
 819	      g_file_replace (child, NULL, TRUE, item.create_flags, NULL,
 820			      &error);
 821	  else if ((item.extra_flags & TEST_APPEND) == TEST_APPEND)
 822	    os = g_file_append_to (child, item.create_flags, NULL, &error);
 823
 824
 825	  if (error)
 826	    log ("       error code %d = %s\n", error->code, error->message);
 827
 828	  if (((item.extra_flags & TEST_NOT_EXISTS) == 0) &&
 829	      ((item.extra_flags & TEST_CREATE) == TEST_CREATE))
 830	    {
 831	      g_assert (os == NULL);
 832	      g_assert (error != NULL);
 833	      g_assert_cmpint (error->code, ==, G_IO_ERROR_EXISTS);
 834	    }
 835	  else if (item.file_type == G_FILE_TYPE_DIRECTORY)
 836	    {
 837	      g_assert (os == NULL);
 838	      g_assert (error != NULL);
 839	      if ((item.extra_flags & TEST_CREATE) == TEST_CREATE)
 840		g_assert_cmpint (error->code, ==, G_IO_ERROR_EXISTS);
 841	      else
 842		g_assert_cmpint (error->code, ==, G_IO_ERROR_IS_DIRECTORY);
 843	    }
 844	  else
 845	    {
 846	      g_assert (os != NULL);
 847	      g_assert (error == NULL);
 848	    }
 849
 850	  if (error)
 851	    g_error_free (error);
 852
 853	  if (os)
 854	    {
 855	      error = NULL;
 856	      res =
 857		g_output_stream_close (G_OUTPUT_STREAM (os), NULL, &error);
 858	      if (error)
 859		log ("         g_output_stream_close: error %d = %s\n",
 860		     error->code, error->message);
 861	      g_assert_cmpint (res, ==, TRUE);
 862	      g_assert (error == NULL);
 863	    }
 864	  g_object_unref (child);
 865	}
 866    }
 867  g_object_unref (root);
 868}
 869
 870static void
 871test_open (gconstpointer test_data)
 872{
 873  GFile *root, *child;
 874  gboolean res;
 875  GError *error;
 876  int i;
 877  struct StructureItem item;
 878  GFileInputStream *input_stream;
 879
 880  g_assert (test_data != NULL);
 881  log ("\n");
 882
 883  root = g_file_new_for_commandline_arg ((char *) test_data);
 884  g_assert (root != NULL);
 885  res = g_file_query_exists (root, NULL);
 886  g_assert_cmpint (res, ==, TRUE);
 887
 888  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 889    {
 890      item = sample_struct[i];
 891
 892      if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
 893	continue;
 894
 895      if ((item.extra_flags & TEST_OPEN) == TEST_OPEN)
 896	{
 897	  log ("  test_open: '%s'\n", item.filename);
 898
 899	  child = g_file_get_child (root, item.filename);
 900	  g_assert (child != NULL);
 901	  error = NULL;
 902	  input_stream = g_file_read (child, NULL, &error);
 903
 904	  if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
 905	      ((item.extra_flags & TEST_INVALID_SYMLINK) ==
 906	       TEST_INVALID_SYMLINK))
 907	    {
 908	      g_assert (input_stream == NULL);
 909	      g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_FOUND);
 910	    }
 911	  else if (item.file_type == G_FILE_TYPE_DIRECTORY)
 912	    {
 913	      g_assert (input_stream == NULL);
 914	      g_assert_cmpint (error->code, ==, G_IO_ERROR_IS_DIRECTORY);
 915	    }
 916	  else
 917	    {
 918	      g_assert (input_stream != NULL);
 919	      g_assert (error == NULL);
 920	    }
 921
 922	  if (error)
 923	    g_error_free (error);
 924
 925	  if (input_stream)
 926	    {
 927	      error = NULL;
 928	      res =
 929		g_input_stream_close (G_INPUT_STREAM (input_stream), NULL,
 930				      &error);
 931	      g_assert_cmpint (res, ==, TRUE);
 932	      g_assert (error == NULL);
 933	    }
 934	  g_object_unref (child);
 935	}
 936    }
 937  g_object_unref (root);
 938}
 939
 940static void
 941test_delete (gconstpointer test_data)
 942{
 943  GFile *root;
 944  GFile *child;
 945  gboolean res;
 946  GError *error;
 947  int i;
 948  struct StructureItem item;
 949
 950  g_assert (test_data != NULL);
 951  log ("\n");
 952
 953  root = g_file_new_for_commandline_arg ((char *) test_data);
 954  g_assert (root != NULL);
 955  res = g_file_query_exists (root, NULL);
 956  g_assert_cmpint (res, ==, TRUE);
 957
 958  for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
 959    {
 960      item = sample_struct[i];
 961
 962      if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
 963	continue;
 964
 965      if (((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL) ||
 966	  ((item.extra_flags & TEST_DELETE_TRASH) == TEST_DELETE_TRASH))
 967	{
 968	  child = file_exists (root, item.filename, &res);
 969	  g_assert (child != NULL);
 970	  /*  we don't care about result here  */
 971
 972	  log ("  Deleting %s, path = %s\n", item.filename,
 973	       g_file_get_path (child));
 974	  error = NULL;
 975	  if ((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL)
 976	    res = g_file_delete (child, NULL, &error);
 977	  else
 978	    res = g_file_trash (child, NULL, &error);
 979
 980	  if ((item.extra_flags & TEST_DELETE_NON_EMPTY) ==
 981	      TEST_DELETE_NON_EMPTY)
 982	    {
 983	      g_assert_cmpint (res, ==, FALSE);
 984	      g_assert (error != NULL);
 985	      g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_EMPTY);
 986	    }
 987	  if ((item.extra_flags & TEST_DELETE_FAILURE) == TEST_DELETE_FAILURE)
 988	    {
 989	      g_assert_cmpint (res, ==, FALSE);
 990	      g_assert (error != NULL);
 991	      g_assert_cmpint (error->code, !=, 0);
 992	    }
 993	  if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS)
 994	    {
 995	      g_assert_cmpint (res, ==, FALSE);
 996	      g_assert (error != NULL);
 997	      g_assert_cmpint (error->code, ==, G_IO_ERROR_NOT_FOUND);
 998	    }
 999
1000	  if (error)
1001	    {
1002	      log ("      result = %d, error = %s\n", res, error->message);
1003	      g_error_free (error);
1004	    }
1005
1006	  g_object_unref (child);
1007	}
1008    }
1009  g_object_unref (root);
1010}
1011
1012int
1013main (int argc, char *argv[])
1014{
1015  static gboolean create_struct;
1016  static char *target_path;
1017  GError *error;
1018  GOptionContext *context;
1019
1020  static GOptionEntry cmd_entries[] = {
1021    {"read-write", 'w', 0, G_OPTION_ARG_NONE, &write_test,
1022     "Perform write tests (incl. structure creation)", NULL},
1023    {"create-struct", 'c', 0, G_OPTION_ARG_NONE, &create_struct,
1024     "Only create testing structure (no tests)", NULL},
1025    {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL},
1026    {"posix", 'x', 0, G_OPTION_ARG_NONE, &posix_compat,
1027     "Test POSIX-specific features (unix permissions, symlinks)", NULL},
1028    {NULL}
1029  };
1030
1031  verbose = FALSE;
1032  write_test = FALSE;
1033  create_struct = FALSE;
1034  target_path = NULL;
1035  posix_compat = FALSE;
1036
1037  /*  strip all gtester-specific args  */
1038  g_type_init ();
1039  g_test_init (&argc, &argv, NULL);
1040
1041  /*  add trailing args  */
1042  error = NULL;
1043  context = g_option_context_new ("target_path");
1044  g_option_context_add_main_entries (context, cmd_entries, NULL);
1045  if (!g_option_context_parse (context, &argc, &argv, &error))
1046    {
1047      g_print ("option parsing failed: %s\n", error->message);
1048      return g_test_run ();
1049    }
1050
1051  /*  missing mandatory arg for target dir  */
1052  if (argc < 2)
1053    {
1054      g_print (g_option_context_get_help (context, TRUE, NULL));
1055      return g_test_run ();
1056    }
1057  target_path = strdup (argv[1]);
1058
1059  /*  Write test - create new testing structure  */
1060  if (write_test || create_struct)
1061    g_test_add_data_func ("/live-g-file/create_structure", target_path,
1062			  test_create_structure);
1063
1064  /*  Read test - test the sample structure - expect defined attributes to be there  */
1065  if (!create_struct)
1066    g_test_add_data_func ("/live-g-file/test_initial_structure", target_path,
1067			  test_initial_structure);
1068
1069  /*  Read test - test traverse the structure - no special file should appear  */
1070  if (!create_struct)
1071    g_test_add_data_func ("/live-g-file/test_traverse_structure", target_path,
1072			  test_traverse_structure);
1073
1074  /*  Read test - enumerate  */
1075  if (!create_struct)
1076    g_test_add_data_func ("/live-g-file/test_enumerate", target_path,
1077			  test_enumerate);
1078
1079  /*  Read test - open (g_file_read())  */
1080  if (!create_struct)
1081    g_test_add_data_func ("/live-g-file/test_open", target_path, test_open);
1082
1083  /*  Write test - create  */
1084  if (write_test && (!create_struct))
1085    g_test_add_data_func ("/live-g-file/test_create", target_path,
1086			  test_create);
1087
1088  /*  Write test - copy, move  */
1089  if (write_test && (!create_struct))
1090    g_test_add_data_func ("/live-g-file/test_copy_move", target_path,
1091			  test_copy_move);
1092
1093  /*  Write test - delete, trash  */
1094  if (write_test && (!create_struct))
1095    g_test_add_data_func ("/live-g-file/test_delete", target_path,
1096			  test_delete);
1097
1098  return g_test_run ();
1099}