diff nss/lib/dbm/tests/lots.c @ 3:150b72113545

Add DBM and legacydb support
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 05 Aug 2014 18:32:02 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/dbm/tests/lots.c	Tue Aug 05 18:32:02 2014 +0200
@@ -0,0 +1,606 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* use sequental numbers printed to strings
+ * to store lots and lots of entries in the
+ * database.
+ *
+ * Start with 100 entries, put them and then
+ * read them out.  Then delete the first
+ * half and verify that all of the first half
+ * is gone and then verify that the second
+ * half is still there.
+ * Then add the first half back and verify
+ * again.  Then delete the middle third
+ * and verify again.
+ * Then increase the size by 1000 and do
+ * the whole add delete thing again.
+ *
+ * The data for each object is the number string translated
+ * to hex and replicated a random number of times.  The
+ * number of times that the data is replicated is the first
+ * int32 in the data.
+ */
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#ifdef STDC_HEADERS
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <string.h>
+#include <assert.h>
+#include "mcom_db.h"
+
+DB *database=0;
+int MsgPriority=5;
+
+#if defined(_WINDOWS) && !defined(WIN32)
+#define int32 long
+#define uint32 unsigned long
+#else
+#define int32 int
+#define uint32 unsigned int
+#endif
+
+typedef enum {
+USE_LARGE_KEY,
+USE_SMALL_KEY
+} key_type_enum;
+
+#define TraceMe(priority, msg) 		\
+	do {							\
+		if(priority <= MsgPriority)	\
+		  {							\
+			ReportStatus msg;		\
+		  }							\
+	} while(0)
+
+int
+ReportStatus(char *string, ...)
+{
+    va_list args;
+
+#ifdef STDC_HEADERS
+    va_start(args, string);
+#else
+    va_start(args);
+#endif
+    vfprintf(stderr, string, args);
+    va_end(args);
+
+	fprintf (stderr, "\n");
+
+	return(0);
+}
+
+int
+ReportError(char *string, ...)
+{
+    va_list args;
+
+#ifdef STDC_HEADERS
+    va_start(args, string);
+#else
+    va_start(args);
+#endif
+	fprintf (stderr, "\n	");
+    vfprintf(stderr, string, args);
+	fprintf (stderr, "\n");
+    va_end(args);
+
+	return(0);
+}
+
+DBT * MakeLargeKey(int32 num)
+{
+	int32 low_bits;
+	static DBT rv;
+	static char *string_rv=0;
+	int rep_char;
+	size_t size;
+
+	if(string_rv)
+		free(string_rv);
+
+	/* generate a really large text key derived from
+	 * an int32
+	 */
+	low_bits = (num % 10000) + 1;
+
+	/* get the repeat char from the low 26 */
+	rep_char = (char) ((low_bits % 26) + 'a');
+
+	/* malloc a string low_bits wide */
+	size = low_bits*sizeof(char);
+	string_rv = (char *)malloc(size);
+
+	memset(string_rv, rep_char, size);
+
+	rv.data = string_rv;
+	rv.size = size;
+
+	return(&rv);
+}
+
+DBT * MakeSmallKey(int32 num)
+{
+	static DBT rv;
+	static char data_string[64];
+
+	rv.data = data_string;
+
+	sprintf(data_string, "%ld", (long)num);
+	rv.size = strlen(data_string);
+
+	return(&rv);
+
+}
+
+DBT * GenKey(int32 num, key_type_enum key_type)
+{
+	DBT *key;
+
+	switch(key_type)
+	  {
+		case USE_LARGE_KEY:
+			key = MakeLargeKey(num);
+			break;
+		case USE_SMALL_KEY:
+			key = MakeSmallKey(num);
+			break;
+		default:
+			abort();
+			break;
+	  }
+
+	return(key);
+}
+
+int
+SeqDatabase()
+{
+	int status;
+	DBT key, data;
+
+	ReportStatus("SEQuencing through database...");
+
+	/* seq through the whole database */
+    if(!(status = (*database->seq)(database, &key, &data, R_FIRST)))
+	  {
+        while(!(status = (database->seq) (database, &key, &data, R_NEXT)))
+			; /* null body */
+	  }
+
+	if(status < 0)
+		ReportError("Error seq'ing database");
+
+	return(status);
+}
+
+int 
+VerifyData(DBT *data, int32 num, key_type_enum key_type)
+{
+	int32 count, compare_num;
+	size_t size;
+	int32 *int32_array;
+
+	/* The first int32 is count 
+	 * The other n entries should
+	 * all equal num
+	 */
+	if(data->size < sizeof(int32))
+	  {
+		ReportError("Data size corrupted");
+		return -1;
+	  }
+
+	memcpy(&count, data->data, sizeof(int32));
+
+	size = sizeof(int32)*(count+1);
+
+	if(size != data->size)
+	  {
+		ReportError("Data size corrupted");
+		return -1;
+	  }
+
+	int32_array = (int32*)data->data;
+
+	for(;count > 0; count--)
+	  {
+		memcpy(&compare_num, &int32_array[count], sizeof(int32));
+
+		if(compare_num != num)
+	      {
+		    ReportError("Data corrupted");
+		    return -1;
+	      }
+	  }
+
+	return(0);
+}
+
+
+/* verify that a range of number strings exist
+ * or don't exist. And that the data is valid
+ */
+#define SHOULD_EXIST 1
+#define SHOULD_NOT_EXIST 0
+int
+VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type)
+{
+	DBT *key, data;
+	int32 num;
+	int status;
+
+	TraceMe(1, ("Verifying: %ld to %ld, using %s keys", 
+		    low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
+
+	for(num = low; num <= high; num++)
+	  {
+
+		key = GenKey(num, key_type);
+
+		status = (*database->get)(database, key, &data, 0);
+
+		if(status == 0)
+		  {
+			/* got the item */
+			if(!should_exist)
+			  {
+				ReportError("Item exists but shouldn't: %ld", num);
+			  }
+			else
+			  {
+			    /* else verify the data */
+			    VerifyData(&data, num, key_type);
+			  }
+		  }
+		else if(status > 0)
+		  {
+			/* item not found */
+			if(should_exist)
+			  {
+				ReportError("Item not found but should be: %ld", num);
+			  }
+		  }
+		else
+		  {
+			/* database error */
+			ReportError("Database error");
+			return(-1);
+		  }
+			
+	  }
+
+	TraceMe(1, ("Correctly verified: %ld to %ld", low, high));
+
+	return(0);
+
+}
+
+DBT *
+GenData(int32 num)
+{
+	int32 n;
+	static DBT *data=0;
+	int32 *int32_array;
+	size_t size;
+
+	if(!data)
+	  {
+		data = (DBT*)malloc(sizeof(DBT));
+		data->size = 0;
+		data->data = 0;
+	  }
+	else if(data->data)
+	  {
+		free(data->data);
+	  }
+
+	n = rand();
+
+	n = n % 512;  /* bound to a 2K size */
+
+	
+	size = sizeof(int32)*(n+1);
+	int32_array = (int32 *) malloc(size);
+
+	memcpy(&int32_array[0], &n, sizeof(int32));
+
+	for(; n > 0; n--)
+	  {
+		memcpy(&int32_array[n], &num, sizeof(int32));
+	  }
+
+	data->data = (void*)int32_array;
+	data->size = size;
+
+	return(data);
+}
+
+#define ADD_RANGE 1
+#define DELETE_RANGE 2
+
+int
+AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type)
+{
+	DBT *key, *data;
+#if 0 /* only do this if your really analy checking the puts */
+	DBT tmp_data;
+#endif 
+	int32 num;
+	int status;
+
+	if(action != ADD_RANGE && action != DELETE_RANGE)
+		assert(0);
+
+	if(action == ADD_RANGE)
+	  {
+		TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high,
+		    	key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
+	  }
+	else
+	  {
+		TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high,
+		    	key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
+	  }
+
+	for(num = low; num <= high; num++)
+	  {
+
+		key = GenKey(num, key_type);
+
+		if(action == ADD_RANGE)
+		  {
+			data = GenData(num);
+			status = (*database->put)(database, key, data, 0);
+		  }
+		else
+		  {
+			status = (*database->del)(database, key, 0);
+		  }
+
+		if(status < 0)
+		  {
+			ReportError("Database error %s item: %ld",
+							action == ADD_RANGE ? "ADDING" : "DELETING", 
+							num);
+		  }
+		else if(status > 0)
+		  {
+			ReportError("Could not %s item: %ld", 
+							action == ADD_RANGE ? "ADD" : "DELETE", 
+							num);
+		  }
+		else if(action == ADD_RANGE)
+		  {
+#define SYNC_EVERY_TIME
+#ifdef SYNC_EVERY_TIME
+			status = (*database->sync)(database, 0);
+			if(status != 0)
+				ReportError("Database error syncing after add");
+#endif
+
+#if 0 /* only do this if your really analy checking the puts */
+	 
+			/* make sure we can still get it
+			 */
+			status = (*database->get)(database, key, &tmp_data, 0);
+
+			if(status != 0)
+			  {
+				ReportError("Database error checking item just added: %d",
+							num);
+			  }
+			else
+			  {
+				/* now verify that none of the ones we already
+				 * put in have disappeared
+				 */
+				VerifyRange(low, num, SHOULD_EXIST, key_type);
+			  }
+#endif
+			
+		  }
+	  }
+
+
+	if(action == ADD_RANGE)
+	  {
+		TraceMe(1, ("Successfully added: %ld to %ld", low, high));
+	  }
+	else
+	  {
+		TraceMe(1, ("Successfully deleted: %ld to %ld", low, high));
+	  }
+
+	return(0);
+}
+
+int
+TestRange(int32 low, int32 range, key_type_enum key_type)
+{
+	int status; int32 low_of_range1, high_of_range1; int32 low_of_range2, high_of_range2;
+	int32 low_of_range3, high_of_range3;
+
+	status = AddOrDelRange(low, low+range, ADD_RANGE, key_type);
+	status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 1"));
+
+	SeqDatabase();
+
+	low_of_range1 = low;
+	high_of_range1 = low+(range/2);
+	low_of_range2 = high_of_range1+1;
+	high_of_range2 = low+range;
+	status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type);
+	status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type);
+	status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 2"));
+
+	SeqDatabase();
+
+	status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type);
+	/* the whole thing should exist now */
+	status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 3"));
+
+	SeqDatabase();
+
+	status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
+	status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
+	status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 4"));
+
+	SeqDatabase();
+
+	status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
+	/* the whole thing should exist now */
+	status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 5"));
+
+	SeqDatabase();
+
+	low_of_range1 = low;
+	high_of_range1 = low+(range/3);
+	low_of_range2 = high_of_range1+1;
+	high_of_range2 = high_of_range1+(range/3);
+	low_of_range3 = high_of_range2+1;
+	high_of_range3 = low+range;
+	/* delete range 2 */
+	status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
+	status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
+	status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type);
+	status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 6"));
+
+	SeqDatabase();
+
+	status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
+	/* the whole thing should exist now */
+	status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
+
+	TraceMe(1, ("Finished with sub test 7"));
+
+	return(0);
+}
+
+#define START_RANGE 109876
+int
+main(int argc, char **argv)
+{
+	int32 i, j=0;
+    int quick_exit = 0;
+    int large_keys = 0;
+    HASHINFO hash_info = {
+        16*1024,
+        0,
+        0,
+        0,
+        0,
+        0};
+
+
+    if(argc > 1)
+      {
+        while(argc > 1)
+	  {
+            if(!strcmp(argv[argc-1], "-quick"))
+                quick_exit = 1;
+            else if(!strcmp(argv[argc-1], "-large"))
+			  {
+                large_keys = 1;
+			  }
+            argc--;
+          }
+      }
+
+	database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info);
+
+	if(!database)
+	  {
+		ReportError("Could not open database");
+#ifdef unix
+		perror("");
+#endif
+		exit(1);
+	  }
+
+	if(quick_exit)
+	  {
+		if(large_keys)
+			TestRange(START_RANGE, 200, USE_LARGE_KEY);
+		else
+			TestRange(START_RANGE, 200, USE_SMALL_KEY);
+
+		(*database->sync)(database, 0);
+		(*database->close)(database);
+        exit(0);
+	  }
+
+	for(i=100; i < 10000000; i+=200)
+	  {
+		if(1 || j)
+		  {
+			TestRange(START_RANGE, i, USE_LARGE_KEY);
+			j = 0;
+		  }
+		else
+		  {
+			TestRange(START_RANGE, i, USE_SMALL_KEY);
+			j = 1;
+		  }
+
+		if(1 == rand() % 3)
+		  {
+			(*database->sync)(database, 0);
+		  }
+		
+		if(1 == rand() % 3)
+	 	  {
+			/* close and reopen */
+			(*database->close)(database);
+			database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
+			if(!database)
+	  		{
+				ReportError("Could not reopen database");
+#ifdef unix
+				perror("");
+#endif
+				exit(1);
+	  		}
+	 	  }
+		else
+		  {
+			/* reopen database without closeing the other */
+			database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
+			if(!database)
+	  		{
+				ReportError("Could not reopen database "
+							"after not closing the other");
+#ifdef unix
+				perror("");
+#endif
+				exit(1);
+	  		}
+	 	  }
+	  }
+
+	return(0);
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)