2002-12-14 22:43:18 +01:00
|
|
|
/*
|
|
|
|
* PROGRAM: Client/Server Common Code
|
|
|
|
* MODULE: class_test.cpp
|
|
|
|
* DESCRIPTION: Class library integrity tests
|
|
|
|
*
|
2003-09-08 22:23:46 +02:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
* You may obtain a copy of the Licence at
|
|
|
|
* http://www.gnu.org/licences/lgpl.html
|
|
|
|
*
|
|
|
|
* As a special exception this file can also be included in modules
|
|
|
|
* with other source code as long as that source code has been
|
|
|
|
* released under an Open Source Initiative certificed licence.
|
|
|
|
* More information about OSI certification can be found at:
|
|
|
|
* http://www.opensource.org
|
|
|
|
*
|
|
|
|
* This module is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public Licence for more details.
|
|
|
|
*
|
|
|
|
* This module was created by members of the firebird development
|
|
|
|
* team. All individual contributions remain the Copyright (C) of
|
|
|
|
* those individuals and all rights are reserved. Contributors to
|
|
|
|
* this file are either listed below or can be obtained from a CVS
|
|
|
|
* history command.
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
2003-09-08 22:23:46 +02:00
|
|
|
* Created by: Nickolay Samofatov <skidder@bssys.com>
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
2003-09-08 22:23:46 +02:00
|
|
|
* Contributor(s):
|
|
|
|
*
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
2004-05-17 17:07:49 +02:00
|
|
|
* $Id: class_test.cpp,v 1.14 2004-05-17 15:06:47 brodsom Exp $
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2003-01-06 18:35:21 +01:00
|
|
|
#include "../../include/firebird.h"
|
2002-12-14 22:43:18 +01:00
|
|
|
#include "tree.h"
|
|
|
|
#include "alloc.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
using namespace Firebird;
|
|
|
|
|
|
|
|
void testVector() {
|
|
|
|
printf("Test Firebird::Vector: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
Vector<int, 100> v;
|
2003-01-06 18:35:21 +01:00
|
|
|
int i;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < 100; i++)
|
2002-12-14 22:43:18 +01:00
|
|
|
v.add(i);
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < 50; i++)
|
2002-12-14 22:43:18 +01:00
|
|
|
v.remove(0);
|
|
|
|
bool passed = true;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 50; i < 100; i++)
|
|
|
|
if (v[i - 50] != i)
|
|
|
|
passed = false;
|
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void testSortedVector() {
|
|
|
|
printf("Test Firebird::SortedVector: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
SortedVector<int, 100> v;
|
2003-01-06 18:35:21 +01:00
|
|
|
int i;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < 100; i++)
|
|
|
|
v.add(99 - i);
|
|
|
|
for (i = 0; i < 50; i++)
|
2002-12-14 22:43:18 +01:00
|
|
|
v.remove(0);
|
|
|
|
bool passed = true;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 50;i < 100; i++)
|
|
|
|
if (v[i - 50] != i)
|
|
|
|
passed = false;
|
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
|
2004-05-17 17:07:49 +02:00
|
|
|
const int TEST_ITEMS = 1000000;
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
struct Test {
|
|
|
|
int value;
|
|
|
|
int count;
|
|
|
|
static const int& generate(void *sender, const Test& value) {
|
|
|
|
return value.value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void testBePlusTree() {
|
2003-01-06 18:35:21 +01:00
|
|
|
MallocAllocator temp;
|
|
|
|
printf("Test Firebird::BePlusTree\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
2003-01-06 18:35:21 +01:00
|
|
|
printf("Fill array with test data (%d items)...", TEST_ITEMS);
|
2002-12-14 22:43:18 +01:00
|
|
|
Vector<int, TEST_ITEMS> v;
|
|
|
|
int n = 0;
|
2003-01-06 18:35:21 +01:00
|
|
|
int i;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < TEST_ITEMS; i++) {
|
2002-12-14 22:43:18 +01:00
|
|
|
n = n * 45578 - 17651;
|
|
|
|
// Fill it with quasi-random values in range 0...TEST_ITEMS-1
|
2004-02-02 12:02:12 +01:00
|
|
|
v.add(((i + n) % TEST_ITEMS + TEST_ITEMS) / 2);
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
printf(" DONE\n");
|
|
|
|
|
|
|
|
printf("Create two trees one with factor 2 and one with factor 13 and fill them with test data: ");
|
|
|
|
BePlusTree<Test, int, MallocAllocator, Test,
|
|
|
|
DefaultComparator<int>, 2, 2> tree1(&temp);
|
|
|
|
BePlusTree<Test, int, MallocAllocator, Test,
|
|
|
|
DefaultComparator<int>, 13, 13> tree2(&temp);
|
|
|
|
int cnt1 = 0, cnt2 = 0;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < v.getCount(); i++) {
|
2002-12-14 22:43:18 +01:00
|
|
|
if (tree1.locate(locEqual, v[i]))
|
|
|
|
tree1.current().count++;
|
|
|
|
else {
|
|
|
|
Test t;
|
|
|
|
t.value = v[i];
|
|
|
|
t.count = 1;
|
|
|
|
if (!tree1.add(t))
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2002-12-14 22:43:18 +01:00
|
|
|
cnt1++;
|
|
|
|
}
|
|
|
|
if (tree2.locate(locEqual, v[i]))
|
|
|
|
tree2.current().count++;
|
|
|
|
else {
|
|
|
|
Test t;
|
|
|
|
t.value = v[i];
|
|
|
|
t.count = 1;
|
|
|
|
if (!tree2.add(t))
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2002-12-14 22:43:18 +01:00
|
|
|
cnt2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf(" DONE\n");
|
|
|
|
|
|
|
|
bool passed = true;
|
|
|
|
|
|
|
|
printf("Check that tree(2) contains test data: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < v.getCount(); i++) {
|
|
|
|
if (!tree1.locate(locEqual, v[i]))
|
2002-12-14 22:43:18 +01:00
|
|
|
passed = false;
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
passed = true;
|
|
|
|
|
|
|
|
printf("Check that tree(13) contains test data: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < v.getCount(); i++) {
|
|
|
|
if(!tree2.locate(locEqual, v[i]))
|
2002-12-14 22:43:18 +01:00
|
|
|
passed = false;
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
passed = true;
|
|
|
|
|
|
|
|
printf("Check that tree(2) contains data from the tree(13) and its count is correct: ");
|
|
|
|
n = 0;
|
|
|
|
if (tree1.getFirst()) do {
|
|
|
|
n++;
|
|
|
|
if (!tree2.locate(locEqual, tree1.current().value))
|
|
|
|
passed = false;
|
|
|
|
} while (tree1.getNext());
|
|
|
|
if (n != cnt1 || cnt1 != cnt2)
|
|
|
|
passed = false;
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
printf("Check that tree(13) contains data from the tree(2) "\
|
|
|
|
"and its count is correct (check in reverse order): ");
|
|
|
|
n = 0;
|
|
|
|
if (tree2.getLast()) do {
|
|
|
|
n++;
|
2004-02-02 12:02:12 +01:00
|
|
|
if (!tree1.locate(locEqual, tree2.current().value))
|
|
|
|
passed = false;
|
2002-12-14 22:43:18 +01:00
|
|
|
} while (tree2.getPrev());
|
|
|
|
if (n != cnt2)
|
|
|
|
passed = false;
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
printf("Remove half of data from the trees: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
while (v.getCount() > TEST_ITEMS / 2) {
|
|
|
|
if (!tree1.locate(locEqual, v[v.getCount() - 1]))
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2002-12-14 22:43:18 +01:00
|
|
|
if (tree1.current().count > 1)
|
|
|
|
tree1.current().count--;
|
|
|
|
else {
|
|
|
|
tree1.fastRemove();
|
|
|
|
cnt1--;
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
if (!tree2.locate(locEqual, v[v.getCount() - 1]))
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2002-12-14 22:43:18 +01:00
|
|
|
if (tree2.current().count > 1)
|
|
|
|
tree2.current().count--;
|
|
|
|
else {
|
|
|
|
tree2.fastRemove();
|
|
|
|
cnt2--;
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
v.shrink(v.getCount() - 1);
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
printf(" DONE\n");
|
|
|
|
|
|
|
|
printf("Check that tree(2) contains test data: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < v.getCount(); i++) {
|
|
|
|
if(!tree1.locate(locEqual, v[i]))
|
2002-12-14 22:43:18 +01:00
|
|
|
passed = false;
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
passed = true;
|
|
|
|
|
|
|
|
printf("Check that tree(13) contains test data: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < v.getCount(); i++) {
|
|
|
|
if(!tree2.locate(locEqual, v[i]))
|
2002-12-14 22:43:18 +01:00
|
|
|
passed = false;
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
passed = true;
|
|
|
|
|
|
|
|
printf("Check that tree(2) contains data from the tree(13) and its count is correct: ");
|
|
|
|
n = 0;
|
|
|
|
if (tree1.getFirst()) do {
|
|
|
|
n++;
|
2004-02-02 12:02:12 +01:00
|
|
|
if (!tree2.locate(locEqual, tree1.current().value))
|
|
|
|
passed = false;
|
2002-12-14 22:43:18 +01:00
|
|
|
} while (tree1.getNext());
|
|
|
|
if (n != cnt1 || cnt1 != cnt2)
|
|
|
|
passed = false;
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
passed = true;
|
|
|
|
|
|
|
|
printf("Check that tree(13) contains data from the tree(2) "\
|
|
|
|
"and its count is correct (check in reverse order): ");
|
|
|
|
n = 0;
|
|
|
|
if (tree2.getLast()) do {
|
|
|
|
n++;
|
2004-02-02 12:02:12 +01:00
|
|
|
if (!tree1.locate(locEqual, tree2.current().value))
|
|
|
|
passed = false;
|
2002-12-14 22:43:18 +01:00
|
|
|
} while (tree2.getPrev());
|
|
|
|
if (n != cnt2)
|
|
|
|
passed = false;
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
passed = true;
|
|
|
|
|
|
|
|
printf("Remove the rest of data from the trees: ");
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0;i < v.getCount(); i++) {
|
2002-12-14 22:43:18 +01:00
|
|
|
if (!tree1.locate(locEqual, v[i]))
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2002-12-14 22:43:18 +01:00
|
|
|
if (tree1.current().count > 1)
|
|
|
|
tree1.current().count--;
|
|
|
|
else {
|
|
|
|
tree1.fastRemove();
|
|
|
|
cnt1--;
|
|
|
|
}
|
|
|
|
if (!tree2.locate(locEqual, v[i]))
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2002-12-14 22:43:18 +01:00
|
|
|
if (tree2.current().count > 1)
|
|
|
|
tree2.current().count--;
|
|
|
|
else {
|
|
|
|
tree2.fastRemove();
|
|
|
|
cnt2--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf(" DONE\n");
|
|
|
|
|
|
|
|
printf("Check that both trees do not contain anything: ");
|
|
|
|
if (tree1.getFirst())
|
|
|
|
passed = false;
|
|
|
|
if (tree2.getLast())
|
|
|
|
passed = false;
|
2004-02-02 12:02:12 +01:00
|
|
|
printf(passed ? "PASSED\n" : "FAILED\n");
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
|
2004-05-17 17:07:49 +02:00
|
|
|
const int ALLOC_ITEMS = 1000000;
|
|
|
|
const int MAX_ITEM_SIZE = 50;
|
|
|
|
const int BIG_ITEMS = ALLOC_ITEMS/10;
|
|
|
|
const int BIG_SIZE = MAX_ITEM_SIZE*5;
|
2002-12-14 22:43:18 +01:00
|
|
|
|
2004-05-17 17:07:49 +02:00
|
|
|
const int LARGE_ITEMS = 10;
|
|
|
|
const size_t LARGE_ITEM_SIZE = 300000;
|
2004-03-26 00:12:50 +01:00
|
|
|
|
2002-12-14 22:43:18 +01:00
|
|
|
struct AllocItem {
|
|
|
|
int order;
|
|
|
|
void *item;
|
2004-03-26 00:12:50 +01:00
|
|
|
static bool greaterThan(const AllocItem &i1, const AllocItem &i2) {
|
2004-02-02 12:02:12 +01:00
|
|
|
return i1.order > i2.order || (i1.order == i2.order && i1.item > i2.item);
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void testAllocator() {
|
|
|
|
printf("Test Firebird::MemoryPool\n");
|
2004-03-26 00:12:50 +01:00
|
|
|
MemoryPool* parent = getDefaultMemoryPool();
|
|
|
|
MemoryPool* pool = MemoryPool::createPool(parent);
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
MallocAllocator allocator;
|
2004-02-02 12:02:12 +01:00
|
|
|
BePlusTree<AllocItem, AllocItem, MallocAllocator, DefaultKeyValue<AllocItem>, AllocItem> items(&allocator),
|
2003-01-03 17:03:30 +01:00
|
|
|
bigItems(&allocator);
|
2004-03-26 00:12:50 +01:00
|
|
|
|
|
|
|
Vector<void*, LARGE_ITEMS> la;
|
|
|
|
printf("Allocate %d large items: ", LARGE_ITEMS);
|
|
|
|
int i;
|
|
|
|
for (i = 0; i<LARGE_ITEMS; i++)
|
|
|
|
la.add(pool->allocate(LARGE_ITEM_SIZE));
|
|
|
|
pool->verify_pool();
|
|
|
|
printf(" DONE\n");
|
|
|
|
|
2002-12-14 22:43:18 +01:00
|
|
|
printf("Allocate %d items: ", ALLOC_ITEMS);
|
|
|
|
int n = 0;
|
2002-12-16 19:33:54 +01:00
|
|
|
pool->verify_pool();
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < ALLOC_ITEMS; i++) {
|
2002-12-14 22:43:18 +01:00
|
|
|
n = n * 47163 - 57412;
|
2004-02-02 12:02:12 +01:00
|
|
|
AllocItem temp = {n, pool->allocate((n % MAX_ITEM_SIZE + MAX_ITEM_SIZE) / 2 + 1)};
|
2002-12-14 22:43:18 +01:00
|
|
|
items.add(temp);
|
|
|
|
}
|
|
|
|
printf(" DONE\n");
|
2003-01-03 17:03:30 +01:00
|
|
|
pool->verify_pool();
|
2004-03-26 00:12:50 +01:00
|
|
|
parent->verify_pool();
|
2002-12-14 22:43:18 +01:00
|
|
|
|
2003-01-03 17:03:30 +01:00
|
|
|
printf("Deallocate half of items in quasi-random order: ");
|
|
|
|
n = 0;
|
2002-12-14 22:43:18 +01:00
|
|
|
if (items.getFirst()) do {
|
2003-01-16 18:47:10 +01:00
|
|
|
pool->deallocate(items.current().item);
|
2003-01-03 17:03:30 +01:00
|
|
|
n++;
|
2004-02-02 12:02:12 +01:00
|
|
|
} while (n < ALLOC_ITEMS / 2 && items.getNext());
|
2003-01-03 17:03:30 +01:00
|
|
|
printf(" DONE\n");
|
|
|
|
pool->verify_pool();
|
2004-03-26 00:12:50 +01:00
|
|
|
parent->verify_pool();
|
2003-01-03 17:03:30 +01:00
|
|
|
|
|
|
|
printf("Allocate %d big items: ", BIG_ITEMS);
|
|
|
|
n = 0;
|
|
|
|
pool->verify_pool();
|
2004-02-02 12:02:12 +01:00
|
|
|
for (i = 0; i < BIG_ITEMS; i++) {
|
2003-01-03 17:03:30 +01:00
|
|
|
n = n * 47163 - 57412;
|
2004-02-02 12:02:12 +01:00
|
|
|
AllocItem temp = {n, pool->allocate((n % BIG_SIZE + BIG_SIZE) / 2 + 1)};
|
2003-01-03 17:03:30 +01:00
|
|
|
bigItems.add(temp);
|
|
|
|
}
|
|
|
|
printf(" DONE\n");
|
|
|
|
pool->verify_pool();
|
2004-03-26 00:12:50 +01:00
|
|
|
parent->verify_pool();
|
2003-01-03 17:03:30 +01:00
|
|
|
|
|
|
|
printf("Deallocate the rest of small items in quasi-random order: ");
|
2003-01-10 22:37:18 +01:00
|
|
|
while (items.getNext()) {
|
2003-01-16 18:47:10 +01:00
|
|
|
pool->deallocate(items.current().item);
|
2003-01-10 22:37:18 +01:00
|
|
|
}
|
2002-12-14 22:43:18 +01:00
|
|
|
printf(" DONE\n");
|
2003-01-03 17:03:30 +01:00
|
|
|
pool->verify_pool();
|
2004-03-26 00:12:50 +01:00
|
|
|
parent->verify_pool();
|
2003-01-03 17:03:30 +01:00
|
|
|
|
|
|
|
printf("Deallocate big items in quasi-random order: ");
|
|
|
|
if (bigItems.getFirst()) do {
|
2003-01-16 18:47:10 +01:00
|
|
|
pool->deallocate(bigItems.current().item);
|
2003-01-03 17:03:30 +01:00
|
|
|
} while (bigItems.getNext());
|
|
|
|
printf(" DONE\n");
|
2004-03-26 00:12:50 +01:00
|
|
|
|
|
|
|
printf("Deallocate %d large items: ", LARGE_ITEMS/2);
|
|
|
|
for (i = 0; i<LARGE_ITEMS/2; i++)
|
|
|
|
pool->deallocate(la[i]);
|
|
|
|
pool->verify_pool();
|
|
|
|
printf(" DONE\n");
|
|
|
|
|
|
|
|
|
2003-01-03 17:03:30 +01:00
|
|
|
pool->verify_pool();
|
2004-03-26 00:12:50 +01:00
|
|
|
parent->verify_pool();
|
|
|
|
pool->print_contents(stdout, false);
|
|
|
|
parent->print_contents(stdout, false);
|
2003-01-09 20:47:46 +01:00
|
|
|
MemoryPool::deletePool(pool);
|
2004-03-26 00:12:50 +01:00
|
|
|
parent->verify_pool();
|
2002-12-14 22:43:18 +01:00
|
|
|
// TODO:
|
|
|
|
// Test critically low memory conditions
|
2004-03-26 00:12:50 +01:00
|
|
|
// Test that tree correctly recovers in low-memory conditions
|
2002-12-14 22:43:18 +01:00
|
|
|
}
|
|
|
|
|
2003-01-07 17:35:10 +01:00
|
|
|
int main() {
|
2002-12-14 22:43:18 +01:00
|
|
|
testVector();
|
|
|
|
testSortedVector();
|
|
|
|
testBePlusTree();
|
|
|
|
testAllocator();
|
|
|
|
}
|
2004-02-02 12:02:12 +01:00
|
|
|
|