LCOV - code coverage report
Current view: top level - lib/util/tests - test_util.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 183 192 95.3 %
Date: 2024-04-21 15:09:00 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *
       4             :  *  Unit test for util.c
       5             :  *
       6             :  *  Copyright (C) Christof Schmitt 2020
       7             :  *  Copyright (C) Andreas Schneider 2020
       8             :  *
       9             :  *  This program is free software; you can redistribute it and/or modify
      10             :  *  it under the terms of the GNU General Public License as published by
      11             :  *  the Free Software Foundation; either version 3 of the License, or
      12             :  *  (at your option) any later version.
      13             :  *
      14             :  *  This program is distributed in the hope that it will be useful,
      15             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :  *  GNU General Public License for more details.
      18             :  *
      19             :  *  You should have received a copy of the GNU General Public License
      20             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      21             :  */
      22             : 
      23             : #include <stdarg.h>
      24             : #include <stddef.h>
      25             : #include <stdint.h>
      26             : #include <setjmp.h>
      27             : #include <cmocka.h>
      28             : 
      29             : #include "lib/replace/replace.h"
      30             : #include "system/dir.h"
      31             : 
      32             : #include "lib/util/util.c"
      33             : 
      34             : struct test_paths {
      35             :         char testdir[PATH_MAX];
      36             :         char none[PATH_MAX];
      37             :         char dir[PATH_MAX];
      38             :         char dir_recursive[PATH_MAX];
      39             :         mode_t dir_mode;
      40             :         char file[PATH_MAX];
      41             :         mode_t file_mode;
      42             :         char symlink_none[PATH_MAX];
      43             :         char symlink_dir[PATH_MAX];
      44             :         char symlink_file[PATH_MAX];
      45             : };
      46             : 
      47           1 : static int group_setup(void **state)
      48             : {
      49           1 :         struct test_paths *paths = NULL;
      50           1 :         char *testdir = NULL;
      51           1 :         int ret, fd;
      52             : 
      53           1 :         umask(0);
      54             : 
      55           1 :         paths = malloc(sizeof(struct test_paths));
      56           1 :         assert_non_null(paths);
      57             : 
      58           1 :         strlcpy(paths->testdir, tmpdir(), sizeof(paths->testdir));
      59           1 :         strlcat(paths->testdir, "/test_util_XXXXXX", sizeof(paths->testdir));
      60           1 :         testdir = mkdtemp(paths->testdir);
      61           1 :         assert_non_null(testdir);
      62             : 
      63           1 :         strlcpy(paths->none, testdir, sizeof(paths->none));
      64           1 :         strlcat(paths->none, "/none", sizeof(paths->none));
      65             : 
      66           1 :         strlcpy(paths->dir, testdir, sizeof(paths->dir));
      67           1 :         strlcat(paths->dir, "/dir", sizeof(paths->dir));
      68           1 :         paths->dir_mode = 0750;
      69           1 :         ret = mkdir(paths->dir, paths->dir_mode);
      70           1 :         assert_return_code(ret, errno);
      71             : 
      72           1 :         strlcpy(paths->dir_recursive, testdir, sizeof(paths->dir));
      73           1 :         strlcat(paths->dir_recursive, "/dir_recursive", sizeof(paths->dir));
      74           1 :         paths->dir_mode = 0750;
      75           1 :         ret = mkdir(paths->dir_recursive, paths->dir_mode);
      76           1 :         assert_return_code(ret, errno);
      77             : 
      78           1 :         strlcpy(paths->file, testdir, sizeof(paths->file));
      79           1 :         strlcat(paths->file, "/file", sizeof(paths->file));
      80           1 :         paths->file_mode = 0640;
      81           1 :         fd = creat(paths->file, paths->file_mode);
      82           1 :         assert_return_code(fd, errno);
      83           1 :         ret = close(fd);
      84           1 :         assert_return_code(ret, errno);
      85             : 
      86           1 :         strlcpy(paths->symlink_none, testdir, sizeof(paths->symlink_none));
      87           1 :         strlcat(paths->symlink_none, "/symlink_none",
      88             :                 sizeof(paths->symlink_none));
      89           1 :         ret = symlink("/none", paths->symlink_none);
      90           1 :         assert_return_code(ret, errno);
      91             : 
      92           1 :         strlcpy(paths->symlink_dir, testdir, sizeof(paths->symlink_dir));
      93           1 :         strlcat(paths->symlink_dir, "/symlink_dir", sizeof(paths->symlink_dir));
      94           1 :         ret = symlink(paths->dir, paths->symlink_dir);
      95           1 :         assert_return_code(ret, errno);
      96             : 
      97           1 :         strlcpy(paths->symlink_file, testdir, sizeof(paths->symlink_file));
      98           1 :         strlcat(paths->symlink_file, "/symlink_file",
      99             :                 sizeof(paths->symlink_file));
     100           1 :         ret = symlink(paths->file, paths->symlink_file);
     101           1 :         assert_return_code(ret, errno);
     102             : 
     103           1 :         *state = paths;
     104             : 
     105           1 :         return 0;
     106             : }
     107             : 
     108           3 : static int torture_rmdirs(const char *path)
     109             : {
     110           3 :         DIR *d;
     111           3 :         struct dirent *dp;
     112           3 :         struct stat sb;
     113           3 :         char *fname;
     114             : 
     115           3 :         if ((d = opendir(path)) != NULL) {
     116           6 :                 while(stat(path, &sb) == 0) {
     117             :                         /* if we can remove the directory we're done */
     118           6 :                         if (rmdir(path) == 0) {
     119             :                                 break;
     120             :                         }
     121           3 :                         switch (errno) {
     122             :                                 case ENOTEMPTY:
     123             :                                 case EEXIST:
     124             :                                 case EBADF:
     125             :                                         break; /* continue */
     126           0 :                                 default:
     127           0 :                                         closedir(d);
     128           0 :                                         return 0;
     129             :                         }
     130             : 
     131          13 :                         while ((dp = readdir(d)) != NULL) {
     132          10 :                                 size_t len;
     133             :                                 /* skip '.' and '..' */
     134          10 :                                 if (dp->d_name[0] == '.' &&
     135           6 :                                                 (dp->d_name[1] == '\0' ||
     136           3 :                                                  (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) {
     137           6 :                                         continue;
     138             :                                 }
     139             : 
     140           4 :                                 len = strlen(path) + strlen(dp->d_name) + 2;
     141           4 :                                 fname = malloc(len);
     142           4 :                                 if (fname == NULL) {
     143           0 :                                         closedir(d);
     144           0 :                                         return -1;
     145             :                                 }
     146           4 :                                 snprintf(fname, len, "%s/%s", path, dp->d_name);
     147             : 
     148             :                                 /* stat the file */
     149           4 :                                 if (lstat(fname, &sb) != -1) {
     150           4 :                                         if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
     151           4 :                                                 if (rmdir(fname) < 0) { /* can't be deleted */
     152           2 :                                                         if (errno == EACCES) {
     153           0 :                                                                 closedir(d);
     154           0 :                                                                 SAFE_FREE(fname);
     155           0 :                                                                 return -1;
     156             :                                                         }
     157           2 :                                                         torture_rmdirs(fname);
     158             :                                                 }
     159             :                                         } else {
     160           0 :                                                 unlink(fname);
     161             :                                         }
     162             :                                 } /* lstat */
     163          17 :                                 SAFE_FREE(fname);
     164             :                         } /* readdir */
     165             : 
     166           3 :                         rewinddir(d);
     167             :                 }
     168             :         } else {
     169             :                 return -1;
     170             :         }
     171             : 
     172           3 :         closedir(d);
     173           3 :         return 0;
     174             : }
     175             : 
     176           1 : static int group_teardown(void **state)
     177             : {
     178           1 :         struct test_paths *paths = *state;
     179           1 :         int ret;
     180             : 
     181           1 :         ret = unlink(paths->file);
     182           1 :         assert_return_code(ret, errno);
     183             : 
     184           1 :         ret = unlink(paths->symlink_none);
     185           1 :         assert_return_code(ret, errno);
     186             : 
     187           1 :         ret = unlink(paths->symlink_dir);
     188           1 :         assert_return_code(ret, errno);
     189             : 
     190           1 :         ret = unlink(paths->symlink_file);
     191           1 :         assert_return_code(ret, errno);
     192             : 
     193           1 :         ret = torture_rmdirs(paths->testdir);
     194           1 :         assert_return_code(ret, errno);
     195             : 
     196           1 :         free(paths);
     197           1 :         return 0;
     198             : }
     199             : 
     200           1 : static void test_directory_create_or_exists_none(void **state)
     201             : {
     202           1 :         struct test_paths *paths = *state;
     203           1 :         bool b;
     204           1 :         struct stat sbuf;
     205           1 :         int ret;
     206             : 
     207           1 :         b = directory_create_or_exist(paths->none, 0775);
     208           1 :         assert_true(b);
     209             : 
     210           1 :         ret = lstat(paths->none, &sbuf);
     211           1 :         assert_return_code(ret, errno);
     212           1 :         assert_int_equal(sbuf.st_mode & 0777, 0775);
     213           1 :         assert_true(S_ISDIR(sbuf.st_mode));
     214           1 : }
     215             : 
     216           1 : static int teardown_none_directory(void **state)
     217             : {
     218           1 :         struct test_paths *paths = *state;
     219             : 
     220           1 :         rmdir(paths->none);
     221           1 :         return 0;
     222             : }
     223             : 
     224           1 : static void test_directory_create_or_exists_dir(void **state)
     225             : {
     226           1 :         struct test_paths *paths = *state;
     227           1 :         bool b;
     228           1 :         struct stat sbuf;
     229           1 :         int ret;
     230             : 
     231           1 :         b = directory_create_or_exist(paths->dir, 770);
     232           1 :         assert_true(b);
     233             : 
     234           1 :         ret = lstat(paths->dir, &sbuf);
     235           1 :         assert_return_code(ret, errno);
     236           1 :         assert_int_equal(sbuf.st_mode & 0777, paths->dir_mode);
     237           1 :         assert_true(S_ISDIR(sbuf.st_mode));
     238           1 : }
     239             : 
     240           1 : static void test_directory_create_or_exists_file(void **state)
     241             : {
     242           1 :         struct test_paths *paths = *state;
     243           1 :         bool b;
     244           1 :         struct stat sbuf;
     245           1 :         int ret;
     246             : 
     247           1 :         b = directory_create_or_exist(paths->file, 770);
     248           1 :         assert_false(b);
     249             : 
     250           1 :         ret = lstat(paths->file, &sbuf);
     251           1 :         assert_return_code(ret, errno);
     252           1 :         assert_int_equal(sbuf.st_mode & 0777, paths->file_mode);
     253           1 :         assert_true(S_ISREG(sbuf.st_mode));
     254           1 : }
     255             : 
     256           1 : static void test_directory_create_or_exists_symlink_none(void **state)
     257             : {
     258           1 :         struct test_paths *paths = *state;
     259           1 :         bool b;
     260           1 :         struct stat sbuf;
     261           1 :         int ret;
     262             : 
     263           1 :         b = directory_create_or_exist(paths->symlink_none, 770);
     264           1 :         assert_false(b);
     265             : 
     266           1 :         ret = lstat(paths->symlink_none, &sbuf);
     267           1 :         assert_return_code(ret, errno);
     268           1 :         assert_int_equal(sbuf.st_mode & 0777, 0777);
     269           1 :         assert_true(S_ISLNK(sbuf.st_mode));
     270           1 : }
     271             : 
     272           1 : static void test_directory_create_or_exists_symlink_dir(void **state)
     273             : {
     274           1 :         struct test_paths *paths = *state;
     275           1 :         bool b;
     276           1 :         struct stat sbuf;
     277           1 :         int ret;
     278             : 
     279           1 :         b = directory_create_or_exist(paths->symlink_dir, 770);
     280           1 :         assert_true(b);
     281             : 
     282           1 :         ret = lstat(paths->symlink_dir, &sbuf);
     283           1 :         assert_return_code(ret, errno);
     284           1 :         assert_int_equal(sbuf.st_mode & 0777, 0777);
     285           1 :         assert_true(S_ISLNK(sbuf.st_mode));
     286           1 : }
     287             : 
     288           1 : static void test_directory_create_or_exists_symlink_file(void **state)
     289             : {
     290           1 :         struct test_paths *paths = *state;
     291           1 :         bool b;
     292           1 :         struct stat sbuf;
     293           1 :         int ret;
     294             : 
     295           1 :         b = directory_create_or_exist(paths->symlink_file, 770);
     296           1 :         assert_false(b);
     297             : 
     298           1 :         ret = lstat(paths->symlink_file, &sbuf);
     299           1 :         assert_return_code(ret, errno);
     300           1 :         assert_int_equal(sbuf.st_mode & 0777, 0777);
     301           1 :         assert_true(S_ISLNK(sbuf.st_mode));
     302           1 : }
     303             : 
     304           1 : static void test_directory_create_or_exists_recursive(void **state)
     305             : {
     306           1 :         struct test_paths *paths = *state;
     307           1 :         char recursive_testdir[PATH_MAX] = {0};
     308           1 :         struct stat sbuf = {0};
     309           1 :         bool ok;
     310           1 :         int ret;
     311             : 
     312           1 :         ret = snprintf(recursive_testdir,
     313             :                        sizeof(recursive_testdir),
     314             :                        "%s/wurst/brot",
     315           1 :                        paths->dir_recursive);
     316           1 :         assert_int_not_equal(ret, -1);
     317             : 
     318           1 :         ok = directory_create_or_exists_recursive(recursive_testdir,
     319             :                                                   0700);
     320           1 :         assert_true(ok);
     321             : 
     322           1 :         ret = lstat(recursive_testdir, &sbuf);
     323           1 :         assert_return_code(ret, errno);
     324           1 :         assert_int_equal(sbuf.st_mode & 0777, 0700);
     325           1 :         assert_true(S_ISDIR(sbuf.st_mode));
     326           1 : }
     327             : 
     328           1 : int main(int argc, char **argv)
     329             : {
     330           1 :         const struct CMUnitTest tests[] = {
     331             :                 cmocka_unit_test_teardown(test_directory_create_or_exists_none,
     332             :                                           teardown_none_directory),
     333             :                 cmocka_unit_test(test_directory_create_or_exists_dir),
     334             :                 cmocka_unit_test(test_directory_create_or_exists_file),
     335             :                 cmocka_unit_test(test_directory_create_or_exists_symlink_none),
     336             :                 cmocka_unit_test(test_directory_create_or_exists_symlink_dir),
     337             :                 cmocka_unit_test(test_directory_create_or_exists_symlink_file),
     338             :                 cmocka_unit_test(test_directory_create_or_exists_recursive),
     339             :         };
     340             : 
     341           1 :         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
     342             : 
     343           1 :         return cmocka_run_group_tests(tests, group_setup, group_teardown);
     344             : }

Generated by: LCOV version 1.14