1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
// -----------------------------------------------------------------------------
// Copyright (c) 2020-2023, PyInstaller Development Team.
//
// Distributed under the terms of the GNU General Public License (version 2
// or later) with exception for distributing the bootloader.
//
// The full license is in the file COPYING.txt, distributed with this software.
//
// SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
// -----------------------------------------------------------------------------
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "pyi_global.h"
#include "pyi_path.h"
#include <setjmp.h> // required fo cmocka :-(
#include <cmocka.h>
// NOTE: path separator is platform dependent, hence the use of PYI_SEPSTR
// and string concatenation...
static void test_dirname(void **state)
{
char result[PYI_PATH_MAX];
// pyi_path_dirname("/a1/bb/cc/dd") -> "/a1/bb/cc"
assert_true(pyi_path_dirname(result, PYI_SEPSTR "a1" PYI_SEPSTR "bb" PYI_SEPSTR "cc" PYI_SEPSTR "dd"));
assert_string_equal(result, PYI_SEPSTR "a1" PYI_SEPSTR "bb" PYI_SEPSTR "cc");
// pyi_path_dirname("/a2/bb/cc/dd/") -> "/a2/bb/cc"
assert_true(pyi_path_dirname(result, PYI_SEPSTR "a2" PYI_SEPSTR "bb" PYI_SEPSTR "cc" PYI_SEPSTR "dd" PYI_SEPSTR));
assert_string_equal(result, PYI_SEPSTR "a2" PYI_SEPSTR "bb" PYI_SEPSTR "cc");
// pyi_path_dirname("d3d") -> "."
assert_true(pyi_path_dirname(result, "d3d"));
assert_string_equal(result, PYI_CURDIRSTR);
// pyi_path_dirname("d5d/") -> "."
assert_true(pyi_path_dirname(result, "d5d" PYI_SEPSTR));
assert_string_equal(result, PYI_CURDIRSTR);
// pyi_path_dirname("") -> "."
assert_true(pyi_path_dirname(result, ""));
assert_string_equal(result, PYI_CURDIRSTR);
// Test correct handling of paths that exceed PYI_PATH_MAX
char *path2 = (char *) malloc(PYI_PATH_MAX+10);
memset(path2, 'a', PYI_PATH_MAX+8);
// a few bytes more
path2[PYI_PATH_MAX+8] = '\0';
assert_false(pyi_path_dirname(result, path2));
// exact length
path2[PYI_PATH_MAX] = '\0';
assert_false(pyi_path_dirname(result, path2));
// one byte less
path2[PYI_PATH_MAX-1] = '\0';
assert_true(pyi_path_dirname(result, path2));
}
static void test_basename(void **state)
{
char result[PYI_PATH_MAX];
char input[PYI_PATH_MAX];
// basename()'s second argument is not `const`, thus using a constant
// string yields to segmentation fault.
// pyi_path_basename("/aa/bb/cc/d1d") -> "d1d"
strcpy(input, PYI_SEPSTR "aa" PYI_SEPSTR "bb" PYI_SEPSTR "cc" PYI_SEPSTR "d1d");
pyi_path_basename(result, input);
assert_string_equal(result, "d1d");
// pyi_path_basename("d3dd") -> "d3dd"
strcpy(input, "d3dd");
pyi_path_basename(result, input);
assert_string_equal(result, "d3dd");
/* These cases are not correctly handled by our implementation of
* basename(). But this is okay, since we use basename() only to determine
* the application path based on argv[0].
*/
#if 0
// pyi_path_basename("/aa/bb/cc/d2d/") -> "d2d"
strcpy(input, PYI_SEPSTR "aa" PYI_SEPSTR "bb" PYI_SEPSTR "cc" PYI_SEPSTR "d2d" PYI_SEPSTR);
pyi_path_basename(result, input);
assert_string_equal(result, "d2d");
// pyi_path_basename("d4dd/") -> "d4dd"
strcpy(input, "d4dd" PYI_SEPSTR);
pyi_path_basename(result, input);
assert_string_equal(result, "d4dd");
// pyi_path_basename("") -> "."
strcpy(input, "");
pyi_path_basename(result, input);
assert_string_equal(result, PYI_CURDIRSTR);
#endif
}
static void test_join(void **state)
{
char path1[PYI_PATH_MAX];
char path2[PYI_PATH_MAX];
char result[PYI_PATH_MAX];
char *r;
// pyi_path_join("lalala", "mememe") -> "lalala/mememe"
r = pyi_path_join((char *)result, "lalala", "mememe");
assert_ptr_equal(r, &result);
assert_string_equal(result, "lalala" PYI_SEPSTR "mememe");
// pyi_path_join("lalala/", "mememe") -> "lalala/mememe"
r = pyi_path_join((char *)result, "lalala" PYI_SEPSTR, "mememe");
assert_ptr_equal(r, &result);
assert_string_equal(result, "lalala" PYI_SEPSTR "mememe");
// pyi_path_join("lalala/", "mememe/") -> "lalala/mememe"
r = pyi_path_join((char *)result, "lalala" PYI_SEPSTR, "mememe" PYI_SEPSTR);
assert_ptr_equal(r, &result);
assert_string_equal(result, "lalala" PYI_SEPSTR "mememe");
// pyi_path_join("lalala", "mememe/") -> "lalala/mememe"
r = pyi_path_join((char *)result, "lalala", "mememe" PYI_SEPSTR);
assert_ptr_equal(r, &result);
assert_string_equal(result, "lalala" PYI_SEPSTR "mememe");
// pyi_path_join("lal/ala", "mem/eme/") -> "lal/ala/meme/me"
r = pyi_path_join((char *)result, "lal" PYI_SEPSTR "ala" PYI_SEPSTR, "mem" PYI_SEPSTR "eme" PYI_SEPSTR);
assert_ptr_equal(r, &result);
assert_string_equal(result, "lal" PYI_SEPSTR "ala" PYI_SEPSTR "mem" PYI_SEPSTR "eme");
// First string empty is not handled:
// pyi_path_join("", "mememe") -> "/mememe"
r = pyi_path_join((char *)result, "", "mememe");
assert_ptr_equal(r, &result);
assert_string_equal(result, PYI_SEPSTR "mememe");
memset(path1, 'a', PYI_PATH_MAX); path1[PYI_PATH_MAX-1] = '\0';
memset(path2, 'b', PYI_PATH_MAX); path2[PYI_PATH_MAX-1] = '\0';
assert_int_equal(strlen(path1), PYI_PATH_MAX-1);
assert_int_equal(strlen(path2), PYI_PATH_MAX-1);
assert_ptr_equal(NULL, pyi_path_join(result, path1, path2));
// tests near max length of path1
assert_ptr_equal(NULL, pyi_path_join(result, path1, ""));
path1[PYI_PATH_MAX-2] = '\0';
assert_ptr_equal(NULL, pyi_path_join(result, path1, ""));
path1[PYI_PATH_MAX-3] = '\0';
assert_ptr_equal(r, pyi_path_join(result, path1, ""));
assert_int_equal(strlen(result), PYI_PATH_MAX-2); // -2 no trailing slash in path1
assert_ptr_equal(NULL, pyi_path_join(result, path1, "x"));
path1[PYI_PATH_MAX-4] = '\0';
assert_ptr_equal(r, pyi_path_join(result, path1, "x"));
assert_int_equal(strlen(result), PYI_PATH_MAX-2); // -2 no trailing slash in path1
assert_ptr_equal(NULL, pyi_path_join(result, path1, "xx"));
// tests near max length of path2
assert_ptr_equal(NULL, pyi_path_join(result, "", path2));
assert_ptr_equal(NULL, pyi_path_join(result, "x", path2));
path2[PYI_PATH_MAX-2] = '\0';
assert_ptr_equal(NULL, pyi_path_join(result, "", path2)); // stash takes space!
assert_ptr_equal(NULL, pyi_path_join(result, "x", path2));
path2[PYI_PATH_MAX-3] = '\0';
assert_ptr_equal(r, pyi_path_join(result, "", path2));
assert_ptr_equal(NULL, pyi_path_join(result, "x", path2));
path2[PYI_PATH_MAX-4] = '\0';
assert_ptr_equal(r, pyi_path_join(result, "", path2));
assert_ptr_equal(r, pyi_path_join(result, "x", path2));
// we don't count exactly if slashes are contained
assert_int_equal(strlen(result), PYI_PATH_MAX-2);
assert_ptr_equal(NULL, pyi_path_join(result, "xx", path2));
path2[PYI_PATH_MAX-4] = PYI_SEP;
assert_int_equal(path2[strlen(path2)], 0);
assert_int_equal(path2[strlen(path2)-1], PYI_SEP);
assert_ptr_equal(r, pyi_path_join(result, "", path2));
// we don't count exactly if slashes are contained
assert_int_equal(strlen(result), PYI_PATH_MAX-3);
assert_int_equal(result[strlen(result)-1], 'b'); // trailing slash removed
assert_ptr_equal(NULL, pyi_path_join(result, "x", path2));
}
#if defined(_WIN32)
int wmain(void)
#else
int main(void)
#endif
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_dirname),
cmocka_unit_test(test_basename),
cmocka_unit_test(test_join),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
|