// This module does unit testing of m_libcbase. #include <assert.h> #include <stdio.h> #include <stdlib.h> #include "pub_tool_basics.h" /* UInt et al, needed for pub_tool_vki.h */ #include "pub_tool_vki.h" #include "m_libcbase.c" #define CHECK(x) \ if (!x) { fprintf(stderr, "failure: %s:%d\n", __FILE__, __LINE__); } void test_VG_STREQ(void) { CHECK( ! VG_STREQ(NULL, NULL) ); // Nb: strcmp() considers these equal CHECK( ! VG_STREQ(NULL, "ab") ); // Nb: strcmp() seg faults on this CHECK( ! VG_STREQ("ab", NULL) ); // Nb: strcmp() seg faults on this CHECK( ! VG_STREQ("", "a") ); CHECK( ! VG_STREQ("a", "") ); CHECK( ! VG_STREQ("abc", "abcd")); CHECK( ! VG_STREQ("abcd", "abc") ); CHECK( ! VG_STREQ("Abcd", "abcd")); CHECK( ! VG_STREQ("abcd", "Abcd")); CHECK( VG_STREQ("", "") ); CHECK( VG_STREQ("a", "a") ); CHECK( VG_STREQ("abcd", "abcd") ); } void test_VG_STREQN(void) { CHECK( ! VG_STREQN(0, NULL, NULL) ); CHECK( ! VG_STREQN(5, NULL, NULL) ); CHECK( ! VG_STREQN(0, NULL, "ab") ); CHECK( ! VG_STREQN(5, NULL, "ab") ); CHECK( ! VG_STREQN(0, "ab", NULL) ); CHECK( ! VG_STREQN(1, "", "a") ); CHECK( ! VG_STREQN(1, "a", "") ); CHECK( ! VG_STREQN(4, "abc", "abcd")); CHECK( ! VG_STREQN(4, "abcd", "abc") ); CHECK( ! VG_STREQN(1, "Abcd", "abcd")); CHECK( ! VG_STREQN(4, "Abcd", "abcd")); CHECK( ! VG_STREQN(4, "abcd", "abce")); CHECK( ! VG_STREQN(9, "abcd", "abce")); CHECK( VG_STREQN(0, "", "") ); CHECK( VG_STREQN(1, "", "") ); CHECK( VG_STREQN(0, "a", "a") ); CHECK( VG_STREQN(1, "a", "a") ); CHECK( VG_STREQN(2, "a", "a") ); CHECK( VG_STREQN(9, "a", "a") ); CHECK( VG_STREQN(1, "ab", "ac")); CHECK( VG_STREQN(3, "abcd", "abce")); } // On PPC/Linux VKI_PAGE_SIZE is a variable, not a macro. #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) unsigned long VKI_PAGE_SIZE = 1UL << 12; #endif void test_VG_IS_XYZ_ALIGNED(void) { CHECK( VG_IS_2_ALIGNED(0x0) ); CHECK( ! VG_IS_2_ALIGNED(0x1) ); CHECK( VG_IS_2_ALIGNED(0x2) ); CHECK( ! VG_IS_2_ALIGNED(0x3) ); CHECK( VG_IS_2_ALIGNED(0x4) ); CHECK( ! VG_IS_2_ALIGNED(0x5) ); CHECK( VG_IS_2_ALIGNED(0x6) ); CHECK( ! VG_IS_2_ALIGNED(0x7) ); CHECK( VG_IS_2_ALIGNED(0x8) ); CHECK( ! VG_IS_2_ALIGNED(0x9) ); CHECK( VG_IS_2_ALIGNED(0xa) ); CHECK( ! VG_IS_2_ALIGNED(0xb) ); CHECK( VG_IS_2_ALIGNED(0xc) ); CHECK( ! VG_IS_2_ALIGNED(0xd) ); CHECK( VG_IS_2_ALIGNED(0xe) ); CHECK( ! VG_IS_2_ALIGNED(0xf) ); CHECK( VG_IS_4_ALIGNED(0x0) ); CHECK( ! VG_IS_4_ALIGNED(0x1) ); CHECK( ! VG_IS_4_ALIGNED(0x2) ); CHECK( ! VG_IS_4_ALIGNED(0x3) ); CHECK( VG_IS_4_ALIGNED(0x4) ); CHECK( ! VG_IS_4_ALIGNED(0x5) ); CHECK( ! VG_IS_4_ALIGNED(0x6) ); CHECK( ! VG_IS_4_ALIGNED(0x7) ); CHECK( VG_IS_4_ALIGNED(0x8) ); CHECK( ! VG_IS_4_ALIGNED(0x9) ); CHECK( ! VG_IS_4_ALIGNED(0xa) ); CHECK( ! VG_IS_4_ALIGNED(0xb) ); CHECK( VG_IS_4_ALIGNED(0xc) ); CHECK( ! VG_IS_4_ALIGNED(0xd) ); CHECK( ! VG_IS_4_ALIGNED(0xe) ); CHECK( ! VG_IS_4_ALIGNED(0xf) ); CHECK( VG_IS_8_ALIGNED(0x0) ); CHECK( ! VG_IS_8_ALIGNED(0x1) ); CHECK( ! VG_IS_8_ALIGNED(0x2) ); CHECK( ! VG_IS_8_ALIGNED(0x3) ); CHECK( ! VG_IS_8_ALIGNED(0x4) ); CHECK( ! VG_IS_8_ALIGNED(0x5) ); CHECK( ! VG_IS_8_ALIGNED(0x6) ); CHECK( ! VG_IS_8_ALIGNED(0x7) ); CHECK( VG_IS_8_ALIGNED(0x8) ); CHECK( ! VG_IS_8_ALIGNED(0x9) ); CHECK( ! VG_IS_8_ALIGNED(0xa) ); CHECK( ! VG_IS_8_ALIGNED(0xb) ); CHECK( ! VG_IS_8_ALIGNED(0xc) ); CHECK( ! VG_IS_8_ALIGNED(0xd) ); CHECK( ! VG_IS_8_ALIGNED(0xe) ); CHECK( ! VG_IS_8_ALIGNED(0xf) ); CHECK( VG_IS_16_ALIGNED(0x0) ); CHECK( ! VG_IS_16_ALIGNED(0x1) ); CHECK( ! VG_IS_16_ALIGNED(0x2) ); CHECK( ! VG_IS_16_ALIGNED(0x3) ); CHECK( ! VG_IS_16_ALIGNED(0x4) ); CHECK( ! VG_IS_16_ALIGNED(0x5) ); CHECK( ! VG_IS_16_ALIGNED(0x6) ); CHECK( ! VG_IS_16_ALIGNED(0x7) ); CHECK( ! VG_IS_16_ALIGNED(0x8) ); CHECK( ! VG_IS_16_ALIGNED(0x9) ); CHECK( ! VG_IS_16_ALIGNED(0xa) ); CHECK( ! VG_IS_16_ALIGNED(0xb) ); CHECK( ! VG_IS_16_ALIGNED(0xc) ); CHECK( ! VG_IS_16_ALIGNED(0xd) ); CHECK( ! VG_IS_16_ALIGNED(0xe) ); CHECK( ! VG_IS_16_ALIGNED(0xf) ); CHECK( VG_IS_WORD_ALIGNED(0x0) ); CHECK( ! VG_IS_WORD_ALIGNED(0x1) ); CHECK( ! VG_IS_WORD_ALIGNED(0x2) ); CHECK( ! VG_IS_WORD_ALIGNED(0x3) ); // 0x4 case below CHECK( ! VG_IS_WORD_ALIGNED(0x5) ); CHECK( ! VG_IS_WORD_ALIGNED(0x6) ); CHECK( ! VG_IS_WORD_ALIGNED(0x7) ); CHECK( VG_IS_WORD_ALIGNED(0x8) ); CHECK( ! VG_IS_WORD_ALIGNED(0x9) ); CHECK( ! VG_IS_WORD_ALIGNED(0xa) ); CHECK( ! VG_IS_WORD_ALIGNED(0xb) ); // 0xc case below CHECK( ! VG_IS_WORD_ALIGNED(0xd) ); CHECK( ! VG_IS_WORD_ALIGNED(0xe) ); CHECK( ! VG_IS_WORD_ALIGNED(0xf) ); if (4 == sizeof(void*)) { CHECK( VG_IS_WORD_ALIGNED(0x4) ); CHECK( VG_IS_WORD_ALIGNED(0xc) ); } else if (8 == sizeof(void*)) { CHECK( ! VG_IS_WORD_ALIGNED(0x4) ); CHECK( ! VG_IS_WORD_ALIGNED(0xc) ); } else { assert(0); } CHECK( VG_IS_PAGE_ALIGNED(0x0) ); CHECK( ! VG_IS_PAGE_ALIGNED(0x1) ); CHECK( ! VG_IS_PAGE_ALIGNED(0x2) ); CHECK( ! VG_IS_PAGE_ALIGNED(0x3) ); CHECK( ! VG_IS_PAGE_ALIGNED(0x4) ); CHECK( ! VG_IS_PAGE_ALIGNED(VKI_PAGE_SIZE-1) ); CHECK( VG_IS_PAGE_ALIGNED(VKI_PAGE_SIZE ) ); CHECK( ! VG_IS_PAGE_ALIGNED(VKI_PAGE_SIZE+1) ); } void test_VG_ROUND_et_al() { CHECK( 0 == VG_ROUNDDN(0, 1) ); CHECK( 1 == VG_ROUNDDN(1, 1) ); CHECK( 2 == VG_ROUNDDN(2, 1) ); CHECK( 3 == VG_ROUNDDN(3, 1) ); CHECK( 4 == VG_ROUNDDN(4, 1) ); CHECK( 5 == VG_ROUNDDN(5, 1) ); CHECK( 6 == VG_ROUNDDN(6, 1) ); CHECK( 7 == VG_ROUNDDN(7, 1) ); CHECK( 0 == VG_ROUNDUP(0, 1) ); CHECK( 1 == VG_ROUNDUP(1, 1) ); CHECK( 2 == VG_ROUNDUP(2, 1) ); CHECK( 3 == VG_ROUNDUP(3, 1) ); CHECK( 4 == VG_ROUNDUP(4, 1) ); CHECK( 5 == VG_ROUNDUP(5, 1) ); CHECK( 6 == VG_ROUNDUP(6, 1) ); CHECK( 7 == VG_ROUNDUP(7, 1) ); CHECK( 0 == VG_ROUNDDN(0, 2) ); CHECK( 0 == VG_ROUNDDN(1, 2) ); CHECK( 2 == VG_ROUNDDN(2, 2) ); CHECK( 2 == VG_ROUNDDN(3, 2) ); CHECK( 4 == VG_ROUNDDN(4, 2) ); CHECK( 4 == VG_ROUNDDN(5, 2) ); CHECK( 6 == VG_ROUNDDN(6, 2) ); CHECK( 6 == VG_ROUNDDN(7, 2) ); CHECK( 0 == VG_ROUNDUP(0, 2) ); CHECK( 2 == VG_ROUNDUP(1, 2) ); CHECK( 2 == VG_ROUNDUP(2, 2) ); CHECK( 4 == VG_ROUNDUP(3, 2) ); CHECK( 4 == VG_ROUNDUP(4, 2) ); CHECK( 6 == VG_ROUNDUP(5, 2) ); CHECK( 6 == VG_ROUNDUP(6, 2) ); CHECK( 8 == VG_ROUNDUP(7, 2) ); CHECK( 0 == VG_ROUNDDN(0, 4) ); CHECK( 0 == VG_ROUNDDN(1, 4) ); CHECK( 0 == VG_ROUNDDN(2, 4) ); CHECK( 0 == VG_ROUNDDN(3, 4) ); CHECK( 4 == VG_ROUNDDN(4, 4) ); CHECK( 4 == VG_ROUNDDN(5, 4) ); CHECK( 4 == VG_ROUNDDN(6, 4) ); CHECK( 4 == VG_ROUNDDN(7, 4) ); CHECK( 0 == VG_ROUNDUP(0, 4) ); CHECK( 4 == VG_ROUNDUP(1, 4) ); CHECK( 4 == VG_ROUNDUP(2, 4) ); CHECK( 4 == VG_ROUNDUP(3, 4) ); CHECK( 4 == VG_ROUNDUP(4, 4) ); CHECK( 8 == VG_ROUNDUP(5, 4) ); CHECK( 8 == VG_ROUNDUP(6, 4) ); CHECK( 8 == VG_ROUNDUP(7, 4) ); CHECK( 0 == VG_ROUNDDN(0, 8) ); CHECK( 0 == VG_ROUNDDN(1, 8) ); CHECK( 0 == VG_ROUNDDN(2, 8) ); CHECK( 0 == VG_ROUNDDN(3, 8) ); CHECK( 0 == VG_ROUNDDN(4, 8) ); CHECK( 0 == VG_ROUNDDN(5, 8) ); CHECK( 0 == VG_ROUNDDN(6, 8) ); CHECK( 0 == VG_ROUNDDN(7, 8) ); CHECK( 0 == VG_ROUNDUP(0, 8) ); CHECK( 8 == VG_ROUNDUP(1, 8) ); CHECK( 8 == VG_ROUNDUP(2, 8) ); CHECK( 8 == VG_ROUNDUP(3, 8) ); CHECK( 8 == VG_ROUNDUP(4, 8) ); CHECK( 8 == VG_ROUNDUP(5, 8) ); CHECK( 8 == VG_ROUNDUP(6, 8) ); CHECK( 8 == VG_ROUNDUP(7, 8) ); CHECK( 0 == VG_PGROUNDDN(0) ); CHECK( 0 == VG_PGROUNDDN(1) ); CHECK( 0 == VG_PGROUNDDN(2) ); CHECK( 0 == VG_PGROUNDDN(3) ); CHECK( 0 == VG_PGROUNDDN(4) ); CHECK( 0 == VG_PGROUNDDN(VKI_PAGE_SIZE-1) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDDN(VKI_PAGE_SIZE ) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDDN(VKI_PAGE_SIZE+1) ); CHECK( 0 == VG_PGROUNDUP(0) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(1) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(2) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(3) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(4) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(VKI_PAGE_SIZE-1) ); CHECK( VKI_PAGE_SIZE == VG_PGROUNDUP(VKI_PAGE_SIZE ) ); CHECK( VKI_PAGE_SIZE*2 == VG_PGROUNDUP(VKI_PAGE_SIZE+1) ); } void test_isspace(void) { CHECK( VG_(isspace)(' ') ); CHECK( VG_(isspace)('\n') ); CHECK( VG_(isspace)('\t') ); CHECK( ! VG_(isspace)('3') ); CHECK( ! VG_(isspace)('x') ); } void test_isdigit(void) { CHECK( VG_(isdigit)('0') ); CHECK( VG_(isdigit)('1') ); CHECK( VG_(isdigit)('5') ); CHECK( VG_(isdigit)('9') ); CHECK( ! VG_(isdigit)('a') ); CHECK( ! VG_(isdigit)('!') ); } void test_is_dec_digit() { Long x; CHECK( is_dec_digit('0', &x) && 0 == x ); CHECK( is_dec_digit('1', &x) && 1 == x ); CHECK( is_dec_digit('9', &x) && 9 == x ); } void test_is_hex_digit() { Long x; CHECK( is_hex_digit('0', &x) && 0 == x ); CHECK( is_hex_digit('1', &x) && 1 == x ); CHECK( is_hex_digit('9', &x) && 9 == x ); CHECK( is_hex_digit('a', &x) && 10 == x ); CHECK( is_hex_digit('f', &x) && 15 == x ); CHECK( is_hex_digit('A', &x) && 10 == x ); CHECK( is_hex_digit('F', &x) && 15 == x ); } void test_strtoll_and_strtod(void) { // For VG_(strtoll*)() typedef struct { Char* str; // The string to convert. Long res; // The result. Char endptr_val; // The char one past the end of the converted text. } StrtollInputs; // VG_(strtoll10)() { StrtollInputs a[] = { // If there's no number at the head of the string, return 0, and // make 'endptr' point to the start of the string. { .str = "", .res = 0, .endptr_val = '\0' }, { .str = " \n\t", .res = 0, .endptr_val = ' ' }, { .str = "one", .res = 0, .endptr_val = 'o' }, { .str = "\ntwo", .res = 0, .endptr_val = '\n' }, // Successful conversion. Leading whitespace is ignored. A single // '-' or '+' is accepted. { .str = "0", .res = 0, .endptr_val = '\0' }, { .str = "+0", .res = 0, .endptr_val = '\0' }, { .str = "-0", .res = 0, .endptr_val = '\0' }, { .str = "1", .res = 1, .endptr_val = '\0' }, { .str = "+1", .res = 1, .endptr_val = '\0' }, { .str = "-1", .res = -1, .endptr_val = '\0' }, { .str = "12", .res = 12, .endptr_val = '\0' }, { .str = "-567", .res = -567, .endptr_val = '\0' }, { .str = "1234567", .res = 1234567, .endptr_val = '\0' }, { .str = "007", .res = 7, .endptr_val = '\0' }, { .str = " +42", .res = 42, .endptr_val = '\0' }, { .str = "\n\t\r\v -56", .res = -56, .endptr_val = '\0' }, { .str = "123xyz", .res = 123, .endptr_val = 'x' }, { .str = " -123abc", .res = -123, .endptr_val = 'a' }, // Whitespace after the +/- is not allowed; conversion fails. { .str = "+ 1", .res = 0, .endptr_val = '+' }, { .str = "-\n1", .res = 0, .endptr_val = '-' }, }; // Nb: We test the results against strtoll() as well. int i; for (i = 0; i < (sizeof(a) / sizeof(StrtollInputs)); i++) { Char* endptr1; char* endptr2; Long res1 = VG_(strtoll10)(a[i].str, &endptr1); long long res2 = strtoll (a[i].str, &endptr2, 10); //printf("res1 = %lld, *endptr1 = '%c'\n", res1, *endptr1); //printf("res2 = %lld, *endptr2 = '%c'\n", res2, *endptr2); CHECK(a[i].res == res1 && a[i].endptr_val == *endptr1); CHECK(res2 == res1 && *endptr2 == *endptr1); } } // VG_(strtoll16)() { StrtollInputs a[] = { // If there's no number at the head of the string, return 0, and // make 'endptr' point to the start of the string. { .str = "", .res = 0, .endptr_val = '\0' }, { .str = " \n\t", .res = 0, .endptr_val = ' ' }, { .str = "one", .res = 0, .endptr_val = 'o' }, { .str = "\ntwo", .res = 0, .endptr_val = '\n' }, // Successful conversion. Leading whitespace is ignored. A single // '-' or '+' is accepted. "0X" and "0x" are also allowed at the // front, but if no digits follow, just the "0" is converted. { .str = "0", .res = 0, .endptr_val = '\0' }, { .str = "0x0", .res = 0, .endptr_val = '\0' }, { .str = "0X0", .res = 0, .endptr_val = '\0' }, { .str = "0x", .res = 0, .endptr_val = 'x' }, { .str = "0Xg", .res = 0, .endptr_val = 'X' }, { .str = "0", .res = 0, .endptr_val = '\0' }, { .str = "+0", .res = 0, .endptr_val = '\0' }, { .str = "-0", .res = 0, .endptr_val = '\0' }, { .str = "1", .res = 1, .endptr_val = '\0' }, { .str = "+1", .res = 1, .endptr_val = '\0' }, { .str = "-1", .res = -1, .endptr_val = '\0' }, { .str = "1a", .res = 26, .endptr_val = '\0' }, { .str = "-5F7", .res = -1527, .endptr_val = '\0' }, { .str = "0x1234567", .res = 19088743, .endptr_val = '\0' }, { .str = "007", .res = 7, .endptr_val = '\0' }, { .str = "0X00ABCD", .res = 43981, .endptr_val = '\0' }, { .str = " +AbC", .res = 2748, .endptr_val = '\0' }, { .str = " -0xAbC", .res = -2748, .endptr_val = '\0' }, { .str = " -0xxx", .res = 0, .endptr_val = 'x' }, { .str = "\n\t\r\v -56", .res = -86, .endptr_val = '\0' }, { .str = "123xyz", .res = 291, .endptr_val = 'x' }, { .str = " -123defghi", .res = -1195503, .endptr_val = 'g' }, // Whitespace after the +/- is not allowed; conversion fails. { .str = "+ 1", .res = 0, .endptr_val = '+' }, { .str = "-\n0x1", .res = 0, .endptr_val = '-' }, }; // Nb: We test the results against strtoll() as well. int i; for (i = 0; i < (sizeof(a) / sizeof(StrtollInputs)); i++) { Char* endptr1; char* endptr2; Long res1 = VG_(strtoll16)(a[i].str, &endptr1); long long res2 = strtoll (a[i].str, &endptr2, 16); //printf(" res1 = %lld, *endptr1 = '%c'\n", res1, *endptr1); //printf(" res2 = %lld, *endptr2 = '%c'\n", res2, *endptr2); CHECK(a[i].res == res1 && a[i].endptr_val == *endptr1); CHECK(res2 == res1 && *endptr2 == *endptr1); } } // VG_(strtod)() // XXX: todo } void test_log2(void) { CHECK( -1 == VG_(log2)(0) ); CHECK( 0 == VG_(log2)(1) ); CHECK( 1 == VG_(log2)(2) ); CHECK( -1 == VG_(log2)(3) ); CHECK( 2 == VG_(log2)(4) ); CHECK( -1 == VG_(log2)(5) ); CHECK( -1 == VG_(log2)(6) ); CHECK( -1 == VG_(log2)(7) ); CHECK( 3 == VG_(log2)(8) ); CHECK( -1 == VG_(log2)( 15) ); CHECK( 4 == VG_(log2)( 16) ); CHECK( -1 == VG_(log2)( 17) ); CHECK( -1 == VG_(log2)( 63) ); CHECK( 6 == VG_(log2)( 64) ); CHECK( -1 == VG_(log2)( 65) ); CHECK( -1 == VG_(log2)(255) ); CHECK( 8 == VG_(log2)(256) ); CHECK( -1 == VG_(log2)(257) ); CHECK( -1 == VG_(log2)(65535) ); CHECK( 16 == VG_(log2)(65536) ); CHECK( -1 == VG_(log2)(65537) ); CHECK( -1 == VG_(log2)(16777215) ); CHECK( 24 == VG_(log2)(16777216) ); CHECK( -1 == VG_(log2)(16777217) ); CHECK( -1 == VG_(log2)(2147483647U) ); CHECK( 31 == VG_(log2)(2147483648U) ); CHECK( -1 == VG_(log2)(2147483649U) ); CHECK( -1 == VG_(log2)(4294967295U) ); // Max UInt } void test_random(void) { // Hmm, it's really hard to unit test a pseudo-random number generator. // So no testing here, sorry. } //----------------------------------------------------------------------- // main //----------------------------------------------------------------------- int main(void) { // Nb: the order of the tests is based on the order of the code in // m_libcbase.c, except that macros defined in pub_tool_libcbase.h are // tested first. //-------------------------------------------------------------------- // pub_tool_libcbase.h macros //-------------------------------------------------------------------- test_VG_STREQ(); test_VG_STREQN(); test_VG_IS_XYZ_ALIGNED(); test_VG_ROUND_et_al(); //-------------------------------------------------------------------- // Char functions //-------------------------------------------------------------------- test_isspace(); test_isdigit(); //-------------------------------------------------------------------- // String-to-number functions //-------------------------------------------------------------------- test_is_dec_digit(); test_is_hex_digit(); test_strtoll_and_strtod(); //-------------------------------------------------------------------- // String functions //-------------------------------------------------------------------- // XXX: more todo: VG_(str_*) //-------------------------------------------------------------------- // Mem functions //-------------------------------------------------------------------- // XXX: todo: VG_(mem*) //-------------------------------------------------------------------- // Miscellaneous functions //-------------------------------------------------------------------- // XXX: todo: VG_(ssort) test_log2(); test_random(); return 0; }