/** * @file db_test.c * Tests for DB hash * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING * * @author Philippe Elie */ #include <sys/types.h> #include <sys/time.h> #include <sys/resource.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include "op_sample_file.h" #include "odb.h" #define TEST_FILENAME "test-hash-db.dat" static int nr_error; static int verbose = 0; #define verbprintf(args...) \ do { \ if (verbose) \ printf(args); \ } while (0) static double used_time(void) { struct rusage usage; getrusage(RUSAGE_SELF, &usage); return (usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1E9 + ((usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) * 1000; } /* update nr item */ static void speed_test(int nr_item, char const * test_name) { int i; double begin, end; odb_t hash; int rc; rc = odb_open(&hash, TEST_FILENAME, ODB_RDWR, sizeof(struct opd_header)); if (rc) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } begin = used_time(); for (i = 0 ; i < nr_item ; ++i) { rc = odb_update_node(&hash, i); if (rc != EXIT_SUCCESS) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } } end = used_time(); odb_close(&hash); verbprintf("%s: nr item: %d, elapsed: %f ns\n", test_name, nr_item, (end - begin) / nr_item); } static void do_speed_test(void) { int i; for (i = 100000; i <= 10000000; i *= 10) { // first test count insertion, second fetch and incr count speed_test(i, "insert"); speed_test(i, "update"); remove(TEST_FILENAME); } } static int test(int nr_item, int nr_unique_item) { int i; odb_t hash; int ret; int rc; rc = odb_open(&hash, TEST_FILENAME, ODB_RDWR, sizeof(struct opd_header)); if (rc) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } for (i = 0 ; i < nr_item ; ++i) { odb_key_t key = (random() % nr_unique_item) + 1; rc = odb_update_node(&hash, key); if (rc != EXIT_SUCCESS) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } } ret = odb_check_hash(&hash); odb_close(&hash); remove(TEST_FILENAME); return ret; } static void do_test(void) { int i, j; for (i = 1000; i <= 100000; i *= 10) { for (j = 100 ; j <= i / 10 ; j *= 10) { if (test(i, j)) { fprintf(stderr, "%s:%d failure for %d %d\n", __FILE__, __LINE__, i, j); nr_error++; } else { verbprintf("test() ok %d %d\n", i, j); } } } } static void sanity_check(char const * filename) { odb_t hash; int rc; rc = odb_open(&hash, filename, ODB_RDONLY, sizeof(struct opd_header)); if (rc) { fprintf(stderr, "%s", strerror(rc)); exit(EXIT_FAILURE); } if (odb_check_hash(&hash)) { fprintf(stderr, "checking file %s FAIL\n", filename); ++nr_error; } else if (verbose) { odb_hash_stat_t * stats; stats = odb_hash_stat(&hash); odb_hash_display_stat(stats); odb_hash_free_stat(stats); } odb_close(&hash); } int main(int argc, char * argv[1]) { /* if a filename is given take it as: "check this db" */ if (argc > 1) { int i; verbose = 1; if (!strcmp(argv[1], "--speed")) goto speed_test; for (i = 1 ; i < argc ; ++i) sanity_check(argv[i]); return 0; } speed_test: remove(TEST_FILENAME); do_test(); do_speed_test(); if (nr_error) printf("%d error occured\n", nr_error); return nr_error ? EXIT_FAILURE : EXIT_SUCCESS; }