/
githubmirror
/
librepo
Обзор
Документация
Войти
/
githubmirror
/
librepo
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/test_checksum.c
308 строк
11 KB
Jaroslav Rohel
Define and use xattr key to store mtime of file checksum as macro
29 апр 2024, 16:51
29 апр 2024, 16:51
fbfb2b7
Код
Авторство
О чём код?
#define _POSIX_C_SOURCE 200809L #define _GNU_SOURCE #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/xattr.h> #include <fcntl.h> #include "librepo/util.h" #include "librepo/checksum.h" #include "librepo/xattr_internal.h" #include "fixtures.h" #include "testsys.h" #include "test_checksum.h" #define CHKS_CONTENT_00 "" #define CHKS_VAL_00_MD5 "d41d8cd98f00b204e9800998ecf8427e" #define CHKS_VAL_00_SHA1 "da39a3ee5e6b4b0d3255bfef95601890afd80709" #define CHKS_VAL_00_SHA224 "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" #define CHKS_VAL_00_SHA256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" #define CHKS_VAL_00_SHA384 "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" #define CHKS_VAL_00_SHA512 "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" #define CHKS_CONTENT_01 "foo\nbar\n\n" #define CHKS_VAL_01_MD5 "8b03476e0c92a803ed47e0817b2717ed" #define CHKS_VAL_01_SHA1 "db957786773c3b2ae5fc2d2c839bab1bbe5dc09e" #define CHKS_VAL_01_SHA224 "00f288c08f7f745d59252f875007b6734bb2f0aac295463cf242aac0" #define CHKS_VAL_01_SHA256 "242218bd1466c1ab22e501d1e86bc906bacfd6943ded790ea8b2b040e618d81b" #define CHKS_VAL_01_SHA384 "1f9d03f7a9fc1c22bfe114e2b58c334fcf58a07df78b4b0e942a28582ebf6489823e242492b2e0e5df1ce995e918c80d" #define CHKS_VAL_01_SHA512 "704861d613afe433160d9b5aa6870e0dd96f5e56c4976f1fe39f4f648e37517ad7374209034290284949b4218ab0c8d8860f941c884cad47a61f208803128049" static void build_test_file(const char *filename, const char *content) { FILE *fp = fopen(filename, "w"); size_t len = strlen(content); ck_assert_ptr_nonnull(fp); ck_assert(fwrite(content, 1, len, fp) == len); fclose(fp); } static void test_checksum(const char *filename, LrChecksumType ch_type, char *expected) { int fd; char *checksum; GError *tmp_err = NULL; fd = open(filename, O_RDONLY); ck_assert_int_ge(fd, 0); checksum = lr_checksum_fd(ch_type, fd, &tmp_err); ck_assert_ptr_nonnull(checksum); ck_assert_ptr_null(tmp_err); ck_assert_msg(!strcmp(checksum, expected), "Checksum is %s instead of %s", checksum, expected); lr_free(checksum); close(fd); } START_TEST(test_checksum_fd) { char *file; file = lr_pathconcat(test_globals.tmpdir, "/test_checksum", NULL); /* Empty file */ build_test_file(file, CHKS_CONTENT_00); test_checksum(file, LR_CHECKSUM_MD5, CHKS_VAL_00_MD5); test_checksum(file, LR_CHECKSUM_SHA1, CHKS_VAL_00_SHA1); test_checksum(file, LR_CHECKSUM_SHA224, CHKS_VAL_00_SHA224); test_checksum(file, LR_CHECKSUM_SHA256, CHKS_VAL_00_SHA256); test_checksum(file, LR_CHECKSUM_SHA384, CHKS_VAL_00_SHA384); test_checksum(file, LR_CHECKSUM_SHA512, CHKS_VAL_00_SHA512); /* File with some content */ build_test_file(file, CHKS_CONTENT_01); test_checksum(file, LR_CHECKSUM_MD5, CHKS_VAL_01_MD5); test_checksum(file, LR_CHECKSUM_SHA1, CHKS_VAL_01_SHA1); test_checksum(file, LR_CHECKSUM_SHA224, CHKS_VAL_01_SHA224); test_checksum(file, LR_CHECKSUM_SHA256, CHKS_VAL_01_SHA256); test_checksum(file, LR_CHECKSUM_SHA384, CHKS_VAL_01_SHA384); test_checksum(file, LR_CHECKSUM_SHA512, CHKS_VAL_01_SHA512); ck_assert_msg(remove(file) == 0, "Cannot delete temporary test file"); g_free(file); } END_TEST START_TEST(test_cached_checksum_matches) { FILE *f; int fd, ret; gboolean checksum_ret, matches; ssize_t attr_ret; char *filename; static char *expected = "d78931fcf2660108eec0d6674ecb4e02401b5256a6b5ee82527766ef6d198c67"; struct stat st; char buf[256]; GError *tmp_err = NULL; gchar *checksum_key = g_strconcat(XATTR_CHKSUM_PREFIX, "sha256", NULL); gchar *mtime_str = NULL; filename = lr_pathconcat(test_globals.tmpdir, "/test_checksum_matches", NULL); f = fopen(filename, "w"); ck_assert_ptr_nonnull(f); fwrite("foo\nbar\n", 1, 8, f); fclose(f); // Assert no cached checksum exists attr_ret = GETXATTR(filename, XATTR_CHKSUM_MTIME, &buf, sizeof(buf)-1); ck_assert(attr_ret == -1); // Cached timestamp should not exists attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)-1); ck_assert(attr_ret == -1); // Cached checksum should not exists // Calculate checksum fd = open(filename, O_RDONLY); ck_assert_int_ge(fd, 0); checksum_ret = lr_checksum_fd_cmp(LR_CHECKSUM_SHA256, fd, expected, 1, &matches, &tmp_err); ck_assert_ptr_null(tmp_err); ck_assert(checksum_ret); ck_assert(matches); close(fd); // Assert cached checksum exists attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)-1); if (attr_ret == -1) { // Error encountered if (errno == ENOTSUP) { // Extended attributes are not supported goto exit_label; } // Any other errno means fail ck_assert(attr_ret != -1); } else { buf[attr_ret] = 0; ck_assert_str_eq(buf, expected); } // stored timestamp matches the file mtime ret = stat(filename, &st); ck_assert_int_eq(ret, 0); long long timestamp = st.st_mtime; timestamp *= 1000000000; //convert sec timestamp to nanosec timestamp timestamp += st.st_mtim.tv_nsec; mtime_str = g_strdup_printf("%lli", timestamp); attr_ret = GETXATTR(filename, XATTR_CHKSUM_MTIME, &buf, sizeof(buf)-1); ck_assert(attr_ret != -1); buf[attr_ret] = 0; ck_assert_str_eq(buf, mtime_str); // Calculate checksum again (cached shoud be used this time) fd = open(filename, O_RDONLY); ck_assert_int_ge(fd, 0); checksum_ret = lr_checksum_fd_cmp(LR_CHECKSUM_SHA256, fd, expected, 1, &matches, &tmp_err); ck_assert_ptr_null(tmp_err); ck_assert(checksum_ret); ck_assert(matches); close(fd); exit_label: lr_free(filename); lr_free(checksum_key); lr_free(mtime_str); } END_TEST START_TEST(test_cached_checksum_value) { FILE *f; int fd; gboolean checksum_ret, matches; ssize_t attr_ret; char *filename; static char *expected = "d78931fcf2660108eec0d6674ecb4e02401b5256a6b5ee82527766ef6d198c67"; char buf[256]; GError *tmp_err = NULL; gchar *checksum_key = g_strconcat(XATTR_CHKSUM_PREFIX, "sha256", NULL); gchar *mtime_str = NULL; gchar *calculated = NULL; filename = lr_pathconcat(test_globals.tmpdir, "/test_checksum_value", NULL); f = fopen(filename, "w"); ck_assert_ptr_nonnull(f); fwrite("foo\nbar\n", 1, 8, f); fclose(f); // Assert no cached checksum exists attr_ret = GETXATTR(filename, XATTR_CHKSUM_MTIME, &buf, sizeof(buf)-1); ck_assert(attr_ret == -1); // Cached timestamp should not exists attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)-1); ck_assert(attr_ret == -1); // Cached checksum should not exists // Calculate checksum fd = open(filename, O_RDONLY); ck_assert_int_ge(fd, 0); checksum_ret = lr_checksum_fd_compare(LR_CHECKSUM_SHA256, fd, "", 1, &matches, &calculated, &tmp_err); ck_assert_ptr_null(tmp_err); ck_assert(checksum_ret); // We pass in an empty string for expected, so we must not match. ck_assert(!matches); close(fd); ck_assert_str_eq(calculated, expected); // Assert no cached checksum exists // This assumes issue #235 is unresolved. Once it is, this code // should fail and the test will need updated. attr_ret = GETXATTR(filename, XATTR_CHKSUM_MTIME, &buf, sizeof(buf)-1); ck_assert(attr_ret == -1); // Cached timestamp should not exists attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)-1); ck_assert(attr_ret == -1); // Cached checksum should not exists lr_free(calculated); g_free(filename); g_free(checksum_key); lr_free(mtime_str); } END_TEST START_TEST(test_cached_checksum_clear) { FILE *f; int fd; ssize_t attr_ret; char *filename; char buf[256]; gchar *checksum_key = g_strconcat(XATTR_CHKSUM_PREFIX, "sha256", NULL); const char *other_key = "user.Other.Attribute"; const char *value = "some value"; filename = lr_pathconcat(test_globals.tmpdir, "/test_checksum_clear", NULL); f = fopen(filename, "w"); ck_assert_ptr_nonnull(f); fclose(f); // set extended attributes fd = open(filename, O_RDONLY); ck_assert_int_ge(fd, 0); attr_ret = FSETXATTR(fd, XATTR_CHKSUM_MTIME, value, strlen(value), 0); if (attr_ret == -1) { if (errno == ENOTSUP) { goto cleanup; } ck_assert(attr_ret != -1); } attr_ret = FSETXATTR(fd, checksum_key, value, strlen(value), 0); ck_assert(attr_ret != -1); attr_ret = FSETXATTR(fd, other_key, value, strlen(value), 0); ck_assert(attr_ret != -1); // verify that xattrs are set attr_ret = GETXATTR(filename, XATTR_CHKSUM_MTIME, &buf, sizeof(buf)); ck_assert(attr_ret != -1); attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)); ck_assert(attr_ret != -1); attr_ret = GETXATTR(filename, other_key, &buf, sizeof(buf)); ck_assert(attr_ret != -1); lr_checksum_clear_cache(fd); // verify that checksum xattrs are removed attr_ret = GETXATTR(filename, XATTR_CHKSUM_MTIME, &buf, sizeof(buf)); ck_assert(attr_ret == -1); attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)); ck_assert(attr_ret == -1); // other then checksum related attributes are not removed attr_ret = GETXATTR(filename, other_key, &buf, sizeof(buf)); ck_assert(attr_ret != -1); cleanup: close(fd); g_free(filename); g_free(checksum_key); } END_TEST Suite * checksum_suite(void) { Suite *s = suite_create("checksum"); TCase *tc = tcase_create("Main"); tcase_add_test(tc, test_checksum_fd); tcase_add_test(tc, test_cached_checksum_matches); tcase_add_test(tc, test_cached_checksum_value); tcase_add_test(tc, test_cached_checksum_clear); suite_add_tcase(s, tc); return s; }