forked from mindspore-Ecosystem/mindspore
229 lines
6.2 KiB
C++
229 lines
6.2 KiB
C++
/**
|
|
* Copyright 2019 Huawei Technologies Co., Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <sstream>
|
|
#include "minddata/dataset/util/btree.h"
|
|
#include "minddata/dataset/util/auto_index.h"
|
|
#include "minddata/dataset/util/system_pool.h"
|
|
#include "minddata/dataset/util/task_manager.h"
|
|
#include "common/common.h"
|
|
#include "gtest/gtest.h"
|
|
#include "utils/log_adapter.h"
|
|
|
|
using namespace mindspore::dataset;
|
|
using mindspore::MsLogLevel::INFO;
|
|
using mindspore::ExceptionType::NoExceptionType;
|
|
using mindspore::LogStream;
|
|
|
|
// For testing purposes, we will make the branching factor very low.
|
|
struct mytraits {
|
|
using slot_type = uint16_t;
|
|
static const slot_type kLeafSlots = 6;
|
|
static const slot_type kInnerSlots = 3;
|
|
};
|
|
|
|
|
|
class MindDataTestBPlusTree : public UT::Common {
|
|
public:
|
|
MindDataTestBPlusTree() = default;
|
|
};
|
|
|
|
// Test serial insert.
|
|
TEST_F(MindDataTestBPlusTree, Test1) {
|
|
Allocator<std::string> alloc(std::make_shared<SystemPool>());
|
|
BPlusTree<uint64_t, std::string, Allocator<std::string>, std::less<uint64_t>, mytraits> btree(alloc);
|
|
Status rc;
|
|
for (int i = 0; i < 100; i++) {
|
|
uint64_t key = 2 * i;
|
|
std::ostringstream oss;
|
|
oss << "Hello World. I am " << key;
|
|
rc = btree.DoInsert(key, oss.str());
|
|
EXPECT_TRUE(rc.IsOk());
|
|
}
|
|
for (int i = 0; i < 100; i++) {
|
|
uint64_t key = 2 * i + 1;
|
|
std::ostringstream oss;
|
|
oss << "Hello World. I am " << key;
|
|
rc = btree.DoInsert(key, oss.str());
|
|
EXPECT_TRUE(rc.IsOk());
|
|
}
|
|
EXPECT_EQ(btree.size(), 200);
|
|
|
|
// Test iterator
|
|
{
|
|
int cnt = 0;
|
|
auto it = btree.begin();
|
|
uint64_t prev = it.key();
|
|
++it;
|
|
++cnt;
|
|
while (it != btree.end()) {
|
|
uint64_t cur = it.key();
|
|
std::string val = "Hello World. I am " + std::to_string(cur);
|
|
EXPECT_TRUE(prev < cur);
|
|
EXPECT_EQ(it.value(), val);
|
|
prev = cur;
|
|
++it;
|
|
++cnt;
|
|
}
|
|
EXPECT_EQ(cnt, 200);
|
|
// Now go backward
|
|
for (int i = 0; i < 10; i++) {
|
|
--it;
|
|
EXPECT_EQ(199 - i, it.key());
|
|
}
|
|
}
|
|
|
|
// Test search
|
|
{
|
|
MS_LOG(INFO) << "Locate key " << 100 << " Expect found.";
|
|
auto r = btree.Search(100);
|
|
auto &it = r.first;
|
|
EXPECT_TRUE(r.second);
|
|
EXPECT_EQ(it.key(), 100);
|
|
EXPECT_EQ(it.value(), "Hello World. I am 100");
|
|
MS_LOG(INFO) << "Locate key " << 300 << " Expect not found.";
|
|
auto q = btree.Search(300);
|
|
EXPECT_FALSE(q.second);
|
|
}
|
|
|
|
// Test duplicate key
|
|
{
|
|
rc = btree.DoInsert(100, "Expect error");
|
|
EXPECT_EQ(rc, Status(StatusCode::kDuplicateKey));
|
|
}
|
|
}
|
|
|
|
// Test concurrent insert.
|
|
TEST_F(MindDataTestBPlusTree, Test2) {
|
|
Allocator<std::string> alloc(std::make_shared<SystemPool>());
|
|
BPlusTree<uint64_t, std::string, Allocator<std::string>, std::less<uint64_t>, mytraits> btree(alloc);
|
|
TaskGroup vg;
|
|
auto f = [&](int k) -> Status {
|
|
TaskManager::FindMe()->Post();
|
|
for (int i = 0; i < 100; i++) {
|
|
uint64_t key = k * 100 + i;
|
|
std::ostringstream oss;
|
|
oss << "Hello World. I am " << key;
|
|
Status rc = btree.DoInsert(key, oss.str());
|
|
EXPECT_TRUE(rc.IsOk());
|
|
}
|
|
return Status::OK();
|
|
};
|
|
auto g = [&](int k) -> Status {
|
|
TaskManager::FindMe()->Post();
|
|
for (int i = 0; i < 1000; i++) {
|
|
uint64_t key = rand() % 10000;;
|
|
auto it = btree.Search(key);
|
|
}
|
|
return Status::OK();
|
|
};
|
|
// Spawn multiple threads to do insert.
|
|
for (int k = 0; k < 100; k++) {
|
|
vg.CreateAsyncTask("Concurrent Insert", std::bind(f, k));
|
|
}
|
|
// Spawn a few threads to do random search.
|
|
for (int k = 0; k < 2; k++) {
|
|
vg.CreateAsyncTask("Concurrent search", std::bind(g, k));
|
|
}
|
|
vg.join_all();
|
|
EXPECT_EQ(btree.size(), 10000);
|
|
|
|
// Test iterator
|
|
{
|
|
int cnt = 0;
|
|
auto it = btree.begin();
|
|
uint64_t prev = it.key();
|
|
++it;
|
|
++cnt;
|
|
while (it != btree.end()) {
|
|
uint64_t cur = it.key();
|
|
std::string val = "Hello World. I am " + std::to_string(cur);
|
|
EXPECT_TRUE(prev < cur);
|
|
EXPECT_EQ(it.value(), val);
|
|
prev = cur;
|
|
++it;
|
|
++cnt;
|
|
}
|
|
EXPECT_EQ(cnt, 10000);
|
|
}
|
|
|
|
// Test search
|
|
{
|
|
MS_LOG(INFO) << "Locating key from 0 to 9999. Expect found.";
|
|
for (int i = 0; i < 10000; i++) {
|
|
auto r = btree.Search(i);
|
|
EXPECT_TRUE(r.second);
|
|
if (r.second) {
|
|
auto &it = r.first;
|
|
EXPECT_EQ(it.key(), i);
|
|
std::string val = "Hello World. I am " + std::to_string(i);
|
|
EXPECT_EQ(it.value(), val);
|
|
}
|
|
}
|
|
MS_LOG(INFO) << "Locate key " << 10000 << ". Expect not found";
|
|
auto q = btree.Search(10000);
|
|
EXPECT_FALSE(q.second);
|
|
}
|
|
}
|
|
|
|
TEST_F(MindDataTestBPlusTree, Test3) {
|
|
Allocator<std::string> alloc(std::make_shared<SystemPool>());
|
|
AutoIndexObj<std::string, Allocator<std::string>> ai(alloc);
|
|
Status rc;
|
|
rc = ai.insert("Hello World");
|
|
EXPECT_TRUE(rc.IsOk());
|
|
rc = ai.insert({"a", "b", "c"});
|
|
EXPECT_TRUE(rc.IsOk());
|
|
uint64_t min = ai.min_key();
|
|
uint64_t max = ai.max_key();
|
|
EXPECT_EQ(min, 0);
|
|
EXPECT_EQ(max, 3);
|
|
auto r = ai.Search(2);
|
|
auto &it = r.first;
|
|
EXPECT_EQ(it.value(), "b");
|
|
MS_LOG(INFO) << "Dump all the values using [] operator.";
|
|
for (uint64_t i = min; i <= max; i++) {
|
|
MS_LOG(DEBUG) << ai[i] << std::endl;
|
|
}
|
|
}
|
|
|
|
TEST_F(MindDataTestBPlusTree, Test4) {
|
|
Allocator<int64_t> alloc(std::make_shared<SystemPool>());
|
|
AutoIndexObj<int64_t, Allocator<int64_t>> ai(alloc);
|
|
Status rc;
|
|
for (int i = 0; i < 1000; i++) {
|
|
rc = ai.insert(std::make_unique<int64_t>(i));
|
|
EXPECT_TRUE(rc.IsOk());
|
|
}
|
|
// Test iterator
|
|
{
|
|
int cnt = 0;
|
|
auto it = ai.begin();
|
|
uint64_t prev = it.key();
|
|
++it;
|
|
++cnt;
|
|
while (it != ai.end()) {
|
|
uint64_t cur = it.key();
|
|
EXPECT_TRUE(prev < cur);
|
|
EXPECT_EQ(it.value(), cnt);
|
|
prev = cur;
|
|
++it;
|
|
++cnt;
|
|
}
|
|
EXPECT_EQ(cnt, 1000);
|
|
}
|
|
}
|