Implemented find/find closest for B+ tree.
Added test suite. Fixed some b+ tree bugs.
This commit is contained in:
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="ClangTidyInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="clangTidyChecks" value="*,-android-*,-bugprone-bool-pointer-implicit-conversion,-cert-env33-c,-cert-dcl50-cpp,-cert-dcl59-cpp,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-*,google-default-arguments,google-explicit-constructor,google-runtime-member-string-references,google-runtime-operator,-hicpp-braces-around-statements,-hicpp-named-parameter,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-no-malloc,-hicpp-function-size,-hicpp-special-member-functions,-hicpp-vararg,-llvm-*,-objc-*,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-simplify-boolean-expr,-readability-braces-around-statements,-readability-identifier-naming,-readability-function-size,-readability-redundant-member-init,-misc-bool-pointer-implicit-conversion,-misc-definitions-in-headers,-misc-unused-alias-decls,-misc-unused-parameters,-misc-unused-using-decls,-modernize-use-using,-modernize-use-default-member-init,-clang-diagnostic-*,-clang-analyzer-*,-hicpp-signed-bitwise" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -1,6 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
<component name="CidrRootsConfiguration">
|
||||||
|
<sourceRoots>
|
||||||
|
<file path="$PROJECT_DIR$/lib" />
|
||||||
|
<file path="$PROJECT_DIR$/src" />
|
||||||
|
</sourceRoots>
|
||||||
|
</component>
|
||||||
<component name="JavaScriptSettings">
|
<component name="JavaScriptSettings">
|
||||||
<option name="languageLevel" value="ES6" />
|
<option name="languageLevel" value="ES6" />
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -1,7 +1,41 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(SDB C)
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
project(SDB C)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/lib)
|
#Check options
|
||||||
add_executable(SDB src/main.c src/InputBuffer.c src/InputBuffer.h src/SQL.c src/SQL.h src/scanner.c src/scanner.h src/parser.c src/parser.h src/bplus_tree.c src/bplus_tree.h)
|
include(CheckCSourceCompiles)
|
||||||
|
include(CheckCSourceRuns)
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
include(CheckIncludeFiles)
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
set(INCLUDES "")
|
||||||
|
macro(ck_check_include_file header var)
|
||||||
|
check_include_files("${INCLUDES};${header}" ${var})
|
||||||
|
if(${var})
|
||||||
|
set(INCLUDES ${INCLUDES} ${header})
|
||||||
|
endif(${var})
|
||||||
|
endmacro(ck_check_include_file)
|
||||||
|
|
||||||
|
ck_check_include_file("stdlib.h" HAVE_STDLIB_H)
|
||||||
|
check_type_size(intmax_t INTMAX_T)
|
||||||
|
check_type_size(uintmax_t UINTMAX_T)
|
||||||
|
|
||||||
|
check_type_size(pid_t PID_T)
|
||||||
|
if(NOT HAVE_PID_T)
|
||||||
|
if(WIN32)
|
||||||
|
set(pid_t "int")
|
||||||
|
else(WIN32)
|
||||||
|
MESSAGE(FATAL_ERROR "pid_t doesn't exist on this platform?")
|
||||||
|
endif(WIN32)
|
||||||
|
endif(NOT HAVE_PID_T)
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
add_test(NAME check_SDB COMMAND check_SDB)
|
||||||
57
cmake/FindCheck.cmake
Normal file
57
cmake/FindCheck.cmake
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# - Try to find the CHECK libraries
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# CHECK_FOUND - system has check
|
||||||
|
# CHECK_INCLUDE_DIR - the check include directory
|
||||||
|
# CHECK_LIBRARIES - check library
|
||||||
|
#
|
||||||
|
# This configuration file for finding libcheck is originally from
|
||||||
|
# the opensync project. The originally was downloaded from here:
|
||||||
|
# opensync.org/browser/branches/3rd-party-cmake-modules/modules/FindCheck.cmake
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||||
|
# Copyright (c) 2007 Bjoern Ricks <b.ricks@fh-osnabrueck.de>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the New
|
||||||
|
# BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
|
||||||
|
|
||||||
|
INCLUDE( FindPkgConfig )
|
||||||
|
|
||||||
|
# Take care about check.pc settings
|
||||||
|
PKG_SEARCH_MODULE( CHECK check )
|
||||||
|
|
||||||
|
# Look for CHECK include dir and libraries
|
||||||
|
IF( NOT CHECK_FOUND )
|
||||||
|
IF ( CHECK_INSTALL_DIR )
|
||||||
|
MESSAGE ( STATUS "Using override CHECK_INSTALL_DIR to find check" )
|
||||||
|
SET ( CHECK_INCLUDE_DIR "${CHECK_INSTALL_DIR}/include" )
|
||||||
|
SET ( CHECK_INCLUDE_DIRS "${CHECK_INCLUDE_DIR}" )
|
||||||
|
FIND_LIBRARY( CHECK_LIBRARY NAMES check PATHS "${CHECK_INSTALL_DIR}/lib" )
|
||||||
|
FIND_LIBRARY( COMPAT_LIBRARY NAMES compat PATHS "${CHECK_INSTALL_DIR}/lib" )
|
||||||
|
SET ( CHECK_LIBRARIES "${CHECK_LIBRARY}" "${COMPAT_LIBRARY}" )
|
||||||
|
ELSE ( CHECK_INSTALL_DIR )
|
||||||
|
FIND_PATH( CHECK_INCLUDE_DIR check.h )
|
||||||
|
FIND_LIBRARY( CHECK_LIBRARIES NAMES check )
|
||||||
|
ENDIF ( CHECK_INSTALL_DIR )
|
||||||
|
|
||||||
|
IF ( CHECK_INCLUDE_DIR AND CHECK_LIBRARIES )
|
||||||
|
SET( CHECK_FOUND 1 )
|
||||||
|
IF ( NOT Check_FIND_QUIETLY )
|
||||||
|
MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" )
|
||||||
|
ENDIF ( NOT Check_FIND_QUIETLY )
|
||||||
|
ELSE ( CHECK_INCLUDE_DIR AND CHECK_LIBRARIES )
|
||||||
|
IF ( Check_FIND_REQUIRED )
|
||||||
|
MESSAGE( FATAL_ERROR "Could NOT find CHECK" )
|
||||||
|
ELSE ( Check_FIND_REQUIRED )
|
||||||
|
IF ( NOT Check_FIND_QUIETLY )
|
||||||
|
MESSAGE( STATUS "Could NOT find CHECK" )
|
||||||
|
ENDIF ( NOT Check_FIND_QUIETLY )
|
||||||
|
ENDIF ( Check_FIND_REQUIRED )
|
||||||
|
ENDIF ( CHECK_INCLUDE_DIR AND CHECK_LIBRARIES )
|
||||||
|
ENDIF( NOT CHECK_FOUND )
|
||||||
|
|
||||||
|
# Hide advanced variables from CMake GUIs
|
||||||
|
MARK_AS_ADVANCED( CHECK_INCLUDE_DIR CHECK_LIBRARIES )
|
||||||
|
|
||||||
0
lib/.gitkeep
Normal file
0
lib/.gitkeep
Normal file
7
src/CMakeLists.txt
Normal file
7
src/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../lib)
|
||||||
|
|
||||||
|
add_library(SDBLib STATIC InputBuffer.c InputBuffer.h SQL.c SQL.h scanner.c scanner.h parser.c parser.h bplus_tree.c bplus_tree.h)
|
||||||
|
|
||||||
|
add_executable(SDB main.c)
|
||||||
|
target_link_libraries(SDB SDBLib)
|
||||||
110
src/bplus_tree.c
110
src/bplus_tree.c
@@ -7,6 +7,14 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "bplus_tree.h"
|
#include "bplus_tree.h"
|
||||||
|
|
||||||
|
#define APPEND_STR(str, size, _) { \
|
||||||
|
if (strlen(_) + strlen(str) + 1 > (size)) { \
|
||||||
|
(size) *= 2; \
|
||||||
|
(str) = realloc(str, (size) * sizeof(char)); \
|
||||||
|
} \
|
||||||
|
strcat(str, _);\
|
||||||
|
}
|
||||||
|
|
||||||
BPlusKV *new_bplus_kv(uint64_t key, void *value, BPlusNode *leftPointer) {
|
BPlusKV *new_bplus_kv(uint64_t key, void *value, BPlusNode *leftPointer) {
|
||||||
BPlusKV *kv = malloc(sizeof(BPlusKV));
|
BPlusKV *kv = malloc(sizeof(BPlusKV));
|
||||||
kv->key = key;
|
kv->key = key;
|
||||||
@@ -93,6 +101,9 @@ void print_bplus_node(BPlusNode *node, size_t indent) {
|
|||||||
} else {
|
} else {
|
||||||
printf("%sLEAF #%ld (%ld/%ld)\n", indentStr, node->id, node->keyCount, node->order);
|
printf("%sLEAF #%ld (%ld/%ld)\n", indentStr, node->id, node->keyCount, node->order);
|
||||||
}
|
}
|
||||||
|
if (node->parent != NULL) {
|
||||||
|
printf("%s Parent #%ld\n", indentStr, node->parent->id);
|
||||||
|
}
|
||||||
|
|
||||||
if (node->leftPointer != NULL) {
|
if (node->leftPointer != NULL) {
|
||||||
print_bplus_node(node->leftPointer, indent + 4);
|
print_bplus_node(node->leftPointer, indent + 4);
|
||||||
@@ -115,6 +126,24 @@ void print_bplus_node(BPlusNode *node, size_t indent) {
|
|||||||
free(indentStr);
|
free(indentStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *debug_bplus_node_str(BPlusNode *node, char *str, size_t *strSize) {
|
||||||
|
APPEND_STR(str, *strSize, "[");
|
||||||
|
if (node->leftPointer != NULL) {
|
||||||
|
str = debug_bplus_node_str(node->leftPointer, str, strSize);
|
||||||
|
}
|
||||||
|
char buffer[32] = {0};
|
||||||
|
for (size_t i = 0; i < node->keyCount; i++) {
|
||||||
|
snprintf(buffer, 32, node->isInternal ? "{%ld}" : "{%ld*}", node->keys[i]->key);
|
||||||
|
APPEND_STR(str, *strSize, buffer);
|
||||||
|
if (node->keys[i]->rightPointer != NULL) {
|
||||||
|
str = debug_bplus_node_str(node->keys[i]->rightPointer, str, strSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
APPEND_STR(str, *strSize, "]");
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
BPlusTree *new_bplus_tree(size_t order) {
|
BPlusTree *new_bplus_tree(size_t order) {
|
||||||
BPlusTree *tree = malloc(sizeof(BPlusTree));
|
BPlusTree *tree = malloc(sizeof(BPlusTree));
|
||||||
tree->order = order;
|
tree->order = order;
|
||||||
@@ -143,6 +172,18 @@ void print_bplus_tree(BPlusTree *tree) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *debug_bplus_tree_str(BPlusTree *tree, char *str) {
|
||||||
|
size_t strSize = 32;
|
||||||
|
str = realloc(str, strSize * sizeof(char));
|
||||||
|
memset(str, 0, strSize * sizeof(char));
|
||||||
|
|
||||||
|
snprintf(str, 32, "B+<%ld>", tree->order);
|
||||||
|
|
||||||
|
str = debug_bplus_node_str(tree->root, str, &strSize);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
BPlusNode *bplus_tree_find_leaf(BPlusTree *tree, uint64_t key) {
|
BPlusNode *bplus_tree_find_leaf(BPlusTree *tree, uint64_t key) {
|
||||||
BPlusNode *node = tree->root;
|
BPlusNode *node = tree->root;
|
||||||
|
|
||||||
@@ -232,6 +273,7 @@ bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
|
|||||||
//Move midpoint up and move keys > midpoint to new node
|
//Move midpoint up and move keys > midpoint to new node
|
||||||
k = 0;
|
k = 0;
|
||||||
for (size_t i = midpointIndex + 1; i < node->order; i++) {
|
for (size_t i = midpointIndex + 1; i < node->order; i++) {
|
||||||
|
node->keys[i]->rightPointer->parent = newNode;
|
||||||
newNode->keys[k++] = node->keys[i];
|
newNode->keys[k++] = node->keys[i];
|
||||||
node->keys[i] = NULL;
|
node->keys[i] = NULL;
|
||||||
newNode->keyCount++;
|
newNode->keyCount++;
|
||||||
@@ -241,6 +283,7 @@ bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
|
|||||||
node->keys[midpointIndex] = NULL;
|
node->keys[midpointIndex] = NULL;
|
||||||
node->keyCount--;
|
node->keyCount--;
|
||||||
newNode->leftPointer = ascendingKV->rightPointer;
|
newNode->leftPointer = ascendingKV->rightPointer;
|
||||||
|
newNode->leftPointer->parent = newNode;
|
||||||
ascendingKV->rightPointer = newNode;
|
ascendingKV->rightPointer = newNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,3 +292,70 @@ bool bplus_tree_insert(BPlusTree *tree, uint64_t newKey, void *newValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BPlusKV *bplus_tree_find(BPlusTree *tree, uint64_t key) {
|
||||||
|
BPlusNode *leaf = bplus_tree_find_leaf(tree, key);
|
||||||
|
if (leaf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < leaf->keyCount; i++) {
|
||||||
|
if (leaf->keys[i]->key == key) {
|
||||||
|
return leaf->keys[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BPlusKV *bplus_tree_find_closest(BPlusTree *tree, uint64_t key, BPlusFindComp dir) {
|
||||||
|
//Do regular find if we are only looking for key
|
||||||
|
if (dir == FIND_EQ) {
|
||||||
|
return bplus_tree_find(tree, key);
|
||||||
|
}
|
||||||
|
BPlusNode *leaf = bplus_tree_find_leaf(tree, key);
|
||||||
|
if (leaf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//Scan right until we find a value >= key
|
||||||
|
ssize_t i;
|
||||||
|
do {
|
||||||
|
bool done = false;
|
||||||
|
for (i = 0; i < leaf->keyCount; i++) {
|
||||||
|
if (leaf->keys[i]->key == key && (dir & FIND_EQ) == FIND_EQ) {
|
||||||
|
//Return the value if we are looking for value = key
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
} else if (leaf->keys[i]->key > key) {
|
||||||
|
//Return the value if we are looking for value > key
|
||||||
|
if ((dir & FIND_GT) == FIND_GT) {
|
||||||
|
return leaf->keys[i];
|
||||||
|
} else {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (leaf->rightLeaf == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
leaf = leaf->rightLeaf;
|
||||||
|
} while (leaf != NULL);
|
||||||
|
|
||||||
|
//Didn't find an acceptable value >= key and we are not looking for value < key
|
||||||
|
if ((dir & FIND_LT) == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scan left until we find a value < key
|
||||||
|
do {
|
||||||
|
for (i = leaf->keyCount - 1; i >= 0; i--) {
|
||||||
|
if (leaf->keys[i]->key < key) {
|
||||||
|
return leaf->keys[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf = leaf->leftLeaf;
|
||||||
|
} while (leaf != NULL);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -43,6 +43,8 @@ bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv);
|
|||||||
|
|
||||||
void print_bplus_node(BPlusNode *node, size_t indent);
|
void print_bplus_node(BPlusNode *node, size_t indent);
|
||||||
|
|
||||||
|
char * debug_bplus_node_str(BPlusNode *node, char *str, size_t *strSize);
|
||||||
|
|
||||||
struct BPlusTree_t {
|
struct BPlusTree_t {
|
||||||
size_t order;
|
size_t order;
|
||||||
size_t minFill;
|
size_t minFill;
|
||||||
@@ -56,10 +58,21 @@ BPlusTree *new_bplus_tree(size_t order);
|
|||||||
void free_bplus_tree(BPlusTree *tree);
|
void free_bplus_tree(BPlusTree *tree);
|
||||||
|
|
||||||
void print_bplus_tree(BPlusTree *tree);
|
void print_bplus_tree(BPlusTree *tree);
|
||||||
|
char *debug_bplus_tree_str(BPlusTree *tree, char *str);
|
||||||
|
|
||||||
BPlusNode * bplus_tree_find_leaf(BPlusTree *tree, uint64_t key);
|
BPlusNode * bplus_tree_find_leaf(BPlusTree *tree, uint64_t key);
|
||||||
|
|
||||||
bool bplus_tree_insert(BPlusTree *tree, uint64_t key, void *value);
|
bool bplus_tree_insert(BPlusTree *tree, uint64_t key, void *value);
|
||||||
|
|
||||||
|
BPlusKV * bplus_tree_find(BPlusTree *tree, uint64_t key);
|
||||||
|
|
||||||
|
enum BPlusFindComp_t {
|
||||||
|
FIND_NONE = 0,
|
||||||
|
FIND_LT = 1,
|
||||||
|
FIND_EQ = 2,
|
||||||
|
FIND_GT = 4
|
||||||
|
};
|
||||||
|
typedef enum BPlusFindComp_t BPlusFindComp;
|
||||||
|
BPlusKV * bplus_tree_find_closest(BPlusTree *tree, uint64_t key, BPlusFindComp dir);
|
||||||
|
|
||||||
#endif //SDB_BPLUS_TREE_H
|
#endif //SDB_BPLUS_TREE_H
|
||||||
|
|||||||
13
tests/CMakeLists.txt
Normal file
13
tests/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
|
||||||
|
|
||||||
|
find_package(Check REQUIRED)
|
||||||
|
find_package (Threads REQUIRED)
|
||||||
|
include_directories(${CHECK_INCLUDE_DIRS})
|
||||||
|
link_directories(${CHECK_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
set(TEST_SOURCES
|
||||||
|
check_sdb.c
|
||||||
|
bplus_tree_test.c bplus_tree_test.h)
|
||||||
|
|
||||||
|
add_executable(check_SDB ${TEST_SOURCES})
|
||||||
|
target_link_libraries(check_SDB SDBLib ${CHECK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
76
tests/bplus_tree_test.c
Normal file
76
tests/bplus_tree_test.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// Created by sam on 23/06/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "bplus_tree_test.h"
|
||||||
|
#include "../src/bplus_tree.h"
|
||||||
|
|
||||||
|
START_TEST(insert_keys_4)
|
||||||
|
{
|
||||||
|
|
||||||
|
BPlusTree *tree = new_bplus_tree(4);
|
||||||
|
|
||||||
|
char *buffer = NULL;
|
||||||
|
|
||||||
|
ck_assert_str_eq(debug_bplus_tree_str(tree, buffer), "B+<4>[]");
|
||||||
|
|
||||||
|
bplus_tree_insert(tree, 10, NULL);
|
||||||
|
bplus_tree_insert(tree, 20, NULL);
|
||||||
|
|
||||||
|
ck_assert_str_eq(debug_bplus_tree_str(tree, buffer), "B+<4>[{10*}{20*}]");
|
||||||
|
|
||||||
|
bplus_tree_insert(tree, 30, NULL);
|
||||||
|
bplus_tree_insert(tree, 40, NULL);
|
||||||
|
|
||||||
|
ck_assert_str_eq(debug_bplus_tree_str(tree, buffer), "B+<4>[[{10*}{20*}]{30}[{30*}{40*}]]");
|
||||||
|
|
||||||
|
bplus_tree_insert(tree, 35, NULL);
|
||||||
|
bplus_tree_insert(tree, 50, NULL);
|
||||||
|
ck_assert_str_eq(debug_bplus_tree_str(tree, buffer), "B+<4>[[{10*}{20*}]{30}[{30*}{35*}]{40}[{40*}{50*}]]");
|
||||||
|
|
||||||
|
free_bplus_tree(tree);
|
||||||
|
|
||||||
|
if (buffer != NULL) free(buffer);
|
||||||
|
|
||||||
|
}END_TEST
|
||||||
|
|
||||||
|
START_TEST(find_keys_4)
|
||||||
|
{
|
||||||
|
BPlusTree *tree = new_bplus_tree(4);
|
||||||
|
|
||||||
|
bplus_tree_insert(tree, 10, NULL);
|
||||||
|
bplus_tree_insert(tree, 20, NULL);
|
||||||
|
bplus_tree_insert(tree, 30, NULL);
|
||||||
|
bplus_tree_insert(tree, 40, NULL);
|
||||||
|
|
||||||
|
ck_assert(bplus_tree_find(tree, 10) != NULL);
|
||||||
|
ck_assert(bplus_tree_find(tree, 40) != NULL);
|
||||||
|
|
||||||
|
BPlusKV *kv;
|
||||||
|
kv = bplus_tree_find_closest(tree, 15, FIND_LT | FIND_EQ);
|
||||||
|
ck_assert_ptr_ne(kv, NULL);
|
||||||
|
ck_assert_int_eq(kv->key, 10);
|
||||||
|
|
||||||
|
kv = bplus_tree_find_closest(tree, 30, FIND_LT);
|
||||||
|
ck_assert_ptr_ne(kv, NULL);
|
||||||
|
ck_assert_int_eq(kv->key, 20);
|
||||||
|
|
||||||
|
kv = bplus_tree_find_closest(tree, 30, FIND_GT);
|
||||||
|
ck_assert_ptr_ne(kv, NULL);
|
||||||
|
ck_assert_int_eq(kv->key, 40);
|
||||||
|
|
||||||
|
free_bplus_tree(tree);
|
||||||
|
}END_TEST
|
||||||
|
|
||||||
|
Suite *blus_tree_suite(void) {
|
||||||
|
Suite *s = suite_create("B+ Tree");
|
||||||
|
|
||||||
|
TCase *core = tcase_create("Insert");
|
||||||
|
suite_add_tcase(s, core);
|
||||||
|
|
||||||
|
tcase_add_test(core, insert_keys_4);
|
||||||
|
tcase_add_test(core, find_keys_4);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
12
tests/bplus_tree_test.h
Normal file
12
tests/bplus_tree_test.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by sam on 23/06/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SDB_BPLUS_TREE_TEST_H
|
||||||
|
#define SDB_BPLUS_TREE_TEST_H
|
||||||
|
|
||||||
|
#include <check.h>
|
||||||
|
|
||||||
|
Suite * blus_tree_suite(void);
|
||||||
|
|
||||||
|
#endif //SDB_BPLUS_TREE_TEST_H
|
||||||
21
tests/check_sdb.c
Normal file
21
tests/check_sdb.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by sam on 22/06/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <check.h>
|
||||||
|
#include "bplus_tree_test.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
int number_failed;
|
||||||
|
Suite *s;
|
||||||
|
SRunner *sr;
|
||||||
|
|
||||||
|
s = blus_tree_suite();
|
||||||
|
sr = srunner_create(s);
|
||||||
|
|
||||||
|
srunner_run_all(sr, CK_NORMAL);
|
||||||
|
number_failed = srunner_ntests_failed(sr);
|
||||||
|
srunner_free(sr);
|
||||||
|
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user