1 /** @brief Unit-test for DRD's bitmap implementation. */ 2 3 4 #include <assert.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include "coregrind/m_xarray.c" 11 #include "coregrind/m_poolalloc.c" 12 #include "coregrind/m_oset.c" 13 #include "drd/drd_bitmap.c" 14 #include "drd/pub_drd_bitmap.h" 15 16 17 #ifndef MIN 18 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 19 #endif 20 #ifndef MAX 21 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 22 #endif 23 24 25 /* Replacements for Valgrind core functionality. */ 26 27 void* VG_(malloc)(const HChar* cc, SizeT nbytes) 28 { return malloc(nbytes); } 29 void VG_(free)(void* p) 30 { return free(p); } 31 void VG_(assert_fail)(Bool isCore, const HChar* assertion, const HChar* file, 32 Int line, const HChar* function, const HChar* format, 33 ...) 34 { 35 fprintf(stderr, 36 "%s:%u: %s%sAssertion `%s' failed.\n", 37 file, 38 line, 39 function ? (char*)function : "", 40 function ? ": " : "", 41 assertion); 42 fflush(stdout); 43 fflush(stderr); 44 abort(); 45 } 46 47 void* VG_(memset)(void *s, Int c, SizeT sz) 48 { return memset(s, c, sz); } 49 void* VG_(memcpy)(void *d, const void *s, SizeT sz) 50 { return memcpy(d, s, sz); } 51 void* VG_(memmove)(void *d, const void *s, SizeT sz) 52 { return memmove(d, s, sz); } 53 Int VG_(memcmp)(const void* s1, const void* s2, SizeT n) 54 { return memcmp(s1, s2, n); } 55 UInt VG_(printf)(const HChar *format, ...) 56 { UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); return ret; } 57 UInt VG_(message)(VgMsgKind kind, const HChar* format, ...) 58 { UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); printf("\n"); return ret; } 59 Bool DRD_(is_suppressed)(const Addr a1, const Addr a2) 60 { assert(0); } 61 void VG_(vcbprintf)(void(*char_sink)(HChar, void* opaque), 62 void* opaque, 63 const HChar* format, va_list vargs) 64 { assert(0); } 65 void VG_(ssort)( void* base, SizeT nmemb, SizeT size, 66 Int (*compar)(const void*, const void*) ) 67 { assert(0); } 68 69 /* Actual unit test */ 70 71 static int s_verbose = 1; 72 73 static 74 struct { Addr address; SizeT size; BmAccessTypeT access_type; } 75 s_test1_args[] = { 76 { 0, 0, eLoad }, 77 { 0, 1, eLoad }, 78 { 666, 4, eLoad }, 79 { 667, 2, eStore }, 80 { 1024, 1, eStore }, 81 { 0xffffULL, 1, eStore }, 82 { 0x0001ffffULL, 1, eLoad }, 83 { 0x00ffffffULL, 1, eLoad }, 84 { 0xffffffffULL - (((1 << ADDR_LSB_BITS) + 1) << ADDR_IGNORED_BITS), 85 1, eStore }, 86 #if defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) 87 { 0xffffffffULL - (1 << ADDR_LSB_BITS << ADDR_IGNORED_BITS), 88 1, eStore }, 89 { 0xffffffffULL, 1, eStore }, 90 { 0x100000000ULL, 1, eStore }, 91 { -2ULL - (1 << ADDR_LSB_BITS << ADDR_IGNORED_BITS), 92 1, eStore }, 93 #endif 94 }; 95 96 /** 97 * Compare two bitmaps and if different, print the differences. 98 */ 99 int bm_equal_print_diffs(struct bitmap* bm1, struct bitmap* bm2) 100 { 101 int equal; 102 103 equal = DRD_(bm_equal)(bm1, bm2); 104 if (s_verbose && ! equal) 105 { 106 unsigned i; 107 108 VG_(printf)("Bitmaps are different.\n"); 109 for (i = 0; i < 0x10000; i++) 110 { 111 if (DRD_(bm_has_1)(bm1, i, eLoad) != DRD_(bm_has_1)(bm2, i, eLoad) 112 || DRD_(bm_has_1)(bm1, i, eStore) != DRD_(bm_has_1)(bm2, i, eStore)) 113 { 114 printf("0x%x %c %c %c %c\n", 115 i, 116 DRD_(bm_has_1)(bm1, i, eLoad) ? 'R' : ' ', 117 DRD_(bm_has_1)(bm1, i, eStore) ? 'W' : ' ', 118 DRD_(bm_has_1)(bm2, i, eLoad) ? 'R' : ' ', 119 DRD_(bm_has_1)(bm2, i, eStore) ? 'W' : ' ' 120 ); 121 } 122 } 123 fflush(stdout); 124 } 125 126 return equal; 127 } 128 129 void bm_test1(void) 130 { 131 struct bitmap* bm; 132 struct bitmap* bm2; 133 unsigned i, j; 134 135 bm = DRD_(bm_new)(); 136 137 for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++) 138 { 139 DRD_(bm_access_range)(bm, 140 s_test1_args[i].address, 141 s_test1_args[i].address + s_test1_args[i].size, 142 s_test1_args[i].access_type); 143 } 144 145 for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++) 146 { 147 for (j = 0; 148 first_address_with_higher_lsb(j) <= s_test1_args[i].size; 149 j = first_address_with_higher_lsb(j)) 150 { 151 tl_assert(DRD_(bm_has_1)(bm, 152 s_test1_args[i].address + j, 153 s_test1_args[i].access_type)); 154 } 155 } 156 157 bm2 = DRD_(bm_new)(); 158 DRD_(bm_merge2)(bm2, bm); 159 DRD_(bm_merge2)(bm2, bm); 160 assert(bm_equal_print_diffs(bm2, bm)); 161 162 if (s_verbose) 163 VG_(printf)("Deleting bitmap bm\n"); 164 DRD_(bm_delete)(bm); 165 if (s_verbose) 166 VG_(printf)("Deleting bitmap bm2\n"); 167 DRD_(bm_delete)(bm2); 168 } 169 170 /** Test whether bm_equal() works correctly. */ 171 void bm_test2() 172 { 173 struct bitmap* bm1; 174 struct bitmap* bm2; 175 176 bm1 = DRD_(bm_new)(); 177 bm2 = DRD_(bm_new)(); 178 DRD_(bm_access_load_1)(bm1, 7); 179 DRD_(bm_access_load_1)(bm2, make_address(1, 0) + 7); 180 assert(! DRD_(bm_equal)(bm1, bm2)); 181 assert(! DRD_(bm_equal)(bm2, bm1)); 182 DRD_(bm_access_load_1)(bm2, 7); 183 assert(! DRD_(bm_equal)(bm1, bm2)); 184 assert(! DRD_(bm_equal)(bm2, bm1)); 185 DRD_(bm_access_store_1)(bm1, make_address(1, 0) + 7); 186 assert(! DRD_(bm_equal)(bm1, bm2)); 187 assert(! DRD_(bm_equal)(bm2, bm1)); 188 DRD_(bm_delete)(bm2); 189 DRD_(bm_delete)(bm1); 190 } 191 192 /** Torture test of the functions that set or clear a range of bits. */ 193 void bm_test3(const int outer_loop_step, const int inner_loop_step) 194 { 195 unsigned i, j; 196 struct bitmap* bm1; 197 struct bitmap* bm2; 198 199 const Addr lb = make_address(2, 0) - 2 * BITS_PER_UWORD; 200 const Addr ub = make_address(2, 0) + 2 * BITS_PER_UWORD; 201 202 assert(outer_loop_step >= 1); 203 assert((outer_loop_step % ADDR_GRANULARITY) == 0); 204 assert(inner_loop_step >= 1); 205 assert((inner_loop_step % ADDR_GRANULARITY) == 0); 206 207 bm1 = DRD_(bm_new)(); 208 bm2 = DRD_(bm_new)(); 209 for (i = lb; i < ub; i += outer_loop_step) 210 { 211 for (j = i + ADDR_GRANULARITY; j < ub; j += inner_loop_step) 212 { 213 DRD_(bm_access_range_load)(bm1, i, j); 214 DRD_(bm_clear_load)(bm1, i, j); 215 assert(bm_equal_print_diffs(bm1, bm2)); 216 DRD_(bm_access_load_1)(bm1, i); 217 DRD_(bm_clear_load)(bm1, i, i + MAX(1, ADDR_GRANULARITY)); 218 assert(bm_equal_print_diffs(bm1, bm2)); 219 DRD_(bm_access_load_2)(bm1, i); 220 DRD_(bm_clear_load)(bm1, i, i + MAX(2, ADDR_GRANULARITY)); 221 assert(bm_equal_print_diffs(bm1, bm2)); 222 DRD_(bm_access_load_4)(bm1, i); 223 DRD_(bm_clear_load)(bm1, i, i + MAX(4, ADDR_GRANULARITY)); 224 assert(bm_equal_print_diffs(bm1, bm2)); 225 DRD_(bm_access_load_8)(bm1, i); 226 DRD_(bm_clear_load)(bm1, i, i + MAX(8, ADDR_GRANULARITY)); 227 assert(bm_equal_print_diffs(bm1, bm2)); 228 229 DRD_(bm_access_range_store)(bm1, i, j); 230 DRD_(bm_clear_store)(bm1, i, j); 231 assert(bm_equal_print_diffs(bm1, bm2)); 232 DRD_(bm_access_store_1)(bm1, i); 233 DRD_(bm_clear_store)(bm1, i, i + MAX(1, ADDR_GRANULARITY)); 234 assert(bm_equal_print_diffs(bm1, bm2)); 235 DRD_(bm_access_store_2)(bm1, i); 236 DRD_(bm_clear_store)(bm1, i, i + MAX(2, ADDR_GRANULARITY)); 237 assert(bm_equal_print_diffs(bm1, bm2)); 238 DRD_(bm_access_store_4)(bm1, i); 239 DRD_(bm_clear_store)(bm1, i, i + MAX(4, ADDR_GRANULARITY)); 240 assert(bm_equal_print_diffs(bm1, bm2)); 241 DRD_(bm_access_store_8)(bm1, i); 242 DRD_(bm_clear_store)(bm1, i, i + MAX(8, ADDR_GRANULARITY)); 243 assert(bm_equal_print_diffs(bm1, bm2)); 244 245 DRD_(bm_access_range_load)(bm1, i, j); 246 DRD_(bm_access_range_store)(bm1, i, j); 247 DRD_(bm_clear)(bm1, i, j); 248 assert(bm_equal_print_diffs(bm1, bm2)); 249 DRD_(bm_access_load_1)(bm1, i); 250 DRD_(bm_access_store_1)(bm1, i); 251 DRD_(bm_clear)(bm1, i, i + MAX(1, ADDR_GRANULARITY)); 252 assert(bm_equal_print_diffs(bm1, bm2)); 253 DRD_(bm_access_load_2)(bm1, i); 254 DRD_(bm_access_store_2)(bm1, i); 255 DRD_(bm_clear)(bm1, i, i + MAX(2, ADDR_GRANULARITY)); 256 assert(bm_equal_print_diffs(bm1, bm2)); 257 DRD_(bm_access_load_4)(bm1, i); 258 DRD_(bm_access_store_4)(bm1, i); 259 DRD_(bm_clear)(bm1, i, i + MAX(4, ADDR_GRANULARITY)); 260 assert(bm_equal_print_diffs(bm1, bm2)); 261 DRD_(bm_access_load_8)(bm1, i); 262 DRD_(bm_access_store_8)(bm1, i); 263 DRD_(bm_clear)(bm1, i, i + MAX(8, ADDR_GRANULARITY)); 264 assert(bm_equal_print_diffs(bm1, bm2)); 265 } 266 } 267 DRD_(bm_access_range_load)(bm1, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 268 DRD_(bm_access_range_store)(bm1, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 269 DRD_(bm_access_range_load)(bm2, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 270 DRD_(bm_access_range_store)(bm2, 0, make_address(2, 0) + 2 * BITS_PER_UWORD); 271 for (i = make_address(1, 0) - 2 * BITS_PER_UWORD; 272 i < make_address(1, 0) + 2 * BITS_PER_UWORD; 273 i += outer_loop_step) 274 { 275 for (j = i + 1; j < ub; j += inner_loop_step) 276 { 277 DRD_(bm_clear_load)(bm1, i, j); 278 DRD_(bm_access_range_load)(bm1, i, j); 279 assert(bm_equal_print_diffs(bm1, bm2)); 280 DRD_(bm_clear_load)(bm1, i, i+1); 281 DRD_(bm_access_load_1)(bm1, i); 282 assert(bm_equal_print_diffs(bm1, bm2)); 283 DRD_(bm_clear_load)(bm1, i, i+2); 284 DRD_(bm_access_load_2)(bm1, i); 285 assert(bm_equal_print_diffs(bm1, bm2)); 286 DRD_(bm_clear_load)(bm1, i, i+4); 287 DRD_(bm_access_load_4)(bm1, i); 288 assert(bm_equal_print_diffs(bm1, bm2)); 289 DRD_(bm_clear_load)(bm1, i, i+8); 290 DRD_(bm_access_load_8)(bm1, i); 291 assert(bm_equal_print_diffs(bm1, bm2)); 292 293 DRD_(bm_clear_store)(bm1, i, j); 294 DRD_(bm_access_range_store)(bm1, i, j); 295 assert(bm_equal_print_diffs(bm1, bm2)); 296 DRD_(bm_clear_store)(bm1, i, i+1); 297 DRD_(bm_access_store_1)(bm1, i); 298 assert(bm_equal_print_diffs(bm1, bm2)); 299 DRD_(bm_clear_store)(bm1, i, i+2); 300 DRD_(bm_access_store_2)(bm1, i); 301 assert(bm_equal_print_diffs(bm1, bm2)); 302 DRD_(bm_clear_store)(bm1, i, i+4); 303 DRD_(bm_access_store_4)(bm1, i); 304 assert(bm_equal_print_diffs(bm1, bm2)); 305 DRD_(bm_clear_store)(bm1, i, i+8); 306 DRD_(bm_access_store_8)(bm1, i); 307 assert(bm_equal_print_diffs(bm1, bm2)); 308 309 DRD_(bm_clear)(bm1, i, j); 310 DRD_(bm_access_range_load)(bm1, i, j); 311 DRD_(bm_access_range_store)(bm1, i, j); 312 assert(bm_equal_print_diffs(bm1, bm2)); 313 } 314 } 315 DRD_(bm_delete)(bm2); 316 DRD_(bm_delete)(bm1); 317 } 318 319 int main(int argc, char** argv) 320 { 321 int outer_loop_step = ADDR_GRANULARITY; 322 int inner_loop_step = ADDR_GRANULARITY; 323 int optchar; 324 325 while ((optchar = getopt(argc, argv, "s:t:q")) != EOF) 326 { 327 switch (optchar) 328 { 329 case 's': 330 outer_loop_step = atoi(optarg); 331 break; 332 case 't': 333 inner_loop_step = atoi(optarg); 334 break; 335 case 'q': 336 s_verbose = 0; 337 break; 338 default: 339 fprintf(stderr, 340 "Usage: %s [-s<outer_loop_step>] [-t<inner_loop_step>] [-q].\n", 341 argv[0]); 342 break; 343 } 344 } 345 346 fprintf(stderr, "Start of DRD BM unit test.\n"); 347 348 DRD_(bm_module_init)(); 349 bm_test1(); 350 bm_test2(); 351 bm_test3(outer_loop_step, inner_loop_step); 352 DRD_(bm_module_cleanup)(); 353 354 fprintf(stderr, "End of DRD BM unit test.\n"); 355 356 return 0; 357 } 358