add more symlink tests

Sun, 24 Nov 2019 12:40:28 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 24 Nov 2019 12:40:28 +0100
changeset 686
ab159748055c
parent 685
487645580b5e
child 687
9922a349a61a

add more symlink tests

dav/db.h file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
test/bin-test/test-dav-sync-symlink1.sh file | annotate | diff | comparison | revisions
test/bin-test/test-dav.sh file | annotate | diff | comparison | revisions
--- a/dav/db.h	Sat Nov 23 17:49:18 2019 +0100
+++ b/dav/db.h	Sun Nov 24 12:40:28 2019 +0100
@@ -71,6 +71,7 @@
     char *local_path;
     
     char *link_target;
+    char *link_target_db;
     
     FilePart *parts;
     size_t numparts;
--- a/dav/sync.c	Sat Nov 23 17:49:18 2019 +0100
+++ b/dav/sync.c	Sun Nov 24 12:40:28 2019 +0100
@@ -969,6 +969,8 @@
         SyncDirectory *dir,
         SyncDatabase *db)
 {
+    DavBool update_db = FALSE;
+    
     char *etag = dav_get_string_property(res, "D:getetag");
     if(!etag) {
         fprintf(stderr, "Error: resource %s has no etag\n", res->path);
@@ -1017,6 +1019,19 @@
         if(SYNC_SYMLINK(dir) && nullstrcmp(link, local->link_target)) {
             ret = REMOTE_CHANGE_LINK;
             nochange = TRUE;
+            
+            if(local->link_target) {
+                LocalResource *local2 = local_resource_new(dir, db, local->path);
+                if(type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED && nullstrcmp(local->link_target, local2->link_target)) {
+                    ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED;
+                }            
+                local_resource_free(local2);
+
+                if(!nullstrcmp(link, local->link_target)) {
+                    ret = REMOTE_NO_CHANGE;
+                    update_db = TRUE;
+                }
+            } 
         } else if(issplit && local->hash && hash) {
             if(!strcmp(local->hash, hash)) {
                 // resource is already up-to-date on the client
@@ -1040,11 +1055,26 @@
             ret = type;
         }
     } else if(link) {
+        // new file is a link
+        ret = REMOTE_CHANGE_LINK;
+        
         if(exists && type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) {
-            ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED;
-        } else {
-            ret = REMOTE_CHANGE_LINK;
-        }
+            // a file with the same name already exists
+            // if it is a link, compare the targets
+            LocalResource *local2 = local_resource_new(dir, db, res->path);
+            if(local2) {
+                if(local2->link_target) {
+                    if(strcmp(link, local2->link_target)) {
+                        ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED;
+                    }
+                } else {
+                    ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED;
+                }
+                
+                local_resource_free(local2);
+            }
+        }
+        
     } else if(exists) {
         ret = type;
     } else {
@@ -1053,7 +1083,6 @@
      
     // if hashing is enabled we can compare the hash of the remote file
     // with the local file to test if a file is really modified
-    DavBool update_db = FALSE;
     char *update_hash = NULL;
     if (!iscollection &&
         !link &&
@@ -1155,6 +1184,10 @@
         if(!local->hash) {
             local->hash = update_hash;
         } // else: hash already updated
+        if(link) {
+            nullfree(local->link_target);
+            local->link_target = link;
+        }
     }
         
     free(local_path);
@@ -2210,6 +2243,7 @@
             sync_error++;
         } else {
             DavBool equal = FALSE;
+            DavBool res_conflict = FALSE;
             int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal);
             if(equal) {
                 char *etag = dav_get_string_property(res, "D:getetag");
@@ -2231,6 +2265,14 @@
                 local_res->hash = NULL;
                 local_res->skipped = TRUE;
                 sync_conflict++;
+                
+                if(local_res->link_target) {
+                    free(local_res->link_target);
+                    local_res->link_target = local_res->link_target_db;
+                    local_res->link_target_db = NULL;
+                }
+                
+                res_conflict = TRUE;
             } else {
                 if(local_res->link_target) {
                     printf(
@@ -2252,7 +2294,11 @@
             
             if(!err) {
                 LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path);
-                ucx_map_cstr_put(db->resources, local_res->path, local_res);
+                // in case of a conflict, don't store the resource
+                // in the db, if it is new
+                if(!res_conflict || dbres) {
+                    ucx_map_cstr_put(db->resources, local_res->path, local_res);
+                }
             }
         }
         
@@ -2847,6 +2893,9 @@
         if(db_res->hash) {
             res->prev_hash = strdup(db_res->hash);
         }
+        if(db_res->link_target) {
+            res->link_target_db = db_res->link_target;
+        }
         
         // if the resource is splitted, copy the part info to the new
         // LocalResource obj, because we need it later
@@ -3005,11 +3054,21 @@
         return 1;
     }
     
+    char *link = dav_get_string_property_ns(remote, DAV_PROPS_NS, "link");
+    
     int ret = 0;
     if(err == 0) {
         char *etag = dav_get_string_property(remote, "D:getetag");
         char *hash = sync_get_content_hash(remote);
         
+        if(res->link_target_db || link) {
+            ret = nullstrcmp(res->link_target_db, link);
+            if(ret && equal) {
+                *equal = !nullstrcmp(res->link_target, link);
+            }
+            return ret;
+        }
+        
         if(hash && res->hash && equal) {
             // if requested, check if the local and remote res are equal
             if(!strcmp(hash, res->hash)) {
--- a/test/bin-test/test-dav-sync-symlink1.sh	Sat Nov 23 17:49:18 2019 +0100
+++ b/test/bin-test/test-dav-sync-symlink1.sh	Sun Nov 24 12:40:28 2019 +0100
@@ -265,3 +265,107 @@
 check_tmpout "0 errors" "test 6: wrong error counter (pull)"
 check_tmpout "intern1" "test 6: intern1 not updated (pull)"
 
+
+# ----------------------------------------------------------------------------
+# test 7: change intern1 target on both sides
+# expected result: conflict
+
+# preparation: add regular files on both sides and sync
+
+echo "test7-new2a" > tmp-sync/test7a/new2a
+echo "test7-new2b" > tmp-sync/test7b/new2b
+
+dav_sync_push test7a "test 7: push a failed"
+check_tmpout "1 file pushed" "test 7: wrong push counter (push a)"
+check_tmpout "0 conflicts" "test 7: wrong conflict counter (push a)"
+check_tmpout "0 errors" "test 7: wrong error counter (push a)"
+
+dav_sync_push test7b "test 7: push b failed"
+check_tmpout "1 file pushed" "test 7: wrong push counter (push b)"
+check_tmpout "0 conflicts" "test 7: wrong conflict counter (push b)"
+check_tmpout "0 errors" "test 7: wrong error counter (push b)"
+
+dav_sync_pull test7a "test 7: pull a failed"
+check_tmpout "1 file pulled" "test 7: wrong pull counter (pull a)"
+check_tmpout "0 conflicts" "test 7: wrong conflict counter (pull a)"
+check_tmpout "0 errors" "test 7: wrong error counter (pull a)"
+
+dav_sync_pull test7b "test 7: pull b failed"
+check_tmpout "1 file pulled" "test 7: wrong pull counter (pull b)"
+check_tmpout "0 conflicts" "test 7: wrong conflict counter (pull b)"
+check_tmpout "0 errors" "test 7: wrong error counter (pull b)"
+
+# test: change symlinks
+
+rm -f tmp-sync/test7a/intern1
+ln -s -r tmp-sync/test7a/new2a tmp-sync/test7a/intern1
+
+rm -f tmp-sync/test7b/intern1
+ln -s -r tmp-sync/test7b/new2b tmp-sync/test7b/intern1
+
+dav_sync_push test7a "test 7: push a failed (a)"
+check_tmpout "1 file pushed" "test 7: wrong push counter (push a 2)"
+check_tmpout "0 conflicts" "test 7: wrong conflict counter (push a 2)"
+check_tmpout "0 errors" "test 7: wrong error counter (push a 2)"
+check_tmpout "intern1" "test 7: intern1 not updated (push a 2)"
+
+dav_sync_push test7b "test 7: push b failed (b)"
+check_tmpout "1 conflict" "test 7: wrong conflict counter (push b 2)"
+check_tmpout "0 errors" "test 7: wrong error counter (push b 2)"
+
+
+# ----------------------------------------------------------------------------
+# test 8: pull test7b
+# expected result: conflict
+
+dav_sync_pull test7b "test 8: pull failed"
+check_tmpout "1 file pulled" "test8: wrong pull counter (pull)"
+check_tmpout "1 conflict" "test 8: wrong conflict counter (pull)"
+check_tmpout "0 errors" "test 8: wrong error counter (pull)"
+
+$DAV_SYNC_BIN delete-conflicts test7b > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+	echo "test 8: delete-conflicts failed"
+	exit 2
+fi
+
+dav_sync_pull test7b "test 8: pull 2 failed"
+check_tmpout "0 files pulled" "test8: wrong pull counter (pull 2)"
+check_tmpout "0 conflicts" "test 8: wrong conflict counter (pull 2)"
+check_tmpout "0 errors" "test 8: wrong error counter (pull 2)"
+
+dav_sync_push test7b "test 8: push b failed (b)"
+check_tmpout "0 files pushed" "test 8: wrong push counter"
+check_tmpout "0 conflicts" "test 8: wrong conflict counter (push)"
+check_tmpout "0 errors" "test 8: wrong error counter (push)"
+
+
+# ----------------------------------------------------------------------------
+# test 9: add new link on both sides
+# expected result: conflict
+
+ln -s -r tmp-sync/test7a/new2a tmp-sync/test7a/newlink1
+ln -s -r tmp-sync/test7b/new2b tmp-sync/test7b/newlink1
+
+dav_sync_push test7a "test 9: push a failed (a)"
+check_tmpout "1 file pushed" "test 9: wrong push counter (push a)"
+check_tmpout "0 conflicts" "test 9: wrong conflict counter (push a)"
+check_tmpout "0 errors" "test 9: wrong error counter (push a)"
+check_tmpout "newlink1" "test 9: intern1 not updated (push a)"
+
+dav_sync_push test7b "test 9: push b failed (b)"
+check_tmpout "1 conflict" "test 9: wrong conflict counter (push b)"
+check_tmpout "0 errors" "test 9: wrong error counter (push b)"
+
+# pull
+
+dav_sync_pull test7b "test 9: pull failed"
+check_tmpout "1 file pulled" "test9: wrong pull counter (pull)"
+check_tmpout "1 conflict" "test 9: wrong conflict counter (pull)"
+check_tmpout "0 errors" "test 9: wrong error counter (pull)"
+
+$DAV_SYNC_BIN delete-conflicts test7b > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+	echo "test 9: delete-conflicts failed"
+	exit 2
+fi
--- a/test/bin-test/test-dav.sh	Sat Nov 23 17:49:18 2019 +0100
+++ b/test/bin-test/test-dav.sh	Sun Nov 24 12:40:28 2019 +0100
@@ -51,6 +51,9 @@
 	exit 1
 fi
 
+# clear test repo
+dav rm dav-test-repo/tests > /dev/null 2>&1
+
 do_test()
 {
 	printf "TEST: $1 ... "

mercurial