1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /* use sequental numbers printed to strings
39 * to store lots and lots of entries in the
42 * Start with 100 entries, put them and then
43 * read them out. Then delete the first
44 * half and verify that all of the first half
45 * is gone and then verify that the second
46 * half is still there.
47 * Then add the first half back and verify
48 * again. Then delete the middle third
50 * Then increase the size by 1000 and do
51 * the whole add delete thing again.
53 * The data for each object is the number string translated
54 * to hex and replicated a random number of times. The
55 * number of times that the data is replicated is the first
78 #if defined(_WINDOWS) && !defined(WIN32)
80 #define uint32 unsigned long
83 #define uint32 unsigned int
91 #define TraceMe(priority, msg) \
93 if(priority <= MsgPriority) \
100 ReportStatus(char *string
, ...)
105 va_start(args
, string
);
109 vfprintf(stderr
, string
, args
);
112 fprintf (stderr
, "\n");
118 ReportError(char *string
, ...)
123 va_start(args
, string
);
127 fprintf (stderr
, "\n ");
128 vfprintf(stderr
, string
, args
);
129 fprintf (stderr
, "\n");
135 DBT
* MakeLargeKey(int32 num
)
139 static char *string_rv
=0;
146 /* generate a really large text key derived from
149 low_bits
= (num
% 10000) + 1;
151 /* get the repeat char from the low 26 */
152 rep_char
= (char) ((low_bits
% 26) + 'a');
154 /* malloc a string low_bits wide */
155 size
= low_bits
*sizeof(char);
156 string_rv
= (char *)malloc(size
);
158 memset(string_rv
, rep_char
, size
);
166 DBT
* MakeSmallKey(int32 num
)
169 static char data_string
[64];
171 rv
.data
= data_string
;
173 sprintf(data_string
, "%ld", (long)num
);
174 rv
.size
= strlen(data_string
);
180 DBT
* GenKey(int32 num
, key_type_enum key_type
)
187 key
= MakeLargeKey(num
);
190 key
= MakeSmallKey(num
);
206 ReportStatus("SEQuencing through database...");
208 /* seq through the whole database */
209 if(!(status
= (*database
->seq
)(database
, &key
, &data
, R_FIRST
)))
211 while(!(status
= (database
->seq
) (database
, &key
, &data
, R_NEXT
)))
216 ReportError("Error seq'ing database");
222 VerifyData(DBT
*data
, int32 num
, key_type_enum key_type
)
224 int32 count
, compare_num
;
228 /* The first int32 is count
229 * The other n entries should
232 if(data
->size
< sizeof(int32
))
234 ReportError("Data size corrupted");
238 memcpy(&count
, data
->data
, sizeof(int32
));
240 size
= sizeof(int32
)*(count
+1);
242 if(size
!= data
->size
)
244 ReportError("Data size corrupted");
248 int32_array
= (int32
*)data
->data
;
250 for(;count
> 0; count
--)
252 memcpy(&compare_num
, &int32_array
[count
], sizeof(int32
));
254 if(compare_num
!= num
)
256 ReportError("Data corrupted");
265 /* verify that a range of number strings exist
266 * or don't exist. And that the data is valid
268 #define SHOULD_EXIST 1
269 #define SHOULD_NOT_EXIST 0
271 VerifyRange(int32 low
, int32 high
, int32 should_exist
, key_type_enum key_type
)
277 TraceMe(1, ("Verifying: %ld to %ld, using %s keys",
278 low
, high
, key_type
== USE_SMALL_KEY
? "SMALL" : "LARGE"));
280 for(num
= low
; num
<= high
; num
++)
283 key
= GenKey(num
, key_type
);
285 status
= (*database
->get
)(database
, key
, &data
, 0);
292 ReportError("Item exists but shouldn't: %ld", num
);
296 /* else verify the data */
297 VerifyData(&data
, num
, key_type
);
305 ReportError("Item not found but should be: %ld", num
);
311 ReportError("Database error");
317 TraceMe(1, ("Correctly verified: %ld to %ld", low
, high
));
333 data
= (DBT
*)malloc(sizeof(DBT
));
344 n
= n
% 512; /* bound to a 2K size */
347 size
= sizeof(int32
)*(n
+1);
348 int32_array
= (int32
*) malloc(size
);
350 memcpy(&int32_array
[0], &n
, sizeof(int32
));
354 memcpy(&int32_array
[n
], &num
, sizeof(int32
));
357 data
->data
= (void*)int32_array
;
364 #define DELETE_RANGE 2
367 AddOrDelRange(int32 low
, int32 high
, int action
, key_type_enum key_type
)
370 #if 0 /* only do this if your really analy checking the puts */
376 if(action
!= ADD_RANGE
&& action
!= DELETE_RANGE
)
379 if(action
== ADD_RANGE
)
381 TraceMe(1, ("Adding: %ld to %ld: %s keys", low
, high
,
382 key_type
== USE_SMALL_KEY
? "SMALL" : "LARGE"));
386 TraceMe(1, ("Deleting: %ld to %ld: %s keys", low
, high
,
387 key_type
== USE_SMALL_KEY
? "SMALL" : "LARGE"));
390 for(num
= low
; num
<= high
; num
++)
393 key
= GenKey(num
, key_type
);
395 if(action
== ADD_RANGE
)
398 status
= (*database
->put
)(database
, key
, data
, 0);
402 status
= (*database
->del
)(database
, key
, 0);
407 ReportError("Database error %s item: %ld",
408 action
== ADD_RANGE
? "ADDING" : "DELETING",
413 ReportError("Could not %s item: %ld",
414 action
== ADD_RANGE
? "ADD" : "DELETE",
417 else if(action
== ADD_RANGE
)
419 #define SYNC_EVERY_TIME
420 #ifdef SYNC_EVERY_TIME
421 status
= (*database
->sync
)(database
, 0);
423 ReportError("Database error syncing after add");
426 #if 0 /* only do this if your really analy checking the puts */
428 /* make sure we can still get it
430 status
= (*database
->get
)(database
, key
, &tmp_data
, 0);
434 ReportError("Database error checking item just added: %d",
439 /* now verify that none of the ones we already
440 * put in have disappeared
442 VerifyRange(low
, num
, SHOULD_EXIST
, key_type
);
450 if(action
== ADD_RANGE
)
452 TraceMe(1, ("Successfully added: %ld to %ld", low
, high
));
456 TraceMe(1, ("Successfully deleted: %ld to %ld", low
, high
));
463 TestRange(int32 low
, int32 range
, key_type_enum key_type
)
465 int status
; int32 low_of_range1
, high_of_range1
; int32 low_of_range2
, high_of_range2
;
466 int32 low_of_range3
, high_of_range3
;
468 status
= AddOrDelRange(low
, low
+range
, ADD_RANGE
, key_type
);
469 status
= VerifyRange(low
, low
+range
, SHOULD_EXIST
, key_type
);
471 TraceMe(1, ("Finished with sub test 1"));
476 high_of_range1
= low
+(range
/2);
477 low_of_range2
= high_of_range1
+1;
478 high_of_range2
= low
+range
;
479 status
= AddOrDelRange(low_of_range1
, high_of_range1
, DELETE_RANGE
, key_type
);
480 status
= VerifyRange(low_of_range1
, high_of_range1
, SHOULD_NOT_EXIST
, key_type
);
481 status
= VerifyRange(low_of_range2
, low_of_range2
, SHOULD_EXIST
, key_type
);
483 TraceMe(1, ("Finished with sub test 2"));
487 status
= AddOrDelRange(low_of_range1
, high_of_range1
, ADD_RANGE
, key_type
);
488 /* the whole thing should exist now */
489 status
= VerifyRange(low
, low
+range
, SHOULD_EXIST
, key_type
);
491 TraceMe(1, ("Finished with sub test 3"));
495 status
= AddOrDelRange(low_of_range2
, high_of_range2
, DELETE_RANGE
, key_type
);
496 status
= VerifyRange(low_of_range1
, high_of_range1
, SHOULD_EXIST
, key_type
);
497 status
= VerifyRange(low_of_range2
, high_of_range2
, SHOULD_NOT_EXIST
, key_type
);
499 TraceMe(1, ("Finished with sub test 4"));
503 status
= AddOrDelRange(low_of_range2
, high_of_range2
, ADD_RANGE
, key_type
);
504 /* the whole thing should exist now */
505 status
= VerifyRange(low
, low
+range
, SHOULD_EXIST
, key_type
);
507 TraceMe(1, ("Finished with sub test 5"));
512 high_of_range1
= low
+(range
/3);
513 low_of_range2
= high_of_range1
+1;
514 high_of_range2
= high_of_range1
+(range
/3);
515 low_of_range3
= high_of_range2
+1;
516 high_of_range3
= low
+range
;
518 status
= AddOrDelRange(low_of_range2
, high_of_range2
, DELETE_RANGE
, key_type
);
519 status
= VerifyRange(low_of_range1
, high_of_range1
, SHOULD_EXIST
, key_type
);
520 status
= VerifyRange(low_of_range2
, low_of_range2
, SHOULD_NOT_EXIST
, key_type
);
521 status
= VerifyRange(low_of_range3
, low_of_range2
, SHOULD_EXIST
, key_type
);
523 TraceMe(1, ("Finished with sub test 6"));
527 status
= AddOrDelRange(low_of_range2
, high_of_range2
, ADD_RANGE
, key_type
);
528 /* the whole thing should exist now */
529 status
= VerifyRange(low
, low
+range
, SHOULD_EXIST
, key_type
);
531 TraceMe(1, ("Finished with sub test 7"));
536 #define START_RANGE 109876
538 main(int argc
, char **argv
)
543 HASHINFO hash_info
= {
556 if(!strcmp(argv
[argc
-1], "-quick"))
558 else if(!strcmp(argv
[argc
-1], "-large"))
566 database
= dbopen("test.db", O_RDWR
| O_CREAT
, 0644, DB_HASH
, &hash_info
);
570 ReportError("Could not open database");
580 TestRange(START_RANGE
, 200, USE_LARGE_KEY
);
582 TestRange(START_RANGE
, 200, USE_SMALL_KEY
);
584 (*database
->sync
)(database
, 0);
585 (*database
->close
)(database
);
589 for(i
=100; i
< 10000000; i
+=200)
593 TestRange(START_RANGE
, i
, USE_LARGE_KEY
);
598 TestRange(START_RANGE
, i
, USE_SMALL_KEY
);
604 (*database
->sync
)(database
, 0);
609 /* close and reopen */
610 (*database
->close
)(database
);
611 database
= dbopen("test.db", O_RDWR
| O_CREAT
, 0644, DB_HASH
, 0);
614 ReportError("Could not reopen database");
623 /* reopen database without closeing the other */
624 database
= dbopen("test.db", O_RDWR
| O_CREAT
, 0644, DB_HASH
, 0);
627 ReportError("Could not reopen database "
628 "after not closing the other");