diff options
Diffstat (limited to 'storage/tokudb/tests')
-rw-r--r-- | storage/tokudb/tests/Makefile | 53 | ||||
-rw-r--r-- | storage/tokudb/tests/card_1.cc | 169 | ||||
-rw-r--r-- | storage/tokudb/tests/card_etime.cc | 199 | ||||
-rw-r--r-- | storage/tokudb/tests/card_inf.cc | 164 | ||||
-rw-r--r-- | storage/tokudb/tests/card_inf_1.cc | 170 | ||||
-rw-r--r-- | storage/tokudb/tests/card_random_1.cc | 176 | ||||
-rw-r--r-- | storage/tokudb/tests/card_test.cc | 204 | ||||
-rw-r--r-- | storage/tokudb/tests/card_test_alter.cc | 621 | ||||
-rw-r--r-- | storage/tokudb/tests/card_test_key_info.cc | 146 | ||||
-rw-r--r-- | storage/tokudb/tests/fake_mysql.h | 50 | ||||
-rw-r--r-- | storage/tokudb/tests/math_test_int.cc | 272 | ||||
-rw-r--r-- | storage/tokudb/tests/math_test_uint.cc | 187 | ||||
-rw-r--r-- | storage/tokudb/tests/max_test.cc | 47 | ||||
-rw-r--r-- | storage/tokudb/tests/sint_test.cc | 53 | ||||
-rw-r--r-- | storage/tokudb/tests/tokudb_buffer_test.cc | 234 | ||||
-rw-r--r-- | storage/tokudb/tests/uint_test.cc | 54 | ||||
-rw-r--r-- | storage/tokudb/tests/vlq_test.cc | 88 | ||||
-rw-r--r-- | storage/tokudb/tests/vlq_test_uint32.cc | 99 | ||||
-rw-r--r-- | storage/tokudb/tests/vlq_test_uint64.cc | 110 |
19 files changed, 3096 insertions, 0 deletions
diff --git a/storage/tokudb/tests/Makefile b/storage/tokudb/tests/Makefile new file mode 100644 index 00000000..47e2027e --- /dev/null +++ b/storage/tokudb/tests/Makefile @@ -0,0 +1,53 @@ +SRCS = $(wildcard *.cc) +TARGETS = $(patsubst %.cc,%,$(SRCS)) +CHECKS = $(patsubst %,%.check,$(TARGETS)) +CPPFLAGS = -I.. -D__STDC_FORMAT_MACROS +CXXFLAGS = -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow +ifdef USE_OPENMP +CPPFLAGS += -DUSE_OPENMP +CXXFLAGS += -fopenmp +endif + +FRACTALTREE_BASE_DIR = ../ft-index +FRACTALTREE_INSTALL_DIR = $(FRACTALTREE_BASE_DIR)/install.debug +VALGRIND = valgrind -q --leak-check=full --show-reachable=yes --suppressions=$(FRACTALTREE_BASE_DIR)/ft/valgrind.suppressions --soname-synonyms=somalloc=*tokuportability* + +ifeq ($(GCOV),1) +CXXFLAGS += -fprofile-arcs -ftest-coverage +else +CXXFLAGS += -O3 +endif + +all: $(TARGETS) + +clean: + rm -rf $(TARGETS) *.gcov *.gcno *.gcda *.testdir *.dSYM + +%.check: % + LD_LIBRARY_PATH=$(FRACTALTREE_INSTALL_DIR)/lib $(VALGRIND) ./$< + +card.check: $(patsubst %.cc,%.check,$(wildcard card*.cc)) + true + +ifndef USE_OPENMP +# unravel vlq_test_uint64 8 times +vlq_test_uint64_%.check: + LD_LIBRARY_PATH=$(FRACTALTREE_INSTALL_DIR)/lib $(VALGRIND) ./vlq_test_uint64 $(patsubst vlq_test_uint64_%.check,%,$@) 8 +vlq_test_uint64.check: $(foreach i,0 1 2 3 4 5 6 7,vlq_test_uint64_$(i).check) + true +endif + +vlq.check: $(patsubst %.cc,%.check,$(wildcard vlq*.cc)) + true + +max_test.check: max_test + $(VALGRIND) ./$< 1 2 + +check: $(CHECKS) + true + +%: %.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -g -o $@ $< + +card_%: card_%.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -g -o $@ $< -I.. -I$(FRACTALTREE_INSTALL_DIR)/include -L$(FRACTALTREE_INSTALL_DIR)/lib -ltokufractaltree -ltokuportability diff --git a/storage/tokudb/tests/card_1.cc b/storage/tokudb/tests/card_1.cc new file mode 100644 index 00000000..8c6934e0 --- /dev/null +++ b/storage/tokudb/tests/card_1.cc @@ -0,0 +1,169 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// Test cardinality algorithm on a single level unique key + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <memory.h> +#include <assert.h> +#include <errno.h> +#include <db.h> +#if __linux__ +#include <endian.h> +#endif +#include <sys/stat.h> +#include <sys/types.h> +typedef unsigned long long ulonglong; +#include "tokudb_status.h" +#include "tokudb_buffer.h" + +#include "fake_mysql.h" + +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include "tokudb_card.h" + +static uint32_t hton32(uint32_t n) { +#if BYTE_ORDER == LITTLE_ENDIAN + return __builtin_bswap32(n); +#else + return n; +#endif +} + +struct key { + uint32_t k0; +}; // __attribute__((packed)); + +struct val { + uint32_t v0; +}; // __attribute__((packed)); + +// load nrows into the db +static void load_db(DB_ENV *env, DB *db, uint32_t nrows) { + DB_TXN *txn = NULL; + int r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + DB_LOADER *loader = NULL; + uint32_t db_flags[1] = { 0 }; + uint32_t dbt_flags[1] = { 0 }; + uint32_t loader_flags = 0; + r = env->create_loader(env, txn, &loader, db, 1, &db, db_flags, dbt_flags, loader_flags); + assert(r == 0); + + for (uint32_t seq = 0; seq < nrows ; seq++) { + struct key k = { hton32(seq) }; + struct val v = { seq }; + DBT key = { .data = &k, .size = sizeof k }; + DBT val = { .data = &v, .size = sizeof v }; + r = loader->put(loader, &key, &val); + assert(r == 0); + } + + r = loader->close(loader); + assert(r == 0); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +static int analyze_key_compare(DB *db __attribute__((unused)), const DBT *a, const DBT *b, uint level) { + assert(level == 1); + assert(a->size == b->size); + return memcmp(a->data, b->data, a->size); +} + +static void test_card(DB_ENV *env, DB *db, uint64_t expect_card) { + int r; + + DB_TXN *txn = NULL; + r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + uint64_t num_key_parts = 1; + uint64_t rec_per_key[num_key_parts]; + + r = tokudb::analyze_card(db, txn, false, num_key_parts, rec_per_key, analyze_key_compare, NULL, NULL); + assert(r == 0); + + assert(rec_per_key[0] == expect_card); + + r = tokudb::analyze_card(db, txn, true, num_key_parts, rec_per_key, analyze_key_compare, NULL, NULL); + assert(r == 0); + + assert(rec_per_key[0] == expect_card); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +int main(int argc, char * const argv[]) { + uint32_t nrows = 1000000; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--nrows") == 0 && i+1 < argc) { + nrows = atoi(argv[++i]); + continue; + } + } + + int r; + r = system("rm -rf " __FILE__ ".testdir"); + assert(r == 0); + r = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert(r == 0); + + r = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert(r == 0); + + r = db->open(db, NULL, "test.db", 0, DB_BTREE, DB_CREATE + DB_AUTO_COMMIT, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // load the db + load_db(env, db, nrows); + + // test cardinality + test_card(env, db, 1); + + r = db->close(db, 0); + assert(r == 0); + + r = env->close(env, 0); + assert(r == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_etime.cc b/storage/tokudb/tests/card_etime.cc new file mode 100644 index 00000000..11cff5cb --- /dev/null +++ b/storage/tokudb/tests/card_etime.cc @@ -0,0 +1,199 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// Verify that analyze can be terminated when its executing time limit is reached + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <inttypes.h> +#include <memory.h> +#include <assert.h> +#include <errno.h> +#include <db.h> +#if __linux__ +#include <endian.h> +#endif +#include <sys/stat.h> +#include <sys/types.h> +typedef unsigned long long ulonglong; +#include "tokudb_status.h" +#include "tokudb_buffer.h" +#include "fake_mysql.h" +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include "tokudb_card.h" + +static int verbose = 0; + +static uint32_t hton32(uint32_t n) { +#if BYTE_ORDER == LITTLE_ENDIAN + return __builtin_bswap32(n); +#else + return n; +#endif +} + +struct key { + uint32_t k0; +}; // __attribute__((packed)); + +struct val { + uint32_t v0; +}; // __attribute__((packed)); + +// load nrows into the db +static void load_db(DB_ENV *env, DB *db, uint32_t nrows) { + DB_TXN *txn = NULL; + int r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + DB_LOADER *loader = NULL; + uint32_t db_flags[1] = { 0 }; + uint32_t dbt_flags[1] = { 0 }; + uint32_t loader_flags = 0; + r = env->create_loader(env, txn, &loader, db, 1, &db, db_flags, dbt_flags, loader_flags); + assert(r == 0); + + for (uint32_t seq = 0; seq < nrows ; seq++) { + struct key k = { hton32(seq) }; + struct val v = { seq }; + DBT key = { .data = &k, .size = sizeof k }; + DBT val = { .data = &v, .size = sizeof v }; + r = loader->put(loader, &key, &val); + assert(r == 0); + } + + r = loader->close(loader); + assert(r == 0); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +static int analyze_key_compare(DB *db __attribute__((unused)), const DBT *a, const DBT *b, uint level) { + assert(level == 1); + assert(a->size == b->size); + return memcmp(a->data, b->data, a->size); +} + +struct analyze_extra { + uint64_t now; + uint64_t limit; +}; + +static int analyze_progress(void *extra, uint64_t rows) { + assert(rows > 0); + struct analyze_extra *e = (struct analyze_extra *) extra; + e->now++; + int r; + if (e->limit > 0 && e->now >= e->limit) + r = ETIME; + else + r = 0; + if (verbose) + printf("%s %"PRIu64" %"PRIu64" r=%d\n", __FUNCTION__, e->now, e->limit, r); + return r; +} + +static void test_card(DB_ENV *env, DB *db, uint64_t expect_card, uint64_t limit) { + int r; + + DB_TXN *txn = NULL; + r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + uint64_t num_key_parts = 1; + uint64_t rec_per_key[num_key_parts]; + for (uint64_t i = 0; i < num_key_parts; i++) + rec_per_key[i] = 0; + + struct analyze_extra analyze_extra = { 0, limit }; + r = tokudb::analyze_card(db, txn, false, num_key_parts, rec_per_key, analyze_key_compare, analyze_progress, &analyze_extra); + if (limit == 0) { + assert(r == 0); + } else { + assert(r == ETIME); + assert(analyze_extra.now == analyze_extra.limit); + } + + assert(rec_per_key[0] == expect_card); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +int main(int argc, char * const argv[]) { + uint32_t nrows = 1000000; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) { + verbose++; + continue; + } + if (strcmp(argv[i], "--nrows") == 0 && i+1 < argc) { + nrows = atoi(argv[++i]); + continue; + } + } + + int r; + r = system("rm -rf " __FILE__ ".testdir"); + assert(r == 0); + r = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert(r == 0); + + r = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert(r == 0); + + r = db->open(db, NULL, "test.db", 0, DB_BTREE, DB_CREATE + DB_AUTO_COMMIT, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // load the db + load_db(env, db, nrows); + + // test cardinality + test_card(env, db, 1, 0); + test_card(env, db, 1, 1); + test_card(env, db, 1, 10); + test_card(env, db, 1, 100); + + r = db->close(db, 0); + assert(r == 0); + + r = env->close(env, 0); + assert(r == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_inf.cc b/storage/tokudb/tests/card_inf.cc new file mode 100644 index 00000000..fda51f9a --- /dev/null +++ b/storage/tokudb/tests/card_inf.cc @@ -0,0 +1,164 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// Test cardinality algorithm on a single level identical key + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <memory.h> +#include <assert.h> +#include <errno.h> +#include <db.h> +#if __linux__ +#include <endian.h> +#endif +#include <sys/stat.h> +typedef unsigned long long ulonglong; +#include "tokudb_status.h" +#include "tokudb_buffer.h" +#include "fake_mysql.h" +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include "tokudb_card.h" + +static uint32_t hton32(uint32_t n) { +#if BYTE_ORDER == LITTLE_ENDIAN + return __builtin_bswap32(n); +#else + return n; +#endif +} + +struct key { + uint32_t k0; + uint32_t seq; +}; // __attribute__((packed)); + +struct val { + uint32_t v0; +}; // __attribute__((packed)); + +// load nrows into the db +static void load_db(DB_ENV *env, DB *db, uint32_t nrows) { + DB_TXN *txn = NULL; + int r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + DB_LOADER *loader = NULL; + uint32_t db_flags[1] = { 0 }; + uint32_t dbt_flags[1] = { 0 }; + uint32_t loader_flags = 0; + r = env->create_loader(env, txn, &loader, db, 1, &db, db_flags, dbt_flags, loader_flags); + assert(r == 0); + + for (uint32_t seq = 0; seq < nrows ; seq++) { + struct key k = { 0, hton32(seq) }; + struct val v = { seq }; + DBT key = { .data = &k, .size = sizeof k }; + DBT val = { .data = &v, .size = sizeof v }; + r = loader->put(loader, &key, &val); + assert(r == 0); + } + + r = loader->close(loader); + assert(r == 0); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +// only compare the first level of the key +static int analyze_key_compare(DB *db __attribute__((unused)), const DBT *a, const DBT *b, uint level) { + assert(level == 1); + assert(a->size == b->size); + assert(a->size == sizeof (struct key)); + return memcmp(a->data, b->data, sizeof (uint32_t)); +} + +static void test_card(DB_ENV *env, DB *db, uint64_t expect_card) { + int r; + + DB_TXN *txn = NULL; + r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + uint64_t num_key_parts = 1; + uint64_t rec_per_key[num_key_parts]; + + r = tokudb::analyze_card(db, txn, false, num_key_parts, rec_per_key, analyze_key_compare, NULL, NULL); + assert(r == 0); + + assert(rec_per_key[0] == expect_card); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +int main(int argc, char * const argv[]) { + uint64_t nrows = 1000000; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--nrows") == 0 && i+1 < argc) { + nrows = atoll(argv[++i]); + continue; + } + } + + int r; + r = system("rm -rf " __FILE__ ".testdir"); + assert(r == 0); + r = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert(r == 0); + + r = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert(r == 0); + + r = db->open(db, NULL, "test.db", 0, DB_BTREE, DB_CREATE + DB_AUTO_COMMIT, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // load the db + load_db(env, db, nrows); + + // test cardinality + test_card(env, db, nrows); + + r = db->close(db, 0); + assert(r == 0); + + r = env->close(env, 0); + assert(r == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_inf_1.cc b/storage/tokudb/tests/card_inf_1.cc new file mode 100644 index 00000000..ca35b260 --- /dev/null +++ b/storage/tokudb/tests/card_inf_1.cc @@ -0,0 +1,170 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// Test cardinality algorithm on a 2 level key where the first level is identical and the second level is unique + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <memory.h> +#include <assert.h> +#include <errno.h> +#include <db.h> +#if __linux__ +#include <endian.h> +#endif +#include <sys/stat.h> +typedef unsigned long long ulonglong; +#include "tokudb_status.h" +#include "tokudb_buffer.h" +#include "fake_mysql.h" +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include "tokudb_card.h" + +static uint32_t hton32(uint32_t n) { +#if BYTE_ORDER == LITTLE_ENDIAN + return __builtin_bswap32(n); +#else + return n; +#endif +} + +struct key { + uint32_t k0; + uint32_t seq; +}; // __attribute__((packed)); + +struct val { + uint32_t v0; +}; // __attribute__((packed)); + +// load nrows into the db +static void load_db(DB_ENV *env, DB *db, uint32_t nrows) { + DB_TXN *txn = NULL; + int r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + DB_LOADER *loader = NULL; + uint32_t db_flags[1] = { 0 }; + uint32_t dbt_flags[1] = { 0 }; + uint32_t loader_flags = 0; + r = env->create_loader(env, txn, &loader, db, 1, &db, db_flags, dbt_flags, loader_flags); + assert(r == 0); + + for (uint32_t seq = 0; seq < nrows ; seq++) { + struct key k = { 0, hton32(seq) }; + struct val v = { seq }; + DBT key = { .data = &k, .size = sizeof k }; + DBT val = { .data = &v, .size = sizeof v }; + r = loader->put(loader, &key, &val); + assert(r == 0); + } + + r = loader->close(loader); + assert(r == 0); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +static int analyze_key_compare(DB *db __attribute__((unused)), const DBT *a, const DBT *b, uint level) { + assert(a->size == b->size); + switch (level) { + default: + assert(0); + case 1: + return memcmp(a->data, b->data, sizeof (uint32_t)); + case 2: + assert(a->size == sizeof (struct key)); + return memcmp(a->data, b->data, sizeof (struct key)); + } +} + +static void test_card(DB_ENV *env, DB *db, uint64_t expect[]) { + int r; + + DB_TXN *txn = NULL; + r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + uint64_t num_key_parts = 2; + uint64_t rec_per_key[num_key_parts]; + + r = tokudb::analyze_card(db, txn, false, num_key_parts, rec_per_key, analyze_key_compare, NULL, NULL); + assert(r == 0); + + assert(rec_per_key[0] == expect[0]); + assert(rec_per_key[1] == expect[1]); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +int main(int argc, char * const argv[]) { + uint64_t nrows = 1000000; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--nrows") == 0 && i+1 < argc) { + nrows = atoll(argv[++i]); + continue; + } + } + + int r; + r = system("rm -rf " __FILE__ ".testdir"); + assert(r == 0); + r = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert(r == 0); + + r = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert(r == 0); + + r = db->open(db, NULL, "test.db", 0, DB_BTREE, DB_CREATE + DB_AUTO_COMMIT, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // load the db + load_db(env, db, nrows); + + uint64_t expect[2] = { nrows, 1 }; + test_card(env, db, expect); + + r = db->close(db, 0); + assert(r == 0); + + r = env->close(env, 0); + assert(r == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_random_1.cc b/storage/tokudb/tests/card_random_1.cc new file mode 100644 index 00000000..a7603ab6 --- /dev/null +++ b/storage/tokudb/tests/card_random_1.cc @@ -0,0 +1,176 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// Test cardinality algorithm on a 2 level key where the first level is random in a space of size maxrand +// and the second level is unique. + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <memory.h> +#include <assert.h> +#include <errno.h> +#include <db.h> +#if __linux__ +#include <endian.h> +#endif +#include <sys/stat.h> +typedef unsigned long long ulonglong; +#include "tokudb_status.h" +#include "tokudb_buffer.h" +#include "fake_mysql.h" +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include "tokudb_card.h" + +static uint32_t hton32(uint32_t n) { +#if BYTE_ORDER == LITTLE_ENDIAN + return __builtin_bswap32(n); +#else + return n; +#endif +} + +struct key { + uint32_t r; + uint32_t seq; +}; // __attribute__((packed)); + +struct val { + uint32_t v0; +}; // __attribute__((packed)); + +// load nrows into the db +static void load_db(DB_ENV *env, DB *db, uint32_t nrows, uint32_t maxrand) { + DB_TXN *txn = NULL; + int r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + DB_LOADER *loader = NULL; + uint32_t db_flags[1] = { 0 }; + uint32_t dbt_flags[1] = { 0 }; + uint32_t loader_flags = 0; + r = env->create_loader(env, txn, &loader, db, 1, &db, db_flags, dbt_flags, loader_flags); + assert(r == 0); + + for (uint32_t seq = 0; seq < nrows ; seq++) { + struct key k = { hton32(random() % maxrand), hton32(seq) }; + struct val v = { seq }; + DBT key = { .data = &k, .size = sizeof k }; + DBT val = { .data = &v, .size = sizeof v }; + r = loader->put(loader, &key, &val); + assert(r == 0); + } + + r = loader->close(loader); + assert(r == 0); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +static int analyze_key_compare(DB *db __attribute__((unused)), const DBT *a, const DBT *b, uint level) { + assert(a->size == b->size); + switch (level) { + default: + assert(0); + case 1: + return memcmp(a->data, b->data, sizeof (uint32_t)); + case 2: + assert(a->size == sizeof (struct key)); + return memcmp(a->data, b->data, sizeof (struct key)); + } +} + +static void test_card(DB_ENV *env, DB *db, uint64_t expect[]) { + int r; + + DB_TXN *txn = NULL; + r = env->txn_begin(env, NULL, &txn, 0); + assert(r == 0); + + uint64_t num_key_parts = 2; + uint64_t rec_per_key[num_key_parts]; + + r = tokudb::analyze_card(db, txn, false, num_key_parts, rec_per_key, analyze_key_compare, NULL, NULL); + assert(r == 0); + + assert(rec_per_key[0] == expect[0]); + assert(rec_per_key[1] == expect[1]); + + r = txn->commit(txn, 0); + assert(r == 0); +} + +int main(int argc, char * const argv[]) { + uint64_t nrows = 1000000; + uint32_t maxrand = 10; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--nrows") == 0 && i+1 < argc) { + nrows = atoll(argv[++i]); + continue; + } + if (strcmp(argv[i], "--maxrand") == 0 && i+1 < argc) { + maxrand = atoi(argv[++i]); + continue; + } + } + + int r; + r = system("rm -rf " __FILE__ ".testdir"); + assert(r == 0); + r = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert(r == 0); + + r = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert(r == 0); + + r = db->open(db, NULL, "test.db", 0, DB_BTREE, DB_CREATE + DB_AUTO_COMMIT, S_IRWXU+S_IRWXG+S_IRWXO); + assert(r == 0); + + // load the db + load_db(env, db, nrows, maxrand); + + uint64_t expect[2] = { nrows/maxrand, 1 }; + test_card(env, db, expect); + + r = db->close(db, 0); + assert(r == 0); + + r = env->close(env, 0); + assert(r == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_test.cc b/storage/tokudb/tests/card_test.cc new file mode 100644 index 00000000..b34a94cf --- /dev/null +++ b/storage/tokudb/tests/card_test.cc @@ -0,0 +1,204 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// test tokudb cardinality in status dictionary +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <memory.h> +#include <errno.h> +#include <sys/stat.h> +#include <db.h> +typedef unsigned long long ulonglong; +#include <tokudb_status.h> +#include <tokudb_buffer.h> + +#include "fake_mysql.h" + +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include <tokudb_card.h> + +// verify that we can create and close a status dictionary +static void test_create(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status.db", txn); + assert(error == 0); + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +// verify that no card row in status works +static void test_no_card(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::open_status(env, &status_db, "status.db", txn); + assert(error == 0); + + error = tokudb::get_card_from_status(status_db, txn, 0, NULL); + assert(error == DB_NOTFOUND); + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +// verify that a card row with 0 array elements works +static void test_0(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::open_status(env, &status_db, "status.db", txn); + assert(error == 0); + + tokudb::set_card_in_status(status_db, txn, 0, NULL); + + error = tokudb::get_card_from_status(status_db, txn, 0, NULL); + assert(error == 0); + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +// verify that writing and reading card info works for several sized card arrays +static void test_10(DB_ENV *env) { + int error; + + for (uint64_t i = 0; i < 20; i++) { + + uint64_t rec_per_key[i]; + for (uint64_t j = 0; j < i; j++) + rec_per_key[j] = j == 0 ? 10+i : 10 * rec_per_key[j-1]; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::open_status(env, &status_db, "status.db", txn); + assert(error == 0); + + tokudb::set_card_in_status(status_db, txn, i, rec_per_key); + + uint64_t stored_rec_per_key[i]; + error = tokudb::get_card_from_status(status_db, txn, i, stored_rec_per_key); + assert(error == 0); + + for (uint64_t j = 0; j < i; j++) + assert(rec_per_key[j] == stored_rec_per_key[j]); + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); + + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + error = tokudb::open_status(env, &status_db, "status.db", txn); + assert(error == 0); + + tokudb::set_card_in_status(status_db, txn, i, rec_per_key); + + error = tokudb::get_card_from_status(status_db, txn, i, stored_rec_per_key); + assert(error == 0); + + for (uint64_t j = 0; j < i; j++) + assert(rec_per_key[j] == stored_rec_per_key[j]); + + error = txn->commit(txn, 0); + assert(error == 0); + + // test delete card + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + error = tokudb::delete_card_from_status(status_db, txn); + assert(error == 0); + + error = tokudb::get_card_from_status(status_db, txn, 0, NULL); + assert(error == DB_NOTFOUND); + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); + } +} + +int main() { + int error; + + error = system("rm -rf " __FILE__ ".testdir"); + assert(error == 0); + + error = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(error == 0); + + DB_ENV *env = NULL; + error = db_env_create(&env, 0); + assert(error == 0); + + error = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(error == 0); + + test_create(env); + test_no_card(env); + test_0(env); + test_10(env); + + error = env->close(env, 0); + assert(error == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_test_alter.cc b/storage/tokudb/tests/card_test_alter.cc new file mode 100644 index 00000000..236dfbf1 --- /dev/null +++ b/storage/tokudb/tests/card_test_alter.cc @@ -0,0 +1,621 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// test tokudb cardinality in status dictionary +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <memory.h> +#include <errno.h> +#include <sys/stat.h> +#include <db.h> +typedef unsigned long long ulonglong; +#include <tokudb_status.h> +#include <tokudb_buffer.h> + +#include "fake_mysql.h" + +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include <tokudb_card.h> + +static void test_no_keys(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_no_keys", txn); + assert(error == 0); + + const uint keys = 0; + const uint key_parts = 0; + TABLE_SHARE s = { MAX_KEY, keys, key_parts, NULL }; + + error = tokudb::alter_card(status_db, txn, &s, &s); + assert(error == 0); + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_keys(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_keys", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 3; + const uint ta_key_parts = 1; + const int ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 1000, 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &ta); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[ta_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, ta_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < ta_rec_per_keys; i++) { + assert(current_rec_per_key[i] == ta_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_drop_0(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_drop_0", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 3; + const uint ta_key_parts = 1; + const uint ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 1000, 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 2; + const uint tb_key_parts = 1; + const int tb_rec_per_keys = tb_keys * tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 2000, 3000, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" }, + { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_drop_1(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_drop_1", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 3; + const uint ta_key_parts = 1; + const uint ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 1000, 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 2; + const uint tb_key_parts = 1; + const int tb_rec_per_keys = tb_keys * tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 1000, 3000, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" }, + { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_drop_2(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_drop_2", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 3; + const uint ta_key_parts = 1; + const uint ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 1000, 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_a" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[2], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 2; + const uint tb_key_parts = 1; + const int tb_rec_per_keys = tb_keys * tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 1000, 2000, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" }, + { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_b" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_drop_1_multiple_parts(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_drop_1_multiple_parts", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 3; + const uint ta_key_parts = 1+2+3; + const uint ta_rec_per_keys = ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 1000, 2000, 2001, 3000, 3001, 3002, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, 1, &ta_rec_per_key[0], (char *) "key_a" }, + { 0, 2, &ta_rec_per_key[0+1], (char *) "key_b" }, + { 0, 3, &ta_rec_per_key[0+1+2], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 2; + const uint tb_key_parts = 1+3; + const int tb_rec_per_keys = tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 1000, 3000, 3001, 3002, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, 1, &tb_rec_per_key[0], (char *) "key_a" }, + { 0, 3, &tb_rec_per_key[0+1], (char *) "key_c" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_add_0(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_add_0", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 2; + const uint ta_key_parts = 1; + const uint ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 3; + const uint tb_key_parts = 1; + const int tb_rec_per_keys = tb_keys * tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 0 /*not computed*/, 2000, 3000, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_a" }, + { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_b" }, + { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_c" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_add_1(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_add_1", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 2; + const uint ta_key_parts = 1; + const uint ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 3; + const uint tb_key_parts = 1; + const int tb_rec_per_keys = tb_keys * tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 2000, 0 /*not computed*/, 3000, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" }, + { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_a" }, + { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_c" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_add_2(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_add_2", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 2; + const uint ta_key_parts = 1; + const uint ta_rec_per_keys = ta_keys * ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 2000, 3000, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, ta_key_parts, &ta_rec_per_key[0], (char *) "key_b" }, + { 0, ta_key_parts, &ta_rec_per_key[1], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 3; + const uint tb_key_parts = 1; + const int tb_rec_per_keys = tb_keys * tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 2000, 3000, 0 /*not computed*/, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, tb_key_parts, &tb_rec_per_key[0], (char *) "key_b" }, + { 0, tb_key_parts, &tb_rec_per_key[1], (char *) "key_c" }, + { 0, tb_key_parts, &tb_rec_per_key[2], (char *) "key_a" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +static void test_add_0_multiple_parts(DB_ENV *env) { + int error; + + DB_TXN *txn = NULL; + error = env->txn_begin(env, NULL, &txn, 0); + assert(error == 0); + + DB *status_db = NULL; + error = tokudb::create_status(env, &status_db, "status_add_0_multiple_parts", txn); + assert(error == 0); + + // define tables + const uint ta_keys = 2; + const uint ta_key_parts = 3+4; + const uint ta_rec_per_keys = ta_key_parts; + uint64_t ta_rec_per_key[ta_rec_per_keys] = { + 2000, 2001, 2002, 3000, 3001, 3002, 3003, + }; + KEY_INFO ta_key_info[ta_rec_per_keys] = { + { 0, 3, &ta_rec_per_key[0], (char *) "key_b" }, + { 0, 4, &ta_rec_per_key[3], (char *) "key_c" }, + }; + TABLE_SHARE ta = { MAX_KEY, ta_keys, ta_key_parts, ta_key_info }; + + const uint tb_keys = 3; + const uint tb_key_parts = 2+3+4; + const int tb_rec_per_keys = tb_key_parts; + uint64_t tb_rec_per_key[tb_rec_per_keys] = { + 0, 0 /*not computed*/, 2000, 2001, 2002, 3000, 3001, 3002, 3003, + }; + KEY_INFO tb_key_info[tb_rec_per_keys] = { + { 0, 2, &tb_rec_per_key[0], (char *) "key_a" }, + { 0, 3, &tb_rec_per_key[0+2], (char *) "key_b" }, + { 0, 4, &tb_rec_per_key[0+2+3], (char *) "key_c" }, + }; + TABLE_SHARE tb = { MAX_KEY, tb_keys, tb_key_parts, tb_key_info }; + + // set initial cardinality + error = tokudb::set_card_in_status(status_db, txn, ta_rec_per_keys, ta_rec_per_key); + assert(error == 0); + + error = tokudb::alter_card(status_db, txn, &ta, &tb); + assert(error == 0); + + // verify + uint64_t current_rec_per_key[tb_rec_per_keys]; + error = tokudb::get_card_from_status(status_db, txn, tb_rec_per_keys, current_rec_per_key); + assert(error == 0); + for (uint i = 0; i < tb_rec_per_keys; i++) { + assert(current_rec_per_key[i] == tb_rec_per_key[i]); + } + + error = txn->commit(txn, 0); + assert(error == 0); + + error = tokudb::close_status(&status_db); + assert(error == 0); +} + +int main() { + int error; + + error = system("rm -rf " __FILE__ ".testdir"); + assert(error == 0); + + error = mkdir(__FILE__ ".testdir", S_IRWXU+S_IRWXG+S_IRWXO); + assert(error == 0); + + DB_ENV *env = NULL; + error = db_env_create(&env, 0); + assert(error == 0); + + error = env->open(env, __FILE__ ".testdir", DB_INIT_MPOOL + DB_INIT_LOG + DB_INIT_LOCK + DB_INIT_TXN + DB_PRIVATE + DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); + assert(error == 0); + + test_no_keys(env); + test_keys(env); + test_drop_0(env); + test_drop_1(env); + test_drop_2(env); + test_drop_1_multiple_parts(env); + test_add_0(env); + test_add_1(env); + test_add_2(env); + test_add_0_multiple_parts(env); + + error = env->close(env, 0); + assert(error == 0); + + return 0; +} diff --git a/storage/tokudb/tests/card_test_key_info.cc b/storage/tokudb/tests/card_test_key_info.cc new file mode 100644 index 00000000..97748def --- /dev/null +++ b/storage/tokudb/tests/card_test_key_info.cc @@ -0,0 +1,146 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// test tokudb cardinality in status dictionary +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <memory.h> +#include <errno.h> +#include <sys/stat.h> +#include <db.h> +typedef unsigned long long ulonglong; +#include <tokudb_status.h> +#include <tokudb_buffer.h> + +#include "fake_mysql.h" + +#if __APPLE__ +typedef unsigned long ulong; +#endif +#include <tokudb_card.h> + +static void test_no_keys() { + TABLE_SHARE s = { 0, 0, 0, NULL }; + TABLE t = { &s, NULL }; + assert(tokudb::compute_total_key_parts(&s) == 0); + tokudb::set_card_in_key_info(&t, 0, NULL); +} + +static void test_simple_pk() { + const uint keys = 1; + const uint key_parts = 1; + uint64_t pk_rec_per_key[keys] = { 0 }; + KEY_INFO pk = { 0, key_parts, pk_rec_per_key, (char *) "PRIMARY" }; + TABLE_SHARE s = { 0, keys, key_parts, &pk }; + TABLE t = { &s, &pk }; + assert(tokudb::compute_total_key_parts(&s) == key_parts); + uint64_t computed_rec_per_key[keys] = { 2 }; + tokudb::set_card_in_key_info(&t, keys, computed_rec_per_key); + assert(t.key_info[0].rec_per_key[0] == 1); +} + +static void test_pk_2() { + const uint keys = 1; + const uint key_parts = 2; + uint64_t pk_rec_per_key[keys * key_parts] = { 0 }; + KEY_INFO pk = { 0, key_parts, pk_rec_per_key, (char *) "PRIMARY" }; + TABLE_SHARE s = { 0, keys, key_parts, &pk }; + TABLE t = { &s, &pk }; + assert(tokudb::compute_total_key_parts(&s) == key_parts); + uint64_t computed_rec_per_key[keys * key_parts] = { 2, 3 }; + tokudb::set_card_in_key_info(&t, keys * key_parts, computed_rec_per_key); + assert(t.key_info[0].rec_per_key[0] == 2); + assert(t.key_info[0].rec_per_key[1] == 1); +} + +static void test_simple_sk() { + const uint keys = 1; + const uint key_parts = 1; + uint64_t sk_rec_per_key[keys] = { 0 }; + KEY_INFO sk = { 0, keys, sk_rec_per_key, (char *) "KEY" }; + TABLE_SHARE s = { MAX_KEY, keys, key_parts, &sk }; + TABLE t = { &s, &sk }; + assert(tokudb::compute_total_key_parts(&s) == 1); + uint64_t computed_rec_per_key[keys] = { 2 }; + tokudb::set_card_in_key_info(&t, keys, computed_rec_per_key); + assert(t.key_info[0].rec_per_key[0] == 2); +} + +static void test_simple_unique_sk() { + const uint keys = 1; + uint64_t sk_rec_per_key[keys] = { 0 }; + KEY_INFO sk = { HA_NOSAME, keys, sk_rec_per_key, (char *) "KEY" }; + TABLE_SHARE s = { MAX_KEY, keys, keys, &sk }; + TABLE t = { &s, &sk }; + assert(tokudb::compute_total_key_parts(&s) == 1); + uint64_t computed_rec_per_key[keys] = { 2 }; + tokudb::set_card_in_key_info(&t, keys, computed_rec_per_key); + assert(t.key_info[0].rec_per_key[0] == 1); +} + +static void test_simple_pk_sk() { + const uint keys = 2; + uint64_t rec_per_key[keys] = { 0 }; + KEY_INFO key_info[keys] = { + { 0, 1, &rec_per_key[0], (char *) "PRIMARY" }, + { 0, 1, &rec_per_key[1], (char *) "KEY" }, + }; + TABLE_SHARE s = { 0, keys, keys, key_info }; + TABLE t = { &s, key_info }; + assert(tokudb::compute_total_key_parts(&s) == 2); + uint64_t computed_rec_per_key[keys] = { 100, 200 }; + tokudb::set_card_in_key_info(&t, keys, computed_rec_per_key); + assert(t.key_info[0].rec_per_key[0] == 1); + assert(t.key_info[1].rec_per_key[0] == 200); +} + +static void test_simple_sk_pk() { + const uint keys = 2; + uint64_t rec_per_key[keys] = { 0 }; + KEY_INFO key_info[keys] = { + { 0, 1, &rec_per_key[0], (char *) "KEY" }, + { 0, 1, &rec_per_key[1], (char *) "PRIMARY" }, + }; + TABLE_SHARE s = { 1, keys, keys, key_info }; + TABLE t = { &s, key_info }; + assert(tokudb::compute_total_key_parts(&s) == 2); + uint64_t computed_rec_per_key[keys] = { 100, 200 }; + tokudb::set_card_in_key_info(&t, keys, computed_rec_per_key); + assert(t.key_info[0].rec_per_key[0] == 100); + assert(t.key_info[1].rec_per_key[0] == 1); +} + +int main() { + test_no_keys(); + test_simple_pk(); + test_pk_2(); + test_simple_sk(); + test_simple_unique_sk(); + test_simple_pk_sk(); + test_simple_sk_pk(); + return 0; +} diff --git a/storage/tokudb/tests/fake_mysql.h b/storage/tokudb/tests/fake_mysql.h new file mode 100644 index 00000000..f6a200d2 --- /dev/null +++ b/storage/tokudb/tests/fake_mysql.h @@ -0,0 +1,50 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions +class KEY_INFO { +public: + uint flags; + uint key_parts; + uint64_t *rec_per_key; + char *name; +}; +#define HA_NOSAME 1 +class TABLE_SHARE { +public: + uint primary_key; + uint keys, key_parts; + KEY_INFO *key_info; +}; +class TABLE { +public: + TABLE_SHARE *s; + KEY_INFO *key_info; +}; +uint get_key_parts(KEY_INFO *key_info) { + assert(key_info); + return key_info->key_parts; +} +#define MAX_KEY (1U << 30) diff --git a/storage/tokudb/tests/math_test_int.cc b/storage/tokudb/tests/math_test_int.cc new file mode 100644 index 00000000..3313bdf5 --- /dev/null +++ b/storage/tokudb/tests/math_test_int.cc @@ -0,0 +1,272 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <assert.h> +#include <sys/types.h> +#include <tokudb_math.h> +using namespace tokudb; + +static int64_t sign_extend(uint length_bits, int64_t n) { + return n | ~((1ULL<<(length_bits-1))-1); +} + +static void test_int_range(uint length_bits) { + assert(int_high_endpoint(length_bits) == (int64_t)((1ULL<<(length_bits-1))-1)); + assert(int_low_endpoint(length_bits) == sign_extend(length_bits, 1ULL<<(length_bits-1))); +} + +static void test_int8() { + printf("%s\n", __FUNCTION__); + test_int_range(8); + int64_t max = (1LL << 7); + for (int64_t x = -max; x <= max-1; x++) { + for (int64_t y = -max; y <= max-1; y++) { + bool over; + int64_t n, m; + n = int_add(x, y, 8, &over); + m = x + y; + if (m > max-1) + assert(over); + else if (m < -max) + assert(over); + else { + assert(!over); + assert(n == m); + } + n = int_sub(x, y, 8, &over); + m = x - y; + if (m > max-1) + assert(over); + else if (m < -max) + assert(over); + else { + assert(!over); + asset(n == m); + } + } + } +} + +static void test_int16() { + printf("%s\n", __FUNCTION__); + test_int_range(16); + int64_t max = (1LL << 15); + for (int64_t x = -max; x <= max-1; x++) { + for (int64_t y = -max; y <= max-1; y++) { + bool over; + int64_t n, m; + n = int_add(x, y, 16, &over); + m = x + y; + if (m > max-1) + assert(over); + else if (m < -max) + assert(over); + else { + assert(!over); + assert(n == m); + } + n = int_sub(x, y, 16, &over); + m = x - y; + if (m > max-1) + assert(over); + else if (m < -max) + assert(over); + else { + assert(!over); + assert(n == m); + } + } + } +} + +static void test_int24() { + printf("%s\n", __FUNCTION__); + test_int_range(24); + int64_t s; + bool over; + + s = int_add(1, (1ULL<<23)-1, 24, &over); assert(over); + s = int_add((1ULL<<23)-1, 1, 24, &over); assert(over); + s = int_sub(-1, (1ULL<<23), 24, &over); + assert(!over); + assert(s == (1ULL<<23)-1); + s = int_sub((1ULL<<23), 1, 24, &over); assert(over); + + s = int_add(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = int_sub(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = int_add(0, -1, 24, &over); + assert(!over); + assert(s == -1); + s = int_sub(0, 1, 24, &over); + assert(!over); + assert(s == -1); + s = int_add(0, (1ULL<<23), 24, &over); + assert(!over); + assert((s & ((1ULL<<24)-1)) == (1ULL<<23)); + s = int_sub(0, (1ULL<<23)-1, 24, &over); + assert(!over); + assert((s & ((1ULL<<24)-1)) == (1ULL<<23)+1); + + s = int_add(-1, 0, 24, &over); + assert(!over); + assert(s == -1); + s = int_add(-1, 1, 24, &over); + assert(!over); + assert(s == 0); + s = int_sub(-1, -1, 24, &over); + assert(!over); + assert(s == 0); + s = int_sub(-1, (1ULL<<23)-1, 24, &over); + assert(!over); + assert((s & ((1ULL<<24)-1)) == (1ULL<<23)); +} + +static void test_int32() { + printf("%s\n", __FUNCTION__); + test_int_range(32); + int64_t s; + bool over; + + s = int_add(1, (1ULL<<31)-1, 32, &over); assert(over); + s = int_add((1ULL<<31)-1, 1, 32, &over); assert(over); + s = int_sub(-1, (1ULL<<31), 32, &over); + assert(s == (1ULL<<31)-1); + assert(!over); + s = int_sub((1ULL<<31), 1, 32, &over); assert(over); + + s = int_add(0, 0, 32, &over); + assert(s == 0); + assert(!over); + s = int_sub(0, 0, 32, &over); + assert(s == 0); + assert(!over); + s = int_add(0, -1, 32, &over); + assert(s == -1); + assert(!over); + s = int_sub(0, 1, 32, &over); + assert(s == -1); + assert(!over); + s = int_add(0, (1ULL<<31), 32, &over); + assert((s & ((1ULL<<32)-1)) == (1ULL<<31)); + assert(!over); + s = int_sub(0, (1ULL<<31)-1, 32, &over); + assert((s & ((1ULL<<32)-1)) == (1ULL<<31)+1); + assert(!over); + + s = int_add(-1, 0, 32, &over); + assert(s == -1); + assert(!over); + s = int_add(-1, 1, 32, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, -1, 32, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, (1ULL<<31)-1, 32, &over); + assert((s & ((1ULL<<32)-1)) == (1ULL<<31)); + assert(!over); +} + +static void test_int64() { + printf("%s\n", __FUNCTION__); + test_int_range(64); + int64_t s; + bool over; + + s = int_add(1, (1ULL<<63)-1, 64, &over); assert(over); + s = int_add((1ULL<<63)-1, 1, 64, &over); assert(over); + s = int_sub(-1, (1ULL<<63), 64, &over); + assert(s == (1ULL<<63)-1); + assert(!over); + s = int_sub((1ULL<<63), 1, 64, &over); assert(over); + + s = int_add(0, 0, 64, &over); + assert(s == 0); + assert(!over); + s = int_sub(0, 0, 64, &over); + assert(s == 0); + assert(!over); + s = int_add(0, -1, 64, &over); + assert(s == -1); + assert(!over); + s = int_sub(0, 1, 64, &over); + assert(s == -1); + assert(!over); + s = int_add(0, (1ULL<<63), 64, &over); + assert(s == (int64_t)(1ULL<<63)); + assert(!over); + s = int_sub(0, (1ULL<<63)-1, 64, &over); + assert(s == (int64_t)((1ULL<<63)+1)); + assert(!over); + + s = int_add(-1, 0, 64, &over); + assert(s == -1); + assert(!over); + s = int_add(-1, 1, 64, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, -1, 64, &over); + assert(s == 0); + assert(!over); + s = int_sub(-1, (1ULL<<63)-1, 64, &over); + assert(s == (int64_t)(1ULL<<63)); + assert(!over); +} + +static void test_int_sign(uint length_bits) { + printf("%s %u\n", __FUNCTION__, length_bits); + int64_t n; + + n = int_high_endpoint(length_bits); + assert(int_sign_extend(n, length_bits) == n); + n = (1ULL<<(length_bits-1)); + assert(int_sign_extend(n, length_bits) == -n); +} + +static void test_int_sign() { + test_int_sign(8); + test_int_sign(16); + test_int_sign(24); + test_int_sign(32); + test_int_sign(64); +} + +int main() { + test_int_sign(); + test_int8(); + test_int16(); + test_int24(); + test_int32(); + test_int64(); + return 0; +} + diff --git a/storage/tokudb/tests/math_test_uint.cc b/storage/tokudb/tests/math_test_uint.cc new file mode 100644 index 00000000..2c5c9261 --- /dev/null +++ b/storage/tokudb/tests/math_test_uint.cc @@ -0,0 +1,187 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <assert.h> +#include <sys/types.h> +#include <tokudb_math.h> +using namespace tokudb; + +static void test_uint_range(uint length_bits) { + assert(uint_low_endpoint(length_bits) == 0); + if (length_bits == 64) + assert(uint_high_endpoint(length_bits) == ~0ULL); + else + assert(uint_high_endpoint(length_bits) == (1ULL<<length_bits)-1); +} + +static void test_uint8() { + printf("%s\n", __FUNCTION__); + test_uint_range(8); + bool over; + uint8_t n; + uint64_t m; + for (uint64_t x = 0; x <= (1ULL<<8)-1; x++) { + for (uint64_t y = 0; y <= (1ULL<<8)-1; y++) { + n = uint_add(x, y, 8, &over); + m = x + y; + if (m > (1ULL<<8)-1) + assert(over); + else { + assert(!over); + assert(n == (m % 256)); + } + n = uint_sub(x, y, 8, &over); + m = x - y; + if (m > x) + assert(over); + else { + assert(!over); + assert(n == (m % 256)); + } + } + } +} + +static void test_uint16() { + printf("%s\n", __FUNCTION__); + test_uint_range(16); + bool over; + uint16_t n; + uint64_t m; + for (uint64_t x = 0; x <= (1ULL<<16)-1; x++) { + for (uint64_t y = 0; y <= (1ULL<<16)-1; y++) { + n = uint_add(x, y, 16, &over); + m = x + y; + if (m > (1ULL<<16)-1) + assert(over); + else { + assert(!over); + assert(n == (m % (1ULL<<16))); + } + n = uint_sub(x, y, 16, &over); + m = x - y; + if (m > x) + assert(over); + else { + assert(!over); + assert(n == (m % (1ULL<<16))); + } + } + } +} + +static void test_uint24() { + printf("%s\n", __FUNCTION__); + test_uint_range(24); + bool over; + uint64_t s; + + s = uint_add((1ULL<<24)-1, (1ULL<<24)-1, 24, &over); assert(over); + s = uint_add((1ULL<<24)-1, 1, 24, &over); assert(over); + s = uint_add((1ULL<<24)-1, 0, 24, &over); + assert(!over); + assert(s == (1ULL<<24)-1); + s = uint_add(0, 1, 24, &over); + assert(!over); + assert(s == 1); + s = uint_add(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 0, 24, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 1, 24, &over); assert(over); + s = uint_sub(0, (1ULL<<24)-1, 24, &over); assert(over); + s = uint_sub((1ULL<<24)-1, (1ULL<<24)-1, 24, &over); + assert(!over); + assert(s == 0); +} + +static void test_uint32() { + printf("%s\n", __FUNCTION__); + test_uint_range(32); + bool over; + uint64_t s; + + s = uint_add((1ULL<<32)-1, (1ULL<<32)-1, 32, &over); assert(over); + s = uint_add((1ULL<<32)-1, 1, 32, &over); assert(over); + s = uint_add((1ULL<<32)-1, 0, 32, &over); + assert(!over); + assert(s == (1ULL<<32)-1); + s = uint_add(0, 1, 32, &over); + assert(!over); + assert(s == 1); + s = uint_add(0, 0, 32, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 0, 32, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 1, 32, &over); assert(over); + s = uint_sub(0, (1ULL<<32)-1, 32, &over); assert(over); + s = uint_sub((1ULL<<32)-1, (1ULL<<32)-1, 32, &over); + assert(!over); + assert(s == 0); +} + +static void test_uint64() { + printf("%s\n", __FUNCTION__); + test_uint_range(64); + bool over; + uint64_t s; + + s = uint_add(~0ULL, ~0ULL, 64, &over); assert(over); + s = uint_add(~0ULL, 1, 64, &over); assert(over); + s = uint_add(~0ULL, 0, 64, &over); + assert(!over); + assert(s == ~0ULL); + s = uint_add(0, 1, 64, &over); + assert(!over); + assert(s == 1); + s = uint_add(0, 0, 64, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 0, 64, &over); + assert(!over); + assert(s == 0); + s = uint_sub(0, 1, 64, &over); assert(over); + s = uint_sub(0, ~0ULL, 64, &over); assert(over); + s = uint_sub(~0ULL, ~0ULL, 64, &over); + assert(!over); + assert(s == 0); +} + +int main() { + test_uint8(); + test_uint16(); + test_uint24(); + test_uint32(); + test_uint64(); + return 0; +} + diff --git a/storage/tokudb/tests/max_test.cc b/storage/tokudb/tests/max_test.cc new file mode 100644 index 00000000..9528111b --- /dev/null +++ b/storage/tokudb/tests/max_test.cc @@ -0,0 +1,47 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +// test explicit generation of a simple template function + +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <assert.h> + +template <class T> T my_max(T a, T b) { + return a > b ? a : b; +} + +template int my_max(int a, int b); + +int main(int argc, char *argv[]) { + assert(argc == 3); + int a = atoi(argv[1]); + int b = atoi(argv[2]); + int m = my_max<int>(a, b); + printf("%d %d %d\n", a, b, m); + assert(m == (a > b ? a : b)); + return 0; +} diff --git a/storage/tokudb/tests/sint_test.cc b/storage/tokudb/tests/sint_test.cc new file mode 100644 index 00000000..7823ee5a --- /dev/null +++ b/storage/tokudb/tests/sint_test.cc @@ -0,0 +1,53 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <stdlib.h> +#include <sys/types.h> + +#include <tokudb_math.h> +using namespace tokudb; + +static void test(int length_bits) { + int64_t max = (1ULL << (length_bits-1)) - 1; + for (int64_t x = -max-1; x <= max; x++) { + for (int64_t y = -max-1; y <= max; y++) { + bool over; + int64_t n = int_add(x, y, length_bits, &over); + printf("%"PRId64" %"PRId64" %"PRId64" %u\n", x, y, n, over); + } + } +} + +int main(int argc, char *argv[]) { + if (argc > 1) { + for (int i = 1; i < argc; i++) { + test(atoi(argv[i])); + } + } + return 0; +} diff --git a/storage/tokudb/tests/tokudb_buffer_test.cc b/storage/tokudb/tests/tokudb_buffer_test.cc new file mode 100644 index 00000000..7e296790 --- /dev/null +++ b/storage/tokudb/tests/tokudb_buffer_test.cc @@ -0,0 +1,234 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdint.h> +#include <tokudb_buffer.h> + +static void test_null() { + tokudb::buffer b; + assert(b.data() == nullptr); + assert(b.size() == 0); + assert(b.limit() == 0); + b.append(NULL, 0); + assert(b.data() == nullptr); + assert(b.size() == 0); + assert(b.limit() == 0); +} + +static void append_az(tokudb::buffer &b) { + for (char c = 'a'; c <= 'z'; c++) { + b.append(&c, sizeof c); + } +} + +static void assert_az(tokudb::buffer &b) { + unsigned char *bp = NULL; + for (size_t i = 0; i < b.size(); i++) { + bp = (unsigned char *) b.data() + i; + assert(*bp == 'a'+i); + } + assert(*bp == 'z'); +} + +static void assert_AZ(tokudb::buffer &b) { + unsigned char *bp = NULL; + for (size_t i = 0; i < b.size(); i++) { + bp = (unsigned char *) b.data() + i; + assert(*bp == 'A'+i); + } + assert(*bp == 'Z'); +} + +static void test_append() { + tokudb::buffer a; + + a.append(NULL, 0); + append_az(a); + a.append(NULL, 0); + assert(a.size() == 'z'-'a'+1); + assert(a.size() <= a.limit()); + assert_az(a); + + tokudb::buffer b(a.data(), 0, a.size()); + for (size_t i = 0; i < b.limit(); i++) { + assert(i <= a.size()); + char *ap = (char *) a.data() + i; + assert(i <= b.limit()); + char *bp = (char *) b.data() + i; + assert(*ap == *bp); + } +} + +static void test_consume() { + tokudb::buffer a; + append_az(a); + tokudb::buffer b(a.data(), 0, a.size()); + for (size_t i = 0; i < b.limit(); i++) { + unsigned char c; + b.consume(&c, 1); + assert(c == 'a'+i); + } + assert(b.size() == b.limit()); +} + +static void test_consume_ptr() { + tokudb::buffer a; + append_az(a); + tokudb::buffer b(a.data(), 0, a.size()); + for (size_t i = 0; i < b.limit(); i++) { + void *p = b.consume_ptr(1); + unsigned char c = *(unsigned char *)p; + assert(c == 'a'+i); + } + assert(b.size() == b.limit()); + assert(b.consume_ptr(1) == NULL); +} + +static void test_replace() { + tokudb::buffer a; + append_az(a); + assert_az(a); + for (size_t i = 0; i < a.size(); i++) { + unsigned char newc[1] = { (unsigned char)('A' + i) }; + a.replace(i, 1, newc, 1); + } + assert_AZ(a); +} + +static void test_replace_grow() { + tokudb::buffer a; + append_az(a); + assert_az(a); + + // grow field + size_t orig_s = a.size(); + for (size_t i = 0; i < orig_s; i++) { + unsigned char newc[2] = { (unsigned char)('a'+i), (unsigned char)('a'+i) }; + size_t old_s = a.size(); + a.replace(2*i, 1, newc, 2); + assert(a.size() == old_s+1); + } + for (size_t i = 0; i < a.size()/2; i++) { + unsigned char *cp = (unsigned char *) a.data() + 2*i; + assert(cp[0] == 'a'+i); + assert(cp[1] == 'a'+i); + } +} + +static void test_replace_shrink() { + tokudb::buffer a; + for (char c = 'a'; c <= 'z'; c++) { + a.append(&c, sizeof c); + a.append(&c, sizeof c); + } + + // shrink field + for (size_t i = 0; i < a.size(); i++) { + unsigned char newc[1] = { (unsigned char)('a'+i) }; + size_t s = a.size(); + a.replace(i, 2, newc, 1); + assert(a.size() == s-1); + } + assert_az(a); +} + +static void test_replace_null() { + tokudb::buffer a; + append_az(a); + assert_az(a); + + // insert between all + size_t n = a.size(); + for (size_t i = 0; i < n; i++) { + unsigned char newc[1] = { (unsigned char)('a'+i) }; + a.replace(2*i, 0, newc, 1); + } + + a.replace(a.size(), 0, (void *)"!", 1); + a.append((void *)"?", 1); +} + +namespace tokudb { + template size_t vlq_encode_ui(uint8_t, void *, size_t); + template size_t vlq_decode_ui(uint8_t *, void *, size_t); + template size_t vlq_encode_ui(uint32_t, void *, size_t); + template size_t vlq_decode_ui(uint32_t *, void *, size_t); +}; + +static void test_ui8() { + tokudb::buffer a; + for (uint8_t n = 0; ; n++) { + assert(a.append_ui<uint8_t>(n) != 0); + if (n == 255) + break; + } + tokudb::buffer b(a.data(), 0, a.size()); + for (uint8_t n = 0; ; n++) { + uint8_t v; + if (b.consume_ui<uint8_t>(&v) == 0) + break; + assert(v == n); + if (n == 255) + break; + } + assert(b.size() == b.limit()); +} + +static void test_ui32() { + tokudb::buffer a; + for (uint32_t n = 0; ; n++) { + assert(a.append_ui<uint32_t>(n) != 0); + if (n == 1<<22) + break; + } + tokudb::buffer b(a.data(), 0, a.size()); + for (uint32_t n = 0; ; n++) { + uint32_t v; + if (b.consume_ui<uint32_t>(&v) == 0) + break; + assert(v == n); + if (n == 1<<22) + break; + } + assert(b.size() == b.limit()); +} + +int main() { + test_null(); + test_append(); + test_consume(); + test_consume_ptr(); + test_replace(); + test_replace_grow(); + test_replace_shrink(); + test_replace_null(); + test_ui8(); + test_ui32(); + return 0; +} diff --git a/storage/tokudb/tests/uint_test.cc b/storage/tokudb/tests/uint_test.cc new file mode 100644 index 00000000..e3aa1a6f --- /dev/null +++ b/storage/tokudb/tests/uint_test.cc @@ -0,0 +1,54 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <stdlib.h> +#include <sys/types.h> + +#include <tokudb_math.h> +using namespace tokudb; + +static void test(int length_bits) { + printf("%s %d\n", __FUNCTION__, length_bits); + uint64_t max = (1ULL << length_bits) - 1; + for (uint64_t x = 0; x <= max; x++) { + for (uint64_t y = 0; y <= max; y++) { + bool over; + uint64_t n = uint_add(x, y, max, &over); + printf("%"PRIu64" %"PRIu64" %"PRIu64"\n", x, y, n); + } + } +} + +int main(int argc, char *argv[]) { + if (argc > 1) { + for (int i = 1; i < argc; i++) { + test(atoi(argv[i])); + } + } + return 0; +} diff --git a/storage/tokudb/tests/vlq_test.cc b/storage/tokudb/tests/vlq_test.cc new file mode 100644 index 00000000..12b222f0 --- /dev/null +++ b/storage/tokudb/tests/vlq_test.cc @@ -0,0 +1,88 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <tokudb_vlq.h> + +namespace tokudb { + template size_t vlq_encode_ui(uint32_t n, void *p, size_t s); + template size_t vlq_decode_ui(uint32_t *np, void *p, size_t s); + template size_t vlq_encode_ui(uint64_t n, void *p, size_t s); + template size_t vlq_decode_ui(uint64_t *np, void *p, size_t s); +}; + +static void test_vlq_uint32_error(void) { + uint32_t n; + unsigned char b[5]; + size_t out_s, in_s; + + out_s = tokudb::vlq_encode_ui<uint32_t>(128, b, 0); + assert(out_s == 0); + out_s = tokudb::vlq_encode_ui<uint32_t>(128, b, 1); + assert(out_s == 0); + out_s = tokudb::vlq_encode_ui<uint32_t>(128, b, 2); + assert(out_s == 2); + in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, 0); + assert(in_s == 0); + in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, 1); + assert(in_s == 0); + in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, 2); + assert(in_s == 2); + assert(n == 128); +} + +static void test_80000000(void) { + uint64_t n; + unsigned char b[10]; + size_t out_s, in_s; + uint64_t v = 0x80000000; + out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 5); + in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 5); + assert(n == v); +} + +static void test_100000000(void) { + uint64_t n; + unsigned char b[10]; + size_t out_s, in_s; + uint64_t v = 0x100000000; + out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 5); + in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 5); + assert(n == v); +} + +int main(void) { + test_vlq_uint32_error(); + test_80000000(); + test_100000000(); + return 0; +} diff --git a/storage/tokudb/tests/vlq_test_uint32.cc b/storage/tokudb/tests/vlq_test_uint32.cc new file mode 100644 index 00000000..3cc8af77 --- /dev/null +++ b/storage/tokudb/tests/vlq_test_uint32.cc @@ -0,0 +1,99 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <tokudb_vlq.h> + +namespace tokudb { + template size_t vlq_encode_ui(uint32_t n, void *p, size_t s); + template size_t vlq_decode_ui(uint32_t *np, void *p, size_t s); + template size_t vlq_encode_ui(uint64_t n, void *p, size_t s); + template size_t vlq_decode_ui(uint64_t *np, void *p, size_t s); +}; + +static void test_vlq_uint32(void) { + printf("%u\n", 0); + for (uint32_t v = 0; v < (1<<7); v++) { + unsigned char b[5]; + size_t out_s = tokudb::vlq_encode_ui<uint32_t>(v, b, sizeof b); + assert(out_s == 1); + uint32_t n; + size_t in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, out_s); + assert(in_s == 1); + assert(n == v); + } + + printf("%u\n", 1<<7); + for (uint32_t v = (1<<7); v < (1<<14); v++) { + unsigned char b[5]; + size_t out_s = tokudb::vlq_encode_ui<uint32_t>(v, b, sizeof b); + assert(out_s == 2); + uint32_t n; + size_t in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, out_s); + assert(in_s == 2); + assert(n == v); + } + + printf("%u\n", 1<<14); + for (uint32_t v = (1<<14); v < (1<<21); v++) { + unsigned char b[5]; + size_t out_s = tokudb::vlq_encode_ui<uint32_t>(v, b, sizeof b); + assert(out_s == 3); + uint32_t n; + size_t in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, out_s); + assert(in_s == 3); + assert(n == v); + } + + printf("%u\n", 1<<21); + for (uint32_t v = (1<<21); v < (1<<28); v++) { + unsigned char b[5]; + size_t out_s = tokudb::vlq_encode_ui<uint32_t>(v, b, sizeof b); + assert(out_s == 4); + uint32_t n; + size_t in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, out_s); + assert(in_s == 4); + assert(n == v); + } + + printf("%u\n", 1<<28); + for (uint32_t v = (1<<28); v != 0; v++) { + unsigned char b[5]; + size_t out_s = tokudb::vlq_encode_ui<uint32_t>(v, b, sizeof b); + assert(out_s == 5); + uint32_t n; + size_t in_s = tokudb::vlq_decode_ui<uint32_t>(&n, b, out_s); + assert(in_s == 5); + assert(n == v); + } +} + +int main(void) { + test_vlq_uint32(); + return 0; +} diff --git a/storage/tokudb/tests/vlq_test_uint64.cc b/storage/tokudb/tests/vlq_test_uint64.cc new file mode 100644 index 00000000..697c5977 --- /dev/null +++ b/storage/tokudb/tests/vlq_test_uint64.cc @@ -0,0 +1,110 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <tokudb_vlq.h> + +namespace tokudb { + template size_t vlq_encode_ui(uint32_t n, void *p, size_t s); + template size_t vlq_decode_ui(uint32_t *np, void *p, size_t s); + template size_t vlq_encode_ui(uint64_t n, void *p, size_t s); + template size_t vlq_decode_ui(uint64_t *np, void *p, size_t s); +}; + +// test a slice of the number space where the slice is described by +// a start number and a stride through the space. +static void test_vlq_uint64(uint64_t start, uint64_t stride) { + printf("%u\n", 0); + for (uint64_t v = 0 + start; v < (1<<7); v += stride) { + unsigned char b[10]; + size_t out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 1); + uint64_t n; + size_t in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 1); + assert(n == v); + } + + printf("%u\n", 1<<7); + for (uint64_t v = (1<<7) + start; v < (1<<14); v += stride) { + unsigned char b[10]; + size_t out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 2); + uint64_t n; + size_t in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 2); + assert(n == v); + } + + printf("%u\n", 1<<14); + for (uint64_t v = (1<<14) + start; v < (1<<21); v += stride) { + unsigned char b[10]; + size_t out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 3); + uint64_t n; + size_t in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 3); + assert(n == v); + } + + printf("%u\n", 1<<21); + for (uint64_t v = (1<<21) + start; v < (1<<28); v += stride) { + unsigned char b[10]; + size_t out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 4); + uint64_t n; + size_t in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 4); + assert(n == v); + } + + printf("%u\n", 1<<28); +#if USE_OPENMP +#pragma omp parallel num_threads(4) +#pragma omp for +#endif + for (uint64_t v = (1<<28) + start; v < (1ULL<<35); v += stride) { + unsigned char b[10]; + size_t out_s = tokudb::vlq_encode_ui<uint64_t>(v, b, sizeof b); + assert(out_s == 5); + uint64_t n; + size_t in_s = tokudb::vlq_decode_ui<uint64_t>(&n, b, out_s); + assert(in_s == 5); + assert(n == v); + } +} + +int main(int argc, char *argv[]) { + uint64_t start = 0, stride = 1; + if (argc == 3) { + start = atoll(argv[1]); + stride = atoll(argv[2]); + } + test_vlq_uint64(start, stride); + return 0; +} |