1/**
2 * @file db_test.c
3 * Tests for DB hash
4 *
5 * @remark Copyright 2002 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Philippe Elie
9 */
10
11#include <sys/types.h>
12#include <sys/time.h>
13#include <sys/resource.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17#include <fcntl.h>
18
19#include "op_sample_file.h"
20#include "odb.h"
21
22#define TEST_FILENAME "test-hash-db.dat"
23
24static int nr_error;
25
26static int verbose = 0;
27
28#define verbprintf(args...) \
29	do { \
30		if (verbose) \
31			printf(args); \
32	} while (0)
33
34static double used_time(void)
35{
36	struct rusage  usage;
37
38	getrusage(RUSAGE_SELF, &usage);
39
40	return (usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1E9 +
41		((usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) * 1000;
42}
43
44
45/* update nr item */
46static void speed_test(int nr_item, char const * test_name)
47{
48	int i;
49	double begin, end;
50	odb_t hash;
51	int rc;
52
53	rc = odb_open(&hash, TEST_FILENAME, ODB_RDWR, sizeof(struct opd_header));
54	if (rc) {
55		fprintf(stderr, "%s", strerror(rc));
56		exit(EXIT_FAILURE);
57	}
58	begin = used_time();
59	for (i = 0 ; i < nr_item ; ++i) {
60		rc = odb_update_node(&hash, i);
61		if (rc != EXIT_SUCCESS) {
62			fprintf(stderr, "%s", strerror(rc));
63			exit(EXIT_FAILURE);
64		}
65	}
66
67	end = used_time();
68	odb_close(&hash);
69
70	verbprintf("%s: nr item: %d, elapsed: %f ns\n",
71		   test_name, nr_item, (end - begin) / nr_item);
72}
73
74
75static void do_speed_test(void)
76{
77	int i;
78
79	for (i = 100000; i <= 10000000; i *= 10) {
80		// first test count insertion, second fetch and incr count
81		speed_test(i, "insert");
82		speed_test(i, "update");
83		remove(TEST_FILENAME);
84	}
85}
86
87
88static int test(int nr_item, int nr_unique_item)
89{
90	int i;
91	odb_t hash;
92	int ret;
93	int rc;
94
95	rc = odb_open(&hash, TEST_FILENAME, ODB_RDWR, sizeof(struct opd_header));
96	if (rc) {
97		fprintf(stderr, "%s", strerror(rc));
98		exit(EXIT_FAILURE);
99	}
100
101
102	for (i = 0 ; i < nr_item ; ++i) {
103		odb_key_t key = (random() % nr_unique_item) + 1;
104		rc = odb_update_node(&hash, key);
105		if (rc != EXIT_SUCCESS) {
106			fprintf(stderr, "%s", strerror(rc));
107			exit(EXIT_FAILURE);
108		}
109	}
110
111	ret = odb_check_hash(&hash);
112
113	odb_close(&hash);
114
115	remove(TEST_FILENAME);
116
117	return ret;
118}
119
120
121static void do_test(void)
122{
123	int i, j;
124
125	for (i = 1000; i <= 100000; i *= 10) {
126		for (j = 100 ; j <= i / 10 ; j *= 10) {
127			if (test(i, j)) {
128				fprintf(stderr, "%s:%d failure for %d %d\n",
129				       __FILE__, __LINE__, i, j);
130				nr_error++;
131			} else {
132				verbprintf("test() ok %d %d\n", i, j);
133			}
134		}
135	}
136}
137
138
139static void sanity_check(char const * filename)
140{
141	odb_t hash;
142	int rc;
143
144	rc = odb_open(&hash, filename, ODB_RDONLY, sizeof(struct opd_header));
145	if (rc) {
146		fprintf(stderr, "%s", strerror(rc));
147	        exit(EXIT_FAILURE);
148	}
149
150	if (odb_check_hash(&hash)) {
151		fprintf(stderr, "checking file %s FAIL\n", filename);
152		++nr_error;
153	} else if (verbose) {
154		odb_hash_stat_t * stats;
155		stats = odb_hash_stat(&hash);
156		odb_hash_display_stat(stats);
157		odb_hash_free_stat(stats);
158	}
159
160	odb_close(&hash);
161}
162
163int main(int argc, char * argv[1])
164{
165	/* if a filename is given take it as: "check this db" */
166	if (argc > 1) {
167		int i;
168		verbose = 1;
169		if (!strcmp(argv[1], "--speed"))
170			goto speed_test;
171		for (i = 1 ; i < argc ; ++i)
172			sanity_check(argv[i]);
173		return 0;
174	}
175
176speed_test:
177	remove(TEST_FILENAME);
178
179	do_test();
180
181	do_speed_test();
182
183	if (nr_error)
184		printf("%d error occured\n", nr_error);
185
186	return nr_error ? EXIT_FAILURE : EXIT_SUCCESS;
187}
188