mirror of
https://github.com/rizinorg/rizin.git
synced 2026-10-12 02:21:57 +00:00
237 lines
9.2 KiB
C
237 lines
9.2 KiB
C
// SPDX-FileCopyrightText: 2018 ret2libc <[email protected]>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_util.h>
|
|
#include "minunit.h"
|
|
|
|
bool test_file_slurp(void) {
|
|
|
|
#ifdef __WINDOWS__
|
|
#define S_IRWXU _S_IREAD | _S_IWRITE
|
|
#endif
|
|
|
|
const char *test_file = "./empty_file";
|
|
size_t s;
|
|
const char *some_words = "some words";
|
|
|
|
int f = open(test_file, O_CREAT, S_IRWXU);
|
|
mu_assert_neq(f, -1, "cannot create empty file");
|
|
close(f);
|
|
|
|
char *content = rz_file_slurp(test_file, &s);
|
|
mu_assert_notnull(content, "content should not be NULL");
|
|
mu_assert_eq(s, 0, "size should be zero");
|
|
mu_assert_eq(strlen(content), 0, "returned buffer should be empty");
|
|
free(content);
|
|
|
|
f = open(test_file, O_WRONLY, S_IRWXU);
|
|
mu_assert_neq(f, -1, "cannot reopen empty file");
|
|
rz_xwrite(f, some_words, strlen(some_words));
|
|
close(f);
|
|
|
|
content = rz_file_slurp(test_file, &s);
|
|
mu_assert_eq(s, strlen(some_words), "size should be correct");
|
|
mu_assert_eq(strlen(content), strlen(some_words), "size for the buffer should be correct");
|
|
mu_assert_streq(content, some_words, "content should match");
|
|
free(content);
|
|
|
|
unlink(test_file);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
#define test_leading_zeros_case(x, expect) \
|
|
mu_assert_eq(rz_bits_leading_zeros(x), expect, "should be " #expect)
|
|
|
|
bool test_leading_zeros(void) {
|
|
test_leading_zeros_case(0ULL, 64);
|
|
test_leading_zeros_case(1ULL, 63);
|
|
|
|
test_leading_zeros_case(0xffffffffffffffffULL, 0);
|
|
test_leading_zeros_case(0xffffffffULL, 32);
|
|
test_leading_zeros_case(0x80000000ULL, 32);
|
|
test_leading_zeros_case(0x100000000ULL, 31);
|
|
test_leading_zeros_case(0x40000000ULL, 33);
|
|
test_leading_zeros_case(0x400000000ULL, 29);
|
|
|
|
test_leading_zeros_case(0x1000000000000, 15);
|
|
test_leading_zeros_case(0x800000000000, 16);
|
|
test_leading_zeros_case(0x400000000000, 17);
|
|
test_leading_zeros_case(0x200000000000, 18);
|
|
test_leading_zeros_case(0x100000000000, 19);
|
|
mu_end;
|
|
}
|
|
|
|
bool test_path_prefix(void) {
|
|
size_t equal;
|
|
RzPath *sys_path = rz_path_new();
|
|
if (!sys_path) {
|
|
mu_assert_eq(1, 0, "initialization error");
|
|
}
|
|
const char *output = rz_path_prefix(sys_path);
|
|
equal = strcmp(output, RZ_PREFIX);
|
|
mu_assert_eq(equal, 0, "not equal");
|
|
rz_path_free(sys_path);
|
|
mu_end;
|
|
}
|
|
|
|
bool test_getopt_long_option(void) {
|
|
RzGetopt opt;
|
|
int c;
|
|
RzPVector cmd_catalog_values;
|
|
rz_pvector_init(&cmd_catalog_values, NULL);
|
|
rz_pvector_push(&cmd_catalog_values, "json");
|
|
enum {
|
|
TEST_LONG_CMD_CATALOG = RZ_GETOPT_LONG_BASE,
|
|
};
|
|
RzGetoptLong cmd_catalog = {
|
|
"cmd-catalog", TEST_LONG_CMD_CATALOG, &cmd_catalog_values, "json"
|
|
};
|
|
RzVector longopts;
|
|
rz_vector_init(&longopts, sizeof(RzGetoptLong), NULL, NULL);
|
|
rz_vector_push(&longopts, &cmd_catalog);
|
|
|
|
const char *argv_default[] = { "test", "--cmd-catalog" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_default), argv_default, "", &longopts);
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, TEST_LONG_CMD_CATALOG, "long option should return descriptor value");
|
|
mu_assert_streq(opt.arg, "json", "long option should use default value");
|
|
mu_assert_eq(opt.ind, RZ_ARRAY_SIZE(argv_default), "long option should be consumed");
|
|
|
|
const char *argv_arg[] = { "test", "--cmd-catalog", "json" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_arg), argv_arg, "", &longopts);
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, TEST_LONG_CMD_CATALOG, "long option with separated argument should return descriptor value");
|
|
mu_assert_streq(opt.arg, "json", "separated long option value should be available in opt.arg");
|
|
mu_assert_eq(opt.ind, RZ_ARRAY_SIZE(argv_arg), "long option with separated argument should consume option and value");
|
|
|
|
const char *argv_eq_arg[] = { "test", "--cmd-catalog=json" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_eq_arg), argv_eq_arg, "", &longopts);
|
|
opt.err = 0;
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, '?', "long option with inline argument should not be supported");
|
|
mu_assert_eq(opt.ind, RZ_ARRAY_SIZE(argv_eq_arg), "unsupported inline long option argument should be consumed");
|
|
|
|
const char *argv_bad_separated_arg[] = { "test", "--cmd-catalog", "yaml" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_bad_separated_arg), argv_bad_separated_arg, "", &longopts);
|
|
opt.err = 0;
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, '?', "unknown separated long option value should be rejected");
|
|
mu_assert_eq(opt.ind, RZ_ARRAY_SIZE(argv_bad_separated_arg), "long option with bad separated value should consume option and value");
|
|
|
|
const char *argv_next_option[] = { "test", "--cmd-catalog", "--cmd-catalog" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_next_option), argv_next_option, "", &longopts);
|
|
opt.err = 0;
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, '?', "long option should reject another long option as its value");
|
|
mu_assert_eq(opt.ind, 2, "invalid long-option value should not consume the next long option");
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, TEST_LONG_CMD_CATALOG, "unconsumed long option should be parsed next");
|
|
|
|
const char *argv_end[] = { "test", "--", "--cmd-catalog" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_end), argv_end, "", &longopts);
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, -1, "exact -- should end option parsing");
|
|
mu_assert_eq(opt.ind, 2, "exact -- should be consumed");
|
|
|
|
RzGetoptLong flag = { "flag", TEST_LONG_CMD_CATALOG, NULL, NULL };
|
|
RzVector flag_longopts;
|
|
rz_vector_init(&flag_longopts, sizeof(RzGetoptLong), NULL, NULL);
|
|
rz_vector_push(&flag_longopts, &flag);
|
|
const char *argv_flag[] = { "test", "--flag", "positional" };
|
|
rz_getopt_init_long(&opt, RZ_ARRAY_SIZE(argv_flag), argv_flag, "", &flag_longopts);
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, TEST_LONG_CMD_CATALOG, "flag long option should return descriptor value");
|
|
mu_assert_null(opt.arg, "flag long option should not have an argument");
|
|
mu_assert_eq(opt.ind, 2, "flag long option should not consume following argv entry");
|
|
|
|
const char *argv_compat[] = { "test", "--cmd-catalog" };
|
|
rz_getopt_init(&opt, RZ_ARRAY_SIZE(argv_compat), argv_compat, "-");
|
|
c = rz_getopt_next(&opt);
|
|
mu_assert_eq(c, -1, "long-option parsing should be opt-in");
|
|
mu_assert_eq(opt.ind, RZ_ARRAY_SIZE(argv_compat), "legacy -- handling should be preserved without longopts");
|
|
rz_vector_fini(&flag_longopts);
|
|
rz_vector_fini(&longopts);
|
|
rz_pvector_fini(&cmd_catalog_values);
|
|
mu_end;
|
|
}
|
|
|
|
bool test_getopt_reentrant(void) {
|
|
// Test grouped options because they retain meaningful state between calls.
|
|
const char *argv_first[] = { "test", "-ab" };
|
|
const char *argv_second[] = { "test", "-xy" };
|
|
RzGetopt first;
|
|
RzGetopt second;
|
|
rz_getopt_init(&first, RZ_ARRAY_SIZE(argv_first), argv_first, "ab");
|
|
rz_getopt_init(&second, RZ_ARRAY_SIZE(argv_second), argv_second, "xy");
|
|
|
|
mu_assert_eq(rz_getopt_next(&first), 'a', "first parser should consume its first grouped option");
|
|
mu_assert_eq(rz_getopt_next(&second), 'x', "second parser should consume its first grouped option");
|
|
mu_assert_eq(rz_getopt_next(&first), 'b', "first parser should retain its grouped-option state");
|
|
mu_assert_eq(rz_getopt_next(&second), 'y', "second parser should retain its grouped-option state");
|
|
mu_assert_eq(rz_getopt_next(&first), -1, "first parser should reach the end of its arguments");
|
|
mu_assert_eq(rz_getopt_next(&second), -1, "second parser should reach the end of its arguments");
|
|
mu_end;
|
|
}
|
|
|
|
bool test_path_normalize_expand(void) {
|
|
char *out;
|
|
|
|
out = rz_path_normalize_expand("", strlen(""));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
mu_assert_streq(out, ".", "empty input should normalize to '.'");
|
|
free(out);
|
|
|
|
out = rz_path_normalize_expand("foo/bar", strlen("foo/bar"));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
#ifdef __WINDOWS__
|
|
mu_assert_streq(out, ".\\foo\\bar", "relative path should be prefixed with '.\\'");
|
|
#else
|
|
mu_assert_streq(out, "./foo/bar", "relative path should be prefixed with './'");
|
|
#endif
|
|
free(out);
|
|
out = rz_path_normalize_expand(".hidden_dir", strlen(".hidden_dir"));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
mu_assert_streq(out, ".hidden_dir", "dotfile should be preserved");
|
|
free(out);
|
|
|
|
out = rz_path_normalize_expand("/home/user/.././etc", strlen("/home/user/.././etc"));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
#ifdef __WINDOWS__
|
|
free(out);
|
|
out = rz_path_normalize_expand("C:\\Users\\Test", strlen("C:\\Users\\Test"));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
mu_assert_streq(out, "C:\\Users\\Test", "Windows absolute path should be unchanged");
|
|
#else
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
mu_assert_streq(out, "/home/user/.././etc", "absolute path should be unchanged");
|
|
#endif
|
|
free(out);
|
|
|
|
out = rz_path_normalize_expand("/home/user/./doc/././", strlen("/home/user/./doc/././"));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
#ifdef __WINDOWS__
|
|
free(out);
|
|
out = rz_path_normalize_expand("C:\\Users\\Test\\.\\.\\", strlen("C:\\Users\\Test\\.\\.\\"));
|
|
mu_assert_notnull(out, "result should not be NULL");
|
|
mu_assert_streq(out, "C:\\Users\\Test\\.\\.\\", "should preserve . in absolute paths");
|
|
#else
|
|
mu_assert_streq(out, "/home/user/./doc/././", "should preserve . in absolute paths");
|
|
#endif
|
|
free(out);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
int all_tests() {
|
|
mu_run_test(test_file_slurp);
|
|
mu_run_test(test_leading_zeros);
|
|
mu_run_test(test_path_prefix);
|
|
mu_run_test(test_getopt_long_option);
|
|
mu_run_test(test_getopt_reentrant);
|
|
mu_run_test(test_path_normalize_expand);
|
|
return tests_passed != tests_run;
|
|
}
|
|
|
|
mu_main(all_tests)
|