diff --git a/SConstruct b/SConstruct index 246cdf7..e58e9ac 100644 --- a/SConstruct +++ b/SConstruct @@ -81,7 +81,7 @@ def InstallPerm(env, dest, files, perm): obj = env.Install(dest, files) for i in obj: env.AddPostAction(i, Chmod(str(i), perm)) - return dest + return obj env = Environment(tools = ['default', 'textfile']) diff --git a/include/ucore/mbuf.h b/include/ucore/mbuf.h index 1b92b81..bcd551d 100644 --- a/include/ucore/mbuf.h +++ b/include/ucore/mbuf.h @@ -151,7 +151,7 @@ static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf) /** * @return the length of the headroom in this mbuf */ -static inline uint32_t uc_mbuf_headroom(struct MBuf *mbuf) +static UC_INLINE uint32_t uc_mbuf_headroom(struct MBuf *mbuf) { return (uint32_t)(mbuf->head - mbuf->bufstart); } @@ -187,6 +187,25 @@ uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size); **/ uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size); +/** Add more tailroom to an mbuf. + * Can only be done with mbufs with either + * UC_MBUF_FL_MALLOC or UC_MBUF_FL_MALLOC_BUF. + * + * @param len additional tailroom to add to mbuf + * @return 0 on success, otherwise failure + * + */ +int uc_mbuf_extend_tailroom(struct MBuf *mbuf, uint32_t len); + +/** Get a pointer to the data of the buffer + * + * @return pointer to the start of the data (head) + */ +static UC_INLINE uint8_t *uc_mbuf_head(struct MBuf* mbuf) +{ + return mbuf->head; +} + #undef UC_INLINE #endif diff --git a/include/ucore/string.h b/include/ucore/string.h index fa586bb..6865403 100644 --- a/include/ucore/string.h +++ b/include/ucore/string.h @@ -77,11 +77,15 @@ int getfields(char *str, char **args, int max, int mflag, const char *set); //Converts bytes to a human representable test, (i.e. 12kB, 160 MB 1.78 GB etc.) -//Conversion is done in decimal (base 10 ,1 kB == 1000 bytes) ///result should be at least of size 12, ///returns the result argument char * -uc_human_bytesz(uint64_t bytes, char *result, size_t result_len); +uc_human_bytesz_dec(uint64_t bytes, char *result, size_t result_len); + +//same as uc_human_bytesz_bin, but Conversion is done in binary +//(base 2 ,1 KiB == 1024 bytes) +char * +uc_human_bytesz_bin(uint64_t bytes, char *result, size_t result_len); #ifdef __cplusplus } #endif diff --git a/include/ucore/utils.h b/include/ucore/utils.h index e70327c..0b2e358 100644 --- a/include/ucore/utils.h +++ b/include/ucore/utils.h @@ -94,7 +94,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ fflush(stdout);\ } while(0) #else - #define TRACEF(fmt, ...) + #define TRACEF(fmt, ...) do {} while(0) #endif /** diff --git a/src/human_bytesz.c b/src/human_bytesz.c index 00edcb4..ab8f658 100644 --- a/src/human_bytesz.c +++ b/src/human_bytesz.c @@ -3,7 +3,7 @@ #include "ucore/string.h" char * -uc_human_bytesz(uint64_t bytes, char *result, size_t result_len) +uc_human_bytesz_dec(uint64_t bytes, char *result, size_t result_len) { if (bytes < 1000) { snprintf(result, result_len, "%" PRIu64 " b", bytes); @@ -22,3 +22,22 @@ uc_human_bytesz(uint64_t bytes, char *result, size_t result_len) return result; } +char * +uc_human_bytesz_bin(uint64_t bytes, char *result, size_t result_len) +{ + if (bytes < 1024) { + snprintf(result, result_len, "%" PRIu64 " b", bytes); + } else if (bytes < 1048576) { + snprintf(result, result_len, "%.2f KiB", bytes/1024.0); + } else if (bytes < 1073741824ULL) { + snprintf(result, result_len, "%.2f MiB", bytes/1048576.0); + } else if (bytes < 1099511627776ULL) { + snprintf(result, result_len, "%.2f GiB", bytes/1073741824.0); + } else if (bytes < 1125899906842624ULL) { + snprintf(result, result_len, "%.2f TiB", bytes/1099511627776.0); + } else { + snprintf(result, result_len, "%.2f PiB", bytes/1125899906842624.0); + } + + return result; +} diff --git a/src/mbuf.c b/src/mbuf.c index 865612a..390630f 100644 --- a/src/mbuf.c +++ b/src/mbuf.c @@ -1,4 +1,5 @@ #include +#include #include #include "ucore/mbuf.h" @@ -119,3 +120,81 @@ struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf) return copy; } +int uc_mbuf_extend_tailroom(struct MBuf *mbuf, uint32_t len) +{ + uint32_t tot_len; + uint32_t headroom_len; + uint32_t data_len; + uint32_t tailroom_len; + uint8_t *new_data; + uint32_t p1_off = 0; + uint32_t p2_off = 0; + uint32_t p3_off = 0; + uint32_t p4_off = 0; + + if ((mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF)) == 0) { + return -1; + } + + headroom_len = uc_mbuf_headroom(mbuf); + data_len = uc_mbuf_len(mbuf); + tailroom_len = uc_mbuf_tailroom(mbuf); + tot_len = headroom_len + + data_len + + tailroom_len; + + if (tot_len + len < tot_len) { + //overflowed + return -2; + } + + tot_len += len; + + //need to re-adjust p1-p4 after the realloc + //This assumes the user controlled p1-p4 really are + //set to point into the data, but we document they have + //to be. + if (mbuf->p1 != NULL) { + p1_off = (uint32_t)(mbuf->p1 - mbuf->bufstart); + } + if (mbuf->p2 != NULL) { + p2_off = (uint32_t)(mbuf->p2 - mbuf->bufstart); + } + if (mbuf->p3 != NULL) { + p3_off = (uint32_t)(mbuf->p3 - mbuf->bufstart); + } + if (mbuf->p4 != NULL) { + p4_off = (uint32_t)(mbuf->p4 - mbuf->bufstart); + } + + assert(tot_len >= mbuf->allocated); + + new_data = realloc(mbuf->bufstart, tot_len); + if (new_data == NULL) { + return -3; + } + + mbuf->allocated = tot_len; + mbuf->bufstart = new_data; + mbuf->head = mbuf->bufstart + headroom_len; + mbuf->tail = mbuf->bufstart + headroom_len + data_len; + + assert(uc_mbuf_len(mbuf) == data_len); + assert(uc_mbuf_tailroom(mbuf) >= tailroom_len); + + if (mbuf->p1 != NULL) { + mbuf->p1 = mbuf->bufstart + p1_off; + } + if (mbuf->p2 != NULL) { + mbuf->p2 = mbuf->bufstart + p2_off; + } + if (mbuf->p3 != NULL) { + mbuf->p3 = mbuf->bufstart + p3_off; + } + if (mbuf->p4 != NULL) { + mbuf->p4 = mbuf->bufstart + p4_off; + } + + return 0; + +} diff --git a/test/SConscript b/test/SConscript index fe318d9..074db11 100644 --- a/test/SConscript +++ b/test/SConscript @@ -21,7 +21,7 @@ tests = test_env.Glob('test_*.c') test_executable = 'test_runner' #run test_runner --xml to produce an xml result file if test_xml: - test_executable += ' --xml' + test_executable += ' -x' prog = test_env.Program('test_runner', tests) cmd = test_env.Command(target='test_phony' , diff --git a/test/test_human_bytesz.c b/test/test_human_bytesz.c index c3819d9..9a1d760 100644 --- a/test/test_human_bytesz.c +++ b/test/test_human_bytesz.c @@ -6,7 +6,11 @@ START_TEST (test_human_bytesz_bytes) char result[128]; char *rc; - rc = uc_human_bytesz(999, result, sizeof result); + rc = uc_human_bytesz_dec(999, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "999 b"); + + rc = uc_human_bytesz_bin(999, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "999 b"); END_TEST @@ -15,7 +19,11 @@ START_TEST (test_human_bytesz_bytes_0) char result[128]; char *rc; - rc = uc_human_bytesz(0, result, sizeof result); + rc = uc_human_bytesz_dec(0, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "0 b"); + + rc = uc_human_bytesz_bin(0, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "0 b"); END_TEST @@ -24,45 +32,65 @@ START_TEST (test_human_bytesz_kilobytes) char result[128]; char *rc; - rc = uc_human_bytesz(64000, result, sizeof result); + rc = uc_human_bytesz_dec(64000, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "64.00 kB"); + + rc = uc_human_bytesz_bin(64000, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "62.50 KiB"); END_TEST START_TEST (test_human_bytesz_megabytes) char result[128]; char *rc; - rc = uc_human_bytesz(6409000, result, sizeof result); + rc = uc_human_bytesz_dec(6409000, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "6.41 MB"); + + rc = uc_human_bytesz_bin(6409000, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "6.11 MiB"); END_TEST START_TEST (test_human_bytesz_gigabytes) char result[128]; char *rc; - rc = uc_human_bytesz(126999400000, result, sizeof result); + rc = uc_human_bytesz_dec(126999400000, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "127.00 GB"); + + rc = uc_human_bytesz_bin(126999400000, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "118.28 GiB"); END_TEST START_TEST (test_human_bytesz_terrabytes) char result[128]; char *rc; - rc = uc_human_bytesz(12453400030000, result, sizeof result); + rc = uc_human_bytesz_dec(12453400030000, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "12.45 TB"); + + rc = uc_human_bytesz_bin(12453400030000, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "11.33 TiB"); END_TEST START_TEST (test_human_bytesz_petabytes) char result[128]; char *rc; - rc = uc_human_bytesz(~0LL, result, sizeof result); + rc = uc_human_bytesz_dec(~0LL, result, sizeof result); fail_if(rc == NULL); ck_assert_str_eq(result, "18446.74 PB"); + + rc = uc_human_bytesz_bin(~0ULL, result, sizeof result); + fail_if(rc == NULL); + ck_assert_str_eq(result, "16384.00 PiB"); END_TEST diff --git a/test/test_mbuf.c b/test/test_mbuf.c index dfe8577..453ffc8 100644 --- a/test/test_mbuf.c +++ b/test/test_mbuf.c @@ -1,5 +1,6 @@ #include #include +#include #include @@ -191,7 +192,7 @@ START_TEST (test_mbuf_copy) fail_if(copy == NULL); fail_if(uc_mbuf_len(copy) != 10); fail_if(uc_mbuf_headroom(copy) != 5); - fail_if(memcmp(mbuf->head, copy->head, 10) != 0); + fail_if(memcmp(uc_mbuf_head(mbuf), uc_mbuf_head(copy), 10) != 0); uc_mbuf_free(mbuf); uc_mbuf_free(copy); @@ -211,7 +212,7 @@ START_TEST (test_mbuf_zero) strcpy((char*)data1, "123456789"); uc_mbuf_zero(mbuf); - fail_if(memcmp(mbuf->head, "\0\0\0\0\0\0\0\0\0\0", 10) != 0); + fail_if(memcmp(uc_mbuf_head(mbuf), "\0\0\0\0\0\0\0\0\0\0", 10) != 0); uc_mbuf_free(mbuf); @@ -240,6 +241,55 @@ START_TEST (test_mbuf_static) END_TEST +START_TEST (test_mbuf_extend_tailroom) + struct MBuf *mbuf; + uint8_t *data; + void *filler; + int rc; + + mbuf = uc_mbuf_new_hr(5,2); + fail_if(mbuf == NULL); + + data = uc_mbuf_put(mbuf, 5); + fail_if(data == NULL); + memcpy((char*)data, "hello", 5); + mbuf->p1 = mbuf->tail; + + data = uc_mbuf_put(mbuf, 6); + fail_if(data != NULL); + + filler = malloc(5); //just a hope, so realloc also moves.. + rc = uc_mbuf_extend_tailroom(mbuf, 1024); + ck_assert_int_eq(rc, 0); + ck_assert_int_eq(uc_mbuf_tailroom(mbuf), 1024); + ck_assert_int_eq(uc_mbuf_headroom(mbuf), 2); + ck_assert_int_eq(uc_mbuf_len(mbuf), 5); + + //should work now + data = uc_mbuf_put(mbuf, 6); + fail_if(data == NULL); + strcpy((char*)data, "world"); + ck_assert_str_eq((const char*)mbuf->head, "helloworld"); + ck_assert_str_eq((const char*)mbuf->p1, "world"); + + uc_mbuf_free(mbuf); + free(filler); + +END_TEST + +START_TEST (test_mbuf_extend_tailroom_wrong_type) + struct MBuf *mbuf; + int rc; + + mbuf = uc_mbuf_new_inline(10); + fail_if(mbuf == NULL); + + rc = uc_mbuf_extend_tailroom(mbuf, 1024); + ck_assert_int_ne(rc, 0); + + uc_mbuf_free(mbuf); + +END_TEST Suite *mbuf_suite(void) @@ -258,6 +308,8 @@ Suite *mbuf_suite(void) tcase_add_test(tc, test_mbuf_copy); tcase_add_test(tc, test_mbuf_zero); tcase_add_test(tc, test_mbuf_static); + tcase_add_test(tc, test_mbuf_extend_tailroom); + tcase_add_test(tc, test_mbuf_extend_tailroom_wrong_type); suite_add_tcase(s, tc); diff --git a/test/test_runner.c b/test/test_runner.c index c485f6f..a797d5f 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -2,6 +2,7 @@ #include #include #include +#include typedef Suite *(*suite_func)(void); @@ -53,7 +54,24 @@ static suite_func suites[] = { int main (int argc, char *argv[]) { - int xml_output = argc > 1 && strcmp(argv[1], "--xml") == 0; + int xml_output = 0; + int c; + const char *test_case = NULL; + + while ((c = getopt(argc, argv, "xk:")) != -1) { + switch (c) { + case 'x': + xml_output = 1; + break; + case 'k': + test_case = optarg; + break; + default: + printf("Ignoring unknown option %c\n", c); + break; + } + } + int number_failed = 0; size_t i; @@ -69,7 +87,12 @@ main (int argc, char *argv[]) srunner_add_suite(sr, suites[i]()); } - srunner_run_all (sr, CK_VERBOSE); + if (test_case == NULL) { + srunner_run_all (sr, CK_VERBOSE); + } else { + printf("Running %s only\n", test_case); + srunner_run(sr, NULL, test_case, CK_VERBOSE); + } number_failed = srunner_ntests_failed (sr); srunner_free (sr); diff --git a/test/test_timers.c b/test/test_timers.c index 33c0b09..b6cdf5f 100644 --- a/test/test_timers.c +++ b/test/test_timers.c @@ -62,7 +62,7 @@ START_TEST (test_timers_simple) rc = uc_timers_run(&timers); fail_if(rc != 0); fail_if(tt.cnt != 0); - fail_if(uc_timers_count(&timers) != 1); + ck_assert_int_eq(uc_timers_count(&timers), 1); //10 seconds into the future, our timer should fire t += 5; @@ -77,7 +77,7 @@ START_TEST (test_timers_simple) rc = uc_timers_run(&timers); fail_if(rc != 0); fail_if(tt.cnt != 1); - fail_if(uc_timers_count(&timers) != 0); + ck_assert_int_eq(uc_timers_count(&timers), 0); fail_if(uc_timer_running(&timer) != 0); END_TEST @@ -112,7 +112,7 @@ START_TEST (test_timers_add_from_callback) fail_if(tt.cnt != 2); fail_if(uc_timer_running(&timer) == 0); - fail_if(uc_timers_count(&timers) != 1); + ck_assert_int_eq(uc_timers_count(&timers), 1); END_TEST @@ -136,7 +136,7 @@ START_TEST (test_timers_remove_from_callback) uc_timers_add(&timers, &timer, 5, 0); uc_timers_add(&timers, &timer2, 10, 0); - fail_if(uc_timers_count(&timers) != 2); + ck_assert_int_eq(uc_timers_count(&timers), 2); rc = uc_timers_first(&timers, &tv); fail_if(rc != 0); fail_if(tv.tv_sec != TEST_TIMER_START + 5); @@ -152,7 +152,7 @@ START_TEST (test_timers_remove_from_callback) //and our timer2 should be removed, and timer has fired so it //should be removed too - fail_if(uc_timers_count(&timers) != 0); + ck_assert_int_eq(uc_timers_count(&timers), 0); fail_if(uc_timer_running(&timer) != 0); fail_if(uc_timer_running(&timer2) != 0); rc = uc_timers_first(&timers, &tv); @@ -183,14 +183,14 @@ START_TEST (test_timers_add_remove) fail_if(first.tv_sec != TEST_TIMER_START + 5); fail_if(first.tv_usec != 0); - fail_if(uc_timers_count(&timers) != sizeof timer/sizeof timer[0]); + ck_assert_int_eq(uc_timers_count(&timers), sizeof timer/sizeof timer[0]); for (i = 0; i < sizeof timer/sizeof timer[0]; i++) { uc_timers_remove(&timers, &timer[i]); } - fail_if(uc_timers_count(&timers) != 0); + ck_assert_int_eq(uc_timers_count(&timers), 0); fail_if(uc_timers_first(&timers, &first) == 0); END_TEST