From 17f8418ea75410c3fbf9c9558f50f22cb8808e3e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 May 2014 16:23:50 +0200 Subject: Add conditional support for -v / --verbose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With FEATURE_VERBOSE off, practically no size change. With it on: function old new delta remove_file 493 556 +63 install_main 719 765 +46 bb_make_directory 383 419 +36 rmdir_main 162 191 +29 copy_file 1516 1544 +28 mv_main 502 525 +23 cmp_main 677 693 +16 bbconfig_config_bz2 5264 5279 +15 mkdir_main 158 168 +10 install_longopts 66 76 +10 rm_main 167 175 +8 nexpr 840 846 +6 scan_tree 275 280 +5 fsck_main 1807 1811 +4 ed_main 2541 2545 +4 expand_one_var 1574 1575 +1 swap_on_off_main 420 418 -2 parse_command 1443 1440 -3 redirect 1279 1274 -5 do_load 946 918 -28 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 16/4 up/down: 304/-38) Total: 266 bytes Based on the patch by Igor Živković. Signed-off-by: Denys Vlasenko --- libbb/copy_file.c | 4 ++++ libbb/make_directory.c | 4 ++++ libbb/remove_file.c | 8 ++++++++ 3 files changed, 16 insertions(+) (limited to 'libbb') diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 9333a8d49..a4be875d2 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -389,5 +389,9 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) bb_perror_msg("can't preserve %s of '%s'", "permissions", dest); } + if (flags & FILEUTILS_VERBOSE) { + printf("'%s' -> '%s'\n", source, dest); + } + return retval; } diff --git a/libbb/make_directory.c b/libbb/make_directory.c index 7826b90f5..89352ca1f 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c @@ -99,6 +99,10 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) if (!c) { goto ret0; } + } else { + if (flags & FILEUTILS_VERBOSE) { + printf("created directory: '%s'\n", path); + } } if (!c) { diff --git a/libbb/remove_file.c b/libbb/remove_file.c index 5b75f7f30..eaca293d9 100644 --- a/libbb/remove_file.c +++ b/libbb/remove_file.c @@ -78,6 +78,10 @@ int FAST_FUNC remove_file(const char *path, int flags) return -1; } + if (flags & FILEUTILS_VERBOSE) { + printf("removed directory: '%s'\n", path); + } + return status; } @@ -98,5 +102,9 @@ int FAST_FUNC remove_file(const char *path, int flags) return -1; } + if (flags & FILEUTILS_VERBOSE) { + printf("removed '%s'\n", path); + } + return 0; } -- cgit v1.2.3-55-g6feb From f92f1d0181853b989f9377debb56902e3e21c9a8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Jun 2014 13:54:40 +0200 Subject: find: use sysconf(_SC_ARG_MAX) to determine the command-line size limit The find utility uses a hardcoded value of 32 * 1024 as the limit of the command-line length when calling 'find -exec ... {} +'. This results in over 4 times more execve() calls than in coreutils' find. This patch uses the limit defined in system headers. Based on the patch by Bartosz Golaszewski . Signed-off-by: Denys Vlasenko --- findutils/find.c | 4 +++- findutils/xargs.c | 26 ++++++++++---------------- include/libbb.h | 8 ++++++++ libbb/Kbuild.src | 1 + libbb/sysconf.c | 16 ++++++++++++++++ 5 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 libbb/sysconf.c (limited to 'libbb') diff --git a/findutils/find.c b/findutils/find.c index 493f72e61..56a7ed3ab 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -419,6 +419,7 @@ struct globals { smallint need_print; smallint xdev_on; recurse_flags_t recurse_flags; + IF_FEATURE_FIND_EXEC_PLUS(unsigned max_argv_len;) } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { \ @@ -428,6 +429,7 @@ struct globals { /* we have to zero it out because of NOEXEC */ \ memset(&G, 0, sizeof(G)); \ IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \ + IF_FEATURE_FIND_EXEC_PLUS(G.max_argv_len = bb_arg_max() - 2048;) \ G.need_print = 1; \ G.recurse_flags = ACTION_RECURSE; \ } while (0) @@ -677,7 +679,7 @@ ACTF(exec) ap->file_len += strlen(fileName) + sizeof(char*) + 1; /* If we have lots of files already, exec the command */ rc = 1; - if (ap->file_len >= 32*1024) + if (ap->file_len >= G.max_argv_len) rc = do_exec(ap, NULL); return rc; } diff --git a/findutils/xargs.c b/findutils/xargs.c index 0ba5b566d..76c4747fe 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -523,12 +523,7 @@ int xargs_main(int argc, char **argv) argc++; } - /* -s NUM default. fileutils-4.4.2 uses 128k, but I heasitate - * to use such a big value - first need to change code to use - * growable buffer instead of fixed one. - */ - n_max_chars = 32 * 1024; - /* Make smaller if system does not allow our default value. + /* * The Open Group Base Specifications Issue 6: * "The xargs utility shall limit the command line length such that * when the command line is invoked, the combined argument @@ -536,16 +531,15 @@ int xargs_main(int argc, char **argv) * in the System Interfaces volume of IEEE Std 1003.1-2001) * shall not exceed {ARG_MAX}-2048 bytes". */ - { - long arg_max = 0; -#if defined _SC_ARG_MAX - arg_max = sysconf(_SC_ARG_MAX) - 2048; -#elif defined ARG_MAX - arg_max = ARG_MAX - 2048; -#endif - if (arg_max > 0 && n_max_chars > arg_max) - n_max_chars = arg_max; - } + n_max_chars = bb_arg_max(); + if (n_max_chars > 32 * 1024) + n_max_chars = 32 * 1024; + /* + * POSIX suggests substracting 2048 bytes from sysconf(_SC_ARG_MAX) + * so that the process may safely modify its environment. + */ + n_max_chars -= 2048; + if (opt & OPT_UPTO_SIZE) { n_max_chars = xatou_range(max_chars, 1, INT_MAX); } diff --git a/include/libbb.h b/include/libbb.h index a1a0dc18c..fa69a7fe6 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -731,6 +731,14 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST /* Never returns NULL */ extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; +#if defined ARG_MAX +# define bb_arg_max() ((unsigned)ARG_MAX) +#elif defined _SC_ARG_MAX +unsigned bb_arg_max(void) FAST_FUNC; +#else +# define bb_arg_max() ((unsigned)(32 * 1024)) +#endif + #define SEAMLESS_COMPRESSION (0 \ || ENABLE_FEATURE_SEAMLESS_XZ \ || ENABLE_FEATURE_SEAMLESS_LZMA \ diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 6578d1171..62680bd52 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -92,6 +92,7 @@ lib-y += skip_whitespace.o lib-y += speed_table.o lib-y += str_tolower.o lib-y += strrstr.o +lib-y += sysconf.o lib-y += time.o lib-y += trim.o lib-y += u_signal_names.o diff --git a/libbb/sysconf.c b/libbb/sysconf.c new file mode 100644 index 000000000..c5fa5e001 --- /dev/null +++ b/libbb/sysconf.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various system configuration helpers. + * + * Copyright (C) 2014 Bartosz Golaszewski + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +#include "libbb.h" + +#if defined _SC_ARG_MAX +unsigned FAST_FUNC bb_arg_max(void) +{ + return sysconf(_SC_ARG_MAX); +} +#endif -- cgit v1.2.3-55-g6feb From 5d2e409ef8224dc32fde59702e8ec90b231441ed Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sun, 22 Jun 2014 14:01:13 +0200 Subject: libbb: use a wrapper around sysconf(_SC_CLK_TCK) to save a few bytes function old new delta bb_sc_clk_tck - 10 +10 timescmd 118 113 -5 print_route 1763 1758 -5 mpstat_main 1288 1283 -5 iostat_main 1947 1942 -5 INET_setroute 879 871 -8 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/5 up/down: 10/-28) Total: -18 bytes Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/sysconf.c | 6 ++++++ networking/libiproute/iproute.c | 2 +- networking/route.c | 2 +- procps/iostat.c | 7 +------ procps/mpstat.c | 8 +------- shell/ash.c | 2 +- 7 files changed, 12 insertions(+), 16 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index fa69a7fe6..7a3610bb9 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -738,6 +738,7 @@ unsigned bb_arg_max(void) FAST_FUNC; #else # define bb_arg_max() ((unsigned)(32 * 1024)) #endif +unsigned bb_clk_tck(void) FAST_FUNC; #define SEAMLESS_COMPRESSION (0 \ || ENABLE_FEATURE_SEAMLESS_XZ \ diff --git a/libbb/sysconf.c b/libbb/sysconf.c index c5fa5e001..4dbffbebd 100644 --- a/libbb/sysconf.c +++ b/libbb/sysconf.c @@ -14,3 +14,9 @@ unsigned FAST_FUNC bb_arg_max(void) return sysconf(_SC_ARG_MAX); } #endif + +/* Return the number of clock ticks per second. */ +unsigned FAST_FUNC bb_clk_tck(void) +{ + return sysconf(_SC_CLK_TCK); +} diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index f8a67d9ee..ec4d8ba03 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c @@ -73,7 +73,7 @@ static unsigned get_hz(void) fclose(fp); } if (!hz_internal) - hz_internal = sysconf(_SC_CLK_TCK); + hz_internal = bb_clk_tck(); return hz_internal; } diff --git a/networking/route.c b/networking/route.c index 4235ea72c..24cc2eb5a 100644 --- a/networking/route.c +++ b/networking/route.c @@ -283,7 +283,7 @@ static NOINLINE void INET_setroute(int action, char **args) if (k == KW_IPVx_IRTT) { rt->rt_flags |= RTF_IRTT; rt->rt_irtt = xatoul(args_m1); - rt->rt_irtt *= (sysconf(_SC_CLK_TCK) / 100); /* FIXME */ + rt->rt_irtt *= (bb_clk_tck() / 100); /* FIXME */ #if 0 /* FIXME: do we need to check anything of this? */ if (rt->rt_irtt < 1 || rt->rt_irtt > (120 * HZ)) { bb_error_msg_and_die("bad irtt"); diff --git a/procps/iostat.c b/procps/iostat.c index 978d23430..8d272c87c 100644 --- a/procps/iostat.c +++ b/procps/iostat.c @@ -109,11 +109,6 @@ enum { OPT_m = 1 << 5, }; -static ALWAYS_INLINE unsigned get_user_hz(void) -{ - return sysconf(_SC_CLK_TCK); -} - static ALWAYS_INLINE int this_is_smp(void) { return (G.total_cpus > 1); @@ -414,7 +409,7 @@ int iostat_main(int argc UNUSED_PARAM, char **argv) memset(&stats_data, 0, sizeof(stats_data)); /* Get number of clock ticks per sec */ - G.clk_tck = get_user_hz(); + G.clk_tck = bb_clk_tck(); /* Determine number of CPUs */ G.total_cpus = get_cpu_count(); diff --git a/procps/mpstat.c b/procps/mpstat.c index aa5a5c73f..c628d6215 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -775,12 +775,6 @@ static void main_loop(void) /* Initialization */ -/* Get number of clock ticks per sec */ -static ALWAYS_INLINE unsigned get_hz(void) -{ - return sysconf(_SC_CLK_TCK); -} - static void alloc_struct(int cpus) { int i; @@ -873,7 +867,7 @@ int mpstat_main(int UNUSED_PARAM argc, char **argv) G.cpu_nr = get_cpu_count(); /* Get number of clock ticks per sec */ - G.hz = get_hz(); + G.hz = bb_clk_tck(); /* Calculate number of interrupts per processor */ G.irqcpu_nr = get_irqcpu_nr(PROCFS_INTERRUPTS, NR_IRQS) + NR_IRQCPU_PREALLOC; diff --git a/shell/ash.c b/shell/ash.c index cabeb40c5..dc7a9bf4f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12759,7 +12759,7 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) const unsigned char *p; struct tms buf; - clk_tck = sysconf(_SC_CLK_TCK); + clk_tck = bb_clk_tck(); times(&buf); p = timescmd_str; -- cgit v1.2.3-55-g6feb From 3ed81cf0529145d04299c4cd48b1aaab2fe36193 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sun, 22 Jun 2014 16:30:41 +0200 Subject: unit-tests: implement the unit-testing framework This set of patches adds a simple unit-testing framework to Busybox unit-tests: add some helper macros for unit-test framework implementation unit-tests: implement the unit-testing framework unit-tests: add basic documentation on writing the unit test cases unit-tests: modify the Makefile 'test' target to run unit-tests too unit-tests: add two example test cases unit-tests: modify the existing strrstr test code to use the unit-test framework Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- Config.in | 8 ++++ Makefile.custom | 4 ++ docs/unit-tests.txt | 50 +++++++++++++++++++ include/libbb.h | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/platform.h | 3 ++ libbb/bbunit.c | 90 +++++++++++++++++++++++++++++++++++ libbb/obscure.c | 38 +++++++++++++++ libbb/strrstr.c | 19 +++----- 8 files changed, 335 insertions(+), 12 deletions(-) create mode 100644 docs/unit-tests.txt create mode 100644 libbb/bbunit.c (limited to 'libbb') diff --git a/Config.in b/Config.in index b6eaea541..b83beb52d 100644 --- a/Config.in +++ b/Config.in @@ -675,6 +675,14 @@ config DEBUG_PESSIMIZE in a much bigger executable that more closely matches the source code. +config UNIT_TEST + bool "Build unit tests" + default n + help + Say Y here if you want to build unit tests (both the framework and + test cases) as a Busybox applet. This results in bigger code, so you + probably don't want this option in production builds. + config WERROR bool "Abort compilation on any warning" default n diff --git a/Makefile.custom b/Makefile.custom index 8c95ef2d4..f8a12831d 100644 --- a/Makefile.custom +++ b/Makefile.custom @@ -55,7 +55,11 @@ endif # (cp -pPR is POSIX-compliant (cp -dpR or cp -a would not be)) .PHONY: check .PHONY: test +ifeq ($(CONFIG_UNIT_TEST),y) +UNIT_CMD = ./busybox unit +endif check test: busybox busybox.links + $(UNIT_CMD) test -d $(objtree)/testsuite || cp -pPR $(srctree)/testsuite $(objtree) bindir=$(objtree) srcdir=$(srctree)/testsuite \ $(SHELL) -c "cd $(objtree)/testsuite && $(srctree)/testsuite/runtest $(if $(KBUILD_VERBOSE:0=),-v)" diff --git a/docs/unit-tests.txt b/docs/unit-tests.txt new file mode 100644 index 000000000..0fb522086 --- /dev/null +++ b/docs/unit-tests.txt @@ -0,0 +1,50 @@ +Busybox unit test framework +=========================== + +This document describes what you need to do to write test cases using the +Busybox unit test framework. + + +Building unit tests +------------------- + +The framework and all tests are built as a regular Busybox applet if option +CONFIG_UNIT_TEST (found in General Configuration -> Debugging Options) is set. + + +Writing test cases +------------------ + +Unit testing interface can be found in include/bbunit.h. + +Tests can be placed in any .c file in Busybox tree - preferably right next to +the functions they test. Test cases should be enclosed within an #if, and +should start with BBUNIT_DEFINE_TEST macro and end with BBUNIT_ENDTEST within +the test curly brackets. If an assertion fails the test ends immediately, ie. +the following assertions will not be reached. Any code placed after +BBUNIT_ENDTEST is executed regardless of the test result. Here's an example: + +#if ENABLE_UNIT_TEST + +BBUNIT_DEFINE_TEST(test_name) +{ + int *i; + + i = malloc(sizeof(int)); + BBUNIT_ASSERT_NOTNULL(i); + *i = 2; + BBUNIT_ASSERT_EQ((*i)*(*i), 4); + + BBUNIT_ENDTEST; + + free(i); +} + +#endif /* ENABLE_UNIT_TEST */ + + +Running the unit test suite +--------------------------- + +To run the tests you can either directly run 'busybox unit' or use 'make test' +to run both the unit tests (if compiled) and regular test suite. diff --git a/include/libbb.h b/include/libbb.h index 7a3610bb9..cede50cc2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1941,6 +1941,141 @@ static ALWAYS_INLINE unsigned char bb_ascii_tolower(unsigned char a) #define isprint_asciionly(a) ((unsigned)((a) - 0x20) <= 0x7e - 0x20) +/* Simple unit-testing framework */ + +typedef void (*bbunit_testfunc)(void); + +struct bbunit_listelem { + struct bbunit_listelem* next; + const char* name; + bbunit_testfunc testfunc; +}; + +void bbunit_registertest(struct bbunit_listelem* test); +void bbunit_settestfailed(void); + +#define BBUNIT_DEFINE_TEST(NAME) \ + static void bbunit_##NAME##_test(void); \ + static struct bbunit_listelem bbunit_##NAME##_elem = { \ + .name = #NAME, \ + .testfunc = bbunit_##NAME##_test, \ + }; \ + static void INIT_LAST bbunit_##NAME##_register(void) \ + { \ + bbunit_registertest(&bbunit_##NAME##_elem); \ + } \ + static void bbunit_##NAME##_test(void) + +/* + * Both 'goto bbunit_end' and 'break' are here only to get rid + * of compiler warnings. + */ +#define BBUNIT_ENDTEST \ + do { \ + goto bbunit_end; \ + bbunit_end: \ + break; \ + } while (0) + +#define BBUNIT_PRINTASSERTFAIL \ + do { \ + bb_error_msg( \ + "[ERROR] Assertion failed in file %s, line %d", \ + __FILE__, __LINE__); \ + } while (0) + +#define BBUNIT_ASSERTION_FAILED \ + do { \ + bbunit_settestfailed(); \ + goto bbunit_end; \ + } while (0) + +/* + * Assertions. + * For now we only offer assertions which cause tests to fail + * immediately. In the future 'expects' might be added too - + * similar to those offered by the gtest framework. + */ +#define BBUNIT_ASSERT_EQ(EXPECTED, ACTUAL) \ + do { \ + if ((EXPECTED) != (ACTUAL)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' isn't equal to '%s'", \ + #EXPECTED, #ACTUAL); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_NOTEQ(EXPECTED, ACTUAL) \ + do { \ + if ((EXPECTED) == (ACTUAL)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' is equal to '%s'", \ + #EXPECTED, #ACTUAL); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_NOTNULL(PTR) \ + do { \ + if ((PTR) == NULL) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' is NULL!", #PTR); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_NULL(PTR) \ + do { \ + if ((PTR) != NULL) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] '%s' is not NULL!", #PTR); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_FALSE(STATEMENT) \ + do { \ + if ((STATEMENT)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Statement '%s' evaluated to true!", \ + #STATEMENT); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_TRUE(STATEMENT) \ + do { \ + if (!(STATEMENT)) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Statement '%s' evaluated to false!", \ + #STATEMENT); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_STREQ(STR1, STR2) \ + do { \ + if (strcmp(STR1, STR2) != 0) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Strings '%s' and '%s' " \ + "are not the same", STR1, STR2); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + +#define BBUNIT_ASSERT_STRNOTEQ(STR1, STR2) \ + do { \ + if (strcmp(STR1, STR2) == 0) { \ + BBUNIT_PRINTASSERTFAIL; \ + bb_error_msg("[ERROR] Strings '%s' and '%s' " \ + "are the same, but were " \ + "expected to differ", STR1, STR2); \ + BBUNIT_ASSERTION_FAILED; \ + } \ + } while (0) + + POP_SAVED_FUNCTION_VISIBILITY #endif diff --git a/include/platform.h b/include/platform.h index 92f775551..413c2224c 100644 --- a/include/platform.h +++ b/include/platform.h @@ -76,6 +76,9 @@ # define UNUSED_PARAM_RESULT #endif +/* used by unit test machinery to run registration functions */ +#define INIT_LAST __attribute__ ((constructor(2000))) + /* -fwhole-program makes all symbols local. The attribute externally_visible * forces a symbol global. */ #if __GNUC_PREREQ(4,1) diff --git a/libbb/bbunit.c b/libbb/bbunit.c new file mode 100644 index 000000000..256014441 --- /dev/null +++ b/libbb/bbunit.c @@ -0,0 +1,90 @@ +/* vi: set sw=4 ts=4: */ +/* + * bbunit: Simple unit-testing framework for Busybox. + * + * Copyright (C) 2014 by Bartosz Golaszewski + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +//kbuild:lib-$(CONFIG_UNIT_TEST) += bbunit.o +//applet:IF_UNIT_TEST(APPLET(unit, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//usage:#define unit_trivial_usage +//usage: "" +//usage:#define unit_full_usage "\n\n" +//usage: "Run the unit-test suite" + +#include "libbb.h" + +#define WANT_TIMING 0 + +static llist_t *tests = NULL; +static unsigned tests_registered = 0; +static int test_retval; + +void bbunit_registertest(struct bbunit_listelem *test) +{ + llist_add_to_end(&tests, test); + tests_registered++; +} + +void bbunit_settestfailed(void) +{ + test_retval = -1; +} + +#if WANT_TIMING +static void timeval_diff(struct timeval* res, + const struct timeval* x, + const struct timeval* y) +{ + long udiff = x->tv_usec - y->tv_usec; + + res->tv_sec = x->tv_sec - y->tv_sec - (udiff < 0); + res->tv_usec = (udiff >= 0 ? udiff : udiff + 1000000); +} +#endif + +int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) MAIN_EXTERNALLY_VISIBLE; +int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) +{ + unsigned tests_run = 0; + unsigned tests_failed = 0; +#if WANT_TIMING + struct timeval begin; + struct timeval end; + struct timeval time_spent; + gettimeofday(&begin, NULL); +#endif + + bb_error_msg("Running %d test(s)...", tests_registered); + for (;;) { + struct bbunit_listelem* el = llist_pop(&tests); + if (!el) + break; + bb_error_msg("Case: [%s]", el->name); + test_retval = 0; + el->testfunc(); + if (test_retval < 0) { + bb_error_msg("[ERROR] [%s]: TEST FAILED", el->name); + tests_failed++; + } + tests_run++; + el = el->next; + } + +#if WANT_TIMING + gettimeofday(&end, NULL); + timeval_diff(&time_spent, &end, &begin); + bb_error_msg("Elapsed time %u.%06u seconds" + (int)time_spent.tv_sec, + (int)time_spent.tv_usec); +#endif + if (tests_failed > 0) { + bb_error_msg("[ERROR] %u test(s) FAILED", tests_failed); + return EXIT_FAILURE; + } + bb_error_msg("All tests passed"); + return EXIT_SUCCESS; +} diff --git a/libbb/obscure.c b/libbb/obscure.c index 24c4ac917..ad17d1ff1 100644 --- a/libbb/obscure.c +++ b/libbb/obscure.c @@ -182,3 +182,41 @@ int FAST_FUNC obscure(const char *old, const char *newval, const struct passwd * } return 0; } + +#if ENABLE_UNIT_TEST + +/* Test obscure_msg() instead of obscure() in order not to print anything. */ + +static const struct passwd pw = { + .pw_name = (char *)"johndoe", + .pw_gecos = (char *)"John Doe", +}; + +BBUNIT_DEFINE_TEST(obscure_weak_pass) +{ + /* Empty password */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "", &pw)); + /* Pure numbers */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "23577315", &pw)); + /* Similar to pw_name */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "johndoe123%", &pw)); + /* Similar to pw_gecos, reversed */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "eoD nhoJ^44@", &pw)); + /* Similar to the old password */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "d4#21?'S", &pw)); + /* adjacent letters */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "qwerty123", &pw)); + /* Many similar chars */ + BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "^33Daaaaaa1", &pw)); + + BBUNIT_ENDTEST; +} + +BBUNIT_DEFINE_TEST(obscure_strong_pass) +{ + BBUNIT_ASSERT_NULL(obscure_msg("Rt4##2&:'|", "}(^#rrSX3S*22", &pw)); + + BBUNIT_ENDTEST; +} + +#endif /* ENABLE_UNIT_TEST */ diff --git a/libbb/strrstr.c b/libbb/strrstr.c index d8823fc51..93d970a1b 100644 --- a/libbb/strrstr.c +++ b/libbb/strrstr.c @@ -7,13 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -#ifdef __DO_STRRSTR_TEST -#include -#include -#include -#else #include "libbb.h" -#endif /* * The strrstr() function finds the last occurrence of the substring needle @@ -34,8 +28,9 @@ char* FAST_FUNC strrstr(const char *haystack, const char *needle) } } -#ifdef __DO_STRRSTR_TEST -int main(int argc, char **argv) +#if ENABLE_UNIT_TEST + +BBUNIT_DEFINE_TEST(strrstr) { static const struct { const char *h, *n; @@ -59,13 +54,13 @@ int main(int argc, char **argv) i = 0; while (i < sizeof(test_array) / sizeof(test_array[0])) { const char *r = strrstr(test_array[i].h, test_array[i].n); - printf("'%s' vs. '%s': '%s' - ", test_array[i].h, test_array[i].n, r); if (r == NULL) r = test_array[i].h - 1; - printf("%s\n", r == test_array[i].h + test_array[i].pos ? "PASSED" : "FAILED"); + BBUNIT_ASSERT_EQ(r, test_array[i].h + test_array[i].pos); i++; } - return 0; + BBUNIT_ENDTEST; } -#endif + +#endif /* ENABLE_UNIT_TEST */ -- cgit v1.2.3-55-g6feb From 5aeae36e2b8bcee19c8eb189f55b19febaab4c42 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jun 2014 15:39:27 +0200 Subject: libbb: fix compile failure if both ARG_MAX and _SC_ARG_MAX are defined Signed-off-by: Denys Vlasenko --- libbb/sysconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/sysconf.c b/libbb/sysconf.c index 4dbffbebd..031901980 100644 --- a/libbb/sysconf.c +++ b/libbb/sysconf.c @@ -8,7 +8,7 @@ */ #include "libbb.h" -#if defined _SC_ARG_MAX +#if !defined(ARG_MAX) && defined(_SC_ARG_MAX) unsigned FAST_FUNC bb_arg_max(void) { return sysconf(_SC_ARG_MAX); -- cgit v1.2.3-55-g6feb