You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2013/05/01 15:55:31 UTC

svn commit: r1478001 - /subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c

Author: julianfoad
Date: Wed May  1 13:55:31 2013
New Revision: 1478001

URL: http://svn.apache.org/r1478001
Log:
Add a test for correct retrieval of property conflict descriptions.  This
catches the node-kind bug that was fixed in r1477876.

* subversion/tests/libsvn_wc/conflict-data-test.c
  (compare_file_content,
   compare_prop_conflict,
   test_prop_conflict_baton_t,
   create_prop_conflict_skel,
   prop_conflict_cb): New
  (test_prop_conflicts): New test.
  (test_funcs): Run it.

Modified:
    subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c

Modified: subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c?rev=1478001&r1=1478000&r2=1478001&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c Wed May  1 13:55:31 2013
@@ -28,6 +28,7 @@
 #include <apr_hash.h>
 #include <apr_tables.h>
 
+#include "svn_props.h"
 #include "svn_pools.h"
 #include "svn_hash.h"
 #include "svn_types.h"
@@ -115,6 +116,70 @@ compare_conflict(const svn_wc_conflict_d
   return SVN_NO_ERROR;
 }
 
+/* Assert that a file contains the expected data.  Return an
+ * error if not. */
+static svn_error_t *
+compare_file_content(const char *file_abspath,
+                     const char *expected_val,
+                     apr_pool_t *scratch_pool)
+{
+  svn_stringbuf_t *actual_val;
+
+  SVN_ERR(svn_stringbuf_from_file2(&actual_val, file_abspath, scratch_pool));
+  ASSERT_STR_EQ(actual_val->data, expected_val);
+  return SVN_NO_ERROR;
+}
+
+/* Assert that ACTUAL and EXPECTED both represent the same property
+ * conflict, or are both NULL.  Return an error if not.
+ *
+ * Compare the property values found in files named by
+ * ACTUAL->base_abspath, ACTUAL->my_abspath, ACTUAL->merged_abspath
+ * with EXPECTED_BASE_VAL, EXPECTED_MY_VAL, EXPECTED_THEIR_VAL
+ * respectively, ignoring the corresponding fields in EXPECTED. */
+static svn_error_t *
+compare_prop_conflict(const svn_wc_conflict_description2_t *actual,
+                      const svn_wc_conflict_description2_t *expected,
+                      const char *expected_base_val,
+                      const char *expected_my_val,
+                      const char *expected_their_val,
+                      apr_pool_t *scratch_pool)
+{
+  if (actual == NULL && expected == NULL)
+    return SVN_NO_ERROR;
+
+  SVN_TEST_ASSERT(actual && expected);
+  ASSERT_INT_EQ(actual->kind,   svn_wc_conflict_kind_property);
+  ASSERT_INT_EQ(expected->kind, svn_wc_conflict_kind_property);
+
+  ASSERT_STR_EQ(actual->local_abspath,  expected->local_abspath);
+  ASSERT_INT_EQ(actual->node_kind,      expected->node_kind);
+  ASSERT_STR_EQ(actual->property_name,  expected->property_name);
+  ASSERT_INT_EQ(actual->action,         expected->action);
+  ASSERT_INT_EQ(actual->reason,         expected->reason);
+  ASSERT_INT_EQ(actual->operation,      expected->operation);
+  SVN_ERR(compare_version(actual->src_left_version,
+                          expected->src_left_version));
+  SVN_ERR(compare_version(actual->src_right_version,
+                          expected->src_right_version));
+
+  SVN_ERR(compare_file_content(actual->base_abspath, expected_base_val,
+                               scratch_pool));
+  SVN_ERR(compare_file_content(actual->my_abspath, expected_my_val,
+                               scratch_pool));
+  /* Historical wart: for a prop conflict, 'theirs' is in the 'merged_file'
+   * field, and the conflict artifact file is in the 'theirs_abspath' field. */
+  SVN_ERR(compare_file_content(actual->merged_file, expected_their_val,
+                               scratch_pool));
+  /*ASSERT_STR_EQ(actual->theirs_abspath, conflict_artifact_file));*/
+
+  /* These are 'undefined' for a prop conflict */
+  /*ASSERT_INT_EQ(actual->is_binary, expected->is_binary);*/
+  /*ASSERT_STR_EQ(actual->mime_type, expected->mime_type);*/
+
+  return SVN_NO_ERROR;
+}
+
 /* Create and return a tree conflict description */
 static svn_wc_conflict_description2_t *
 tree_conflict_create(const char *local_abspath,
@@ -562,6 +627,186 @@ test_serialize_tree_conflict(const svn_t
   return SVN_NO_ERROR;
 }
 
+/* A conflict resolver callback baton for test_prop_conflicts(). */
+typedef struct test_prop_conflict_baton_t
+{
+  /* Sets of properties. */
+  apr_hash_t *mine;
+  apr_hash_t *their_old;
+  apr_hash_t *theirs;
+  /* The set of prop names in conflict. */
+  apr_hash_t *conflicts;
+
+  /* We use all the fields of DESC except the base/theirs/mine/merged paths. */
+  svn_wc_conflict_description2_t *desc;
+
+  int conflicts_seen;
+} test_prop_conflict_baton_t;
+
+/* Set *CONFLICT_SKEL_P to a new property conflict skel reflecting the
+ * conflict details given in B. */
+static svn_error_t *
+create_prop_conflict_skel(svn_skel_t **conflict_skel_p,
+                          svn_wc_context_t *wc_ctx,
+                          const test_prop_conflict_baton_t *b,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  svn_skel_t *conflict_skel = svn_wc__conflict_skel_create(result_pool);
+  const char *marker_abspath;
+  svn_boolean_t complete;
+
+  SVN_ERR(svn_io_write_unique(&marker_abspath,
+                              b->desc->local_abspath,
+                              "conflict-artifact-file-content\n", 6,
+                              svn_io_file_del_none, scratch_pool));
+
+  SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_skel,
+                                                  wc_ctx->db,
+                                                  b->desc->local_abspath,
+                                                  marker_abspath,
+                                                  b->mine, b->their_old,
+                                                  b->theirs, b->conflicts,
+                                                  result_pool, scratch_pool));
+
+  switch (b->desc->operation)
+    {
+    case svn_wc_operation_update:
+      SVN_ERR(svn_wc__conflict_skel_set_op_update(
+                conflict_skel,
+                b->desc->src_left_version, b->desc->src_right_version,
+                result_pool, scratch_pool));
+      break;
+    case svn_wc_operation_switch:
+      SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+                conflict_skel,
+                b->desc->src_left_version, b->desc->src_right_version,
+                result_pool, scratch_pool));
+      break;
+    case svn_wc_operation_merge:
+      SVN_ERR(svn_wc__conflict_skel_set_op_merge(
+                conflict_skel,
+                b->desc->src_left_version, b->desc->src_right_version,
+                result_pool, scratch_pool));
+      break;
+    default:
+      SVN_ERR_MALFUNCTION();
+    }
+
+  SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+  SVN_TEST_ASSERT(complete);
+  *conflict_skel_p = conflict_skel;
+  return SVN_NO_ERROR;
+}
+
+/* A conflict resolver callback for test_prop_conflicts(), that checks
+ * that the conflict described to it matches the one described in BATON,
+ * and also counts the number of times it is called. */
+static svn_error_t *
+prop_conflict_cb(svn_wc_conflict_result_t **result_p,
+                 const svn_wc_conflict_description2_t *desc,
+                 void *baton,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  test_prop_conflict_baton_t *b = baton;
+
+  SVN_ERR(compare_prop_conflict(
+            desc, b->desc,
+            svn_prop_get_value(b->their_old, desc->property_name),
+            svn_prop_get_value(b->mine, desc->property_name),
+            svn_prop_get_value(b->theirs, desc->property_name),
+            scratch_pool));
+  b->conflicts_seen++;
+
+  *result_p = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone,
+                                            NULL /*merged_file*/, result_pool);
+  return SVN_NO_ERROR;
+}
+
+/* Test for correct retrieval of property conflict descriptions from
+ * the WC DB.
+ *
+ * Presently it tests just one prop conflict, and only during the
+ * 'resolve' operation.  We should also test during the 'update'/
+ * 'switch'/'merge' operations.
+ */
+static svn_error_t *
+test_prop_conflicts(const svn_test_opts_t *opts,
+                    apr_pool_t *pool)
+{
+  svn_test__sandbox_t sbox;
+  svn_skel_t *conflict_skel;
+  svn_error_t *err;
+  const char *lock_abspath;
+  test_prop_conflict_baton_t *b = apr_pcalloc(pool, sizeof(*b));
+  svn_wc_conflict_description2_t *desc = apr_pcalloc(pool, sizeof(*b));
+
+  SVN_ERR(svn_test__sandbox_create(&sbox, "test_prop_conflicts", opts, pool));
+
+  /* Describe a property conflict */
+  b->mine = apr_hash_make(pool);
+  b->their_old = apr_hash_make(pool);
+  b->theirs = apr_hash_make(pool);
+  b->conflicts = apr_hash_make(pool);
+  svn_hash_sets(b->mine, "prop", svn_string_create("Mine", pool));
+  svn_hash_sets(b->their_old, "prop", svn_string_create("Their-Old", pool));
+  svn_hash_sets(b->theirs, "prop", svn_string_create("Theirs", pool));
+  svn_hash_sets(b->conflicts, "prop", "");
+
+  b->desc = desc;
+  desc->local_abspath = sbox.wc_abspath;
+  desc->kind = svn_wc_conflict_kind_property;
+  desc->node_kind = svn_node_dir;
+  desc->operation = svn_wc_operation_update;
+  desc->action = svn_wc_conflict_action_edit;
+  desc->reason = svn_wc_conflict_reason_edited;
+  desc->mime_type = NULL;
+  desc->is_binary = FALSE;
+  desc->property_name = "prop";
+  desc->src_left_version
+    = svn_wc_conflict_version_create2(sbox.repos_url, "uuid",
+                                      "trunk", 12, svn_node_dir, pool);
+  desc->src_right_version = NULL;  /* WC only */
+
+  b->conflicts_seen = 0;
+
+  /* Record a conflict */
+  {
+    apr_pool_t *subpool = svn_pool_create(pool);
+    SVN_ERR(create_prop_conflict_skel(&conflict_skel, sbox.wc_ctx, b,
+                                      pool, subpool));
+    svn_pool_clear(subpool);
+    SVN_ERR(svn_wc__db_op_mark_conflict(sbox.wc_ctx->db,
+                                        sbox.wc_abspath,
+                                        conflict_skel, NULL, subpool));
+    svn_pool_destroy(subpool);
+  }
+
+  /* Test the API for resolving the conflict: check that correct details
+   * of the conflict are returned. */
+  SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, sbox.wc_ctx,
+                                                 sbox.wc_abspath, pool, pool));
+  err = svn_wc__resolve_conflicts(sbox.wc_ctx, sbox.wc_abspath,
+                                  svn_depth_empty,
+                                  FALSE /* resolve_text */,
+                                  "" /* resolve_prop (ALL props) */,
+                                  FALSE /* resolve_tree */,
+                                  svn_wc_conflict_choose_unspecified,
+                                  prop_conflict_cb, b,
+                                  NULL, NULL, /* cancellation */
+                                  NULL, NULL, /* notification */
+                                  pool);
+
+  SVN_ERR(svn_error_compose_create(err,
+                                   svn_wc__release_write_lock(sbox.wc_ctx,
+                                                              lock_abspath,
+                                                              pool)));
+
+  ASSERT_INT_EQ(b->conflicts_seen, 1);
+  return SVN_NO_ERROR;
+}
+
 /* The test table.  */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -579,6 +824,8 @@ struct svn_test_descriptor_t test_funcs[
                        "read and write a text conflict"),
     SVN_TEST_OPTS_PASS(test_serialize_tree_conflict,
                        "read and write a tree conflict"),
+    SVN_TEST_OPTS_PASS(test_prop_conflicts,
+                       "test prop conflicts"),
     SVN_TEST_NULL
   };