Fix bug when comparing chunks and add test case.
authorJonathan Dieter <jdieter@gmail.com>
Fri, 28 Dec 2018 22:13:41 +0000 (22:13 +0000)
committerJonathan Dieter <jdieter@gmail.com>
Fri, 28 Dec 2018 22:13:41 +0000 (22:13 +0000)
Signed-off-by: Jonathan Dieter <jdieter@gmail.com>
src/lib/dl/dl.c
test/copy_chunks.c [new file with mode: 0644]
test/files/LICENSE.header.new.nodict.fodt.zck [new file with mode: 0644]
test/files/LICENSE.nodict.fodt.zck
test/meson.build

index 5f18afa1d25283d7c7e2aa78f3be310e1d13d2f4..e5e1e5702c92b0d66964531bd6fecf7675367179 100644 (file)
@@ -238,7 +238,6 @@ bool PUBLIC zck_copy_chunks(zckCtx *src, zckCtx *tgt) {
     zckIndex *tgt_info = &(tgt->index);
     zckIndex *src_info = &(src->index);
     zckChunk *tgt_idx = tgt_info->first;
-    zckChunk *src_idx = src_info->first;
     while(tgt_idx) {
         /* No need to copy already valid chunk */
         if(tgt_idx->valid == 1) {
@@ -247,10 +246,10 @@ bool PUBLIC zck_copy_chunks(zckCtx *src, zckCtx *tgt) {
         }
         zckChunk *f = NULL;
 
-        HASH_FIND(hh, src_info->ht, src_idx->digest, src_idx->digest_size, f);
+        HASH_FIND(hh, src_info->ht, tgt_idx->digest, tgt_idx->digest_size, f);
         if(f && f->length == tgt_idx->length &&
            f->comp_length == tgt_idx->comp_length)
-            write_and_verify_chunk(src, tgt, src_idx, tgt_idx);
+            write_and_verify_chunk(src, tgt, f, tgt_idx);
         tgt_idx = tgt_idx->next;
     }
     return true;
diff --git a/test/copy_chunks.c b/test/copy_chunks.c
new file mode 100644 (file)
index 0000000..f5d78c8
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2018 Jonathan Dieter <jdieter@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <zck.h>
+#include <libgen.h>
+#include "zck_private.h"
+#include "util.h"
+
+int main (int argc, char *argv[]) {
+    zck_set_log_level(ZCK_LOG_DEBUG);
+    char *path = zmalloc(strlen(argv[1]));
+    strcpy(path, argv[1]);
+
+    char *base_name = basename(path);
+    int in = open(argv[1], O_RDONLY);
+    if(in < 0) {
+        perror("Unable to open LICENSE.header.new.nodict.fodt.zck for reading");
+        exit(1);
+    }
+    int tgt = open(base_name, O_RDWR | O_CREAT, 0644);
+    if(tgt < 0) {
+        perror("Unable to open LICENSE.header.new.nodict.fodt.zck for writing");
+        exit(1);
+    }
+    char buffer[4096] = {0};
+    int len = 0;
+    while((len=read(in, buffer, 4096)) > 0) {
+        if(write(tgt, buffer, len) < len) {
+            perror("Unable to write to LICENSE.header.new.nodict.fodt.zck");
+            exit(1);
+        }
+    }
+    lseek(tgt, 0, SEEK_SET);
+
+    /* Open target zchunk header and read */
+    zckCtx *tgt_zck = zck_create();
+    if(tgt_zck == NULL)
+        exit(1);
+    if(!zck_init_adv_read(tgt_zck, tgt)) {
+        printf("%s", zck_get_error(tgt_zck));
+        exit(1);
+    }
+
+    /* Open source zchunk file and read header */
+    int src = open(argv[2], O_RDONLY);
+    if(src < 0) {
+        perror("Unable to open LICENSE.nodict.fodt.zck for reading");
+        exit(1);
+    }
+
+    zckCtx *src_zck = zck_create();
+    if(src_zck == NULL)
+        exit(1);
+    if(!zck_init_read(src_zck, src)) {
+        printf("%s", zck_get_error(src_zck));
+        exit(1);
+    }
+
+    if(!zck_read_lead(tgt_zck) || !zck_read_header(tgt_zck)) {
+        printf("%s", zck_get_error(tgt_zck));
+        exit(1);
+    }
+    if(zck_find_valid_chunks(tgt_zck) > 0) {
+        printf("All chunks were valid, but the target shouldn't have any "
+               "chunks\n");
+        exit(1);
+    }
+    int out = zck_copy_chunks(src_zck, tgt_zck);
+    if(!out) {
+        printf("%i: %s%s\n", out, zck_get_error(src_zck), zck_get_error(tgt_zck));
+        exit(1);
+    }
+    zck_reset_failed_chunks(tgt_zck);
+    printf("Missing chunks: %i\n", zck_missing_chunks(tgt_zck));
+    if(zck_missing_chunks(tgt_zck) != 1) {
+        printf("Should be only one chunk missing");
+        exit(1);
+    }
+
+    if(zck_close(tgt_zck)) {
+        printf("Should have run into an error closing "
+               "LICENSE.header.new.nodict.fodt.zck");
+        exit(1);
+    }
+
+    zck_free(&tgt_zck);
+    zck_free(&src_zck);
+    return 0;
+}
diff --git a/test/files/LICENSE.header.new.nodict.fodt.zck b/test/files/LICENSE.header.new.nodict.fodt.zck
new file mode 100644 (file)
index 0000000..550eade
Binary files /dev/null and b/test/files/LICENSE.header.new.nodict.fodt.zck differ
index d46b68db0cf5cd2d02530252a07d2705922de3fb..06172a01a5be4eb0f3b5a13b2d0a99f9b587e06c 100644 (file)
Binary files a/test/files/LICENSE.nodict.fodt.zck and b/test/files/LICENSE.nodict.fodt.zck differ
index 386f9b0a35bf2b6a950ae59efd37db5f102d556b..d010b92a712a2eec997e3074c93273aa5c4311a7 100644 (file)
@@ -7,6 +7,10 @@ empty = executable('empty', ['empty.c'] + util_sources,
 optelems = executable('optelems', ['optelems.c'] + util_sources,
                      include_directories: incdir,
                      dependencies: [zstd_dep, openssl_dep])
+copy_chunks = executable('copy_chunks', ['copy_chunks.c'] + util_sources,
+                     include_directories: incdir,
+                     dependencies: [zstd_dep, openssl_dep])
+
 invalid_input_checksum = executable('invalid_input_checksum',
                                     ['invalid_input_checksum.c'] + util_sources,
                                     include_directories: incdir,
@@ -139,6 +143,14 @@ test(
         'empty.zck'
     ]
 )
+test(
+    'copy chunks from source',
+    copy_chunks,
+    args: [
+        join_paths(file_path, 'LICENSE.header.new.nodict.fodt.zck'),
+        join_paths(file_path, 'LICENSE.nodict.fodt.zck')
+    ]
+)
 test(
     'decompress auto-chunked file - nocomp',
     shacheck,