forked from caoXF/curve
463 lines
12 KiB
C++
463 lines
12 KiB
C++
/*
|
|
* Copyright (c) 2020 NetEase Inc.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* Project: Curve
|
|
*
|
|
* History:
|
|
* 2018/11/23 Wenyu Zhou Initial version
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <gflags/gflags.h>
|
|
#include <glog/logging.h>
|
|
#include <braft/configuration.h>
|
|
|
|
#include <string>
|
|
|
|
// #define CBD_BACKEND_FAKE
|
|
|
|
#include "include/client/libcbd.h"
|
|
|
|
#include "src/client/libcurve_file.h"
|
|
#include "include/client/libcurve.h"
|
|
#include "src/client/file_instance.h"
|
|
#include "test/client/fake/mock_schedule.h"
|
|
#include "test/client/fake/fakeMDS.h"
|
|
#include "src/client/client_common.h"
|
|
#include "test/integration/cluster_common/cluster.h"
|
|
#include "test/util/config_generator.h"
|
|
|
|
using curve::client::EndPoint;
|
|
|
|
#define BUFSIZE 4 * 1024
|
|
#define FILESIZE 10uL * 1024 * 1024 * 1024
|
|
#define NEWSIZE 20uL * 1024 * 1024 * 1024
|
|
|
|
#define filename "1_userinfo_test.img"
|
|
|
|
const uint64_t GiB = 1024ull * 1024 * 1024;
|
|
|
|
DECLARE_string(chunkserver_list);
|
|
|
|
extern std::string configpath;
|
|
void LibcbdLibcurveTestCallback(CurveAioContext* context) {
|
|
context->op = LIBCURVE_OP_MAX;
|
|
}
|
|
|
|
std::atomic<bool> discardComplete(false);
|
|
void AioDiscardCallback(CurveAioContext* context) {
|
|
ASSERT_EQ(context->ret, 0);
|
|
discardComplete.store(true, std::memory_order_release);
|
|
}
|
|
|
|
class TestLibcbdLibcurve : public ::testing::Test {
|
|
public:
|
|
void SetUp() {
|
|
FLAGS_chunkserver_list =
|
|
"127.0.0.1:9110:0,127.0.0.1:9111:0,127.0.0.1:9112:0";
|
|
|
|
mds_ = new FakeMDS(filename);
|
|
|
|
// 设置leaderid
|
|
EndPoint ep;
|
|
butil::str2endpoint("127.0.0.1", 9110, &ep);
|
|
braft::PeerId pd(ep);
|
|
|
|
/*** init mds service ***/
|
|
mds_->Initialize();
|
|
mds_->StartCliService(pd);
|
|
mds_->StartService();
|
|
mds_->CreateCopysetNode(true);
|
|
|
|
if (Init(configpath.c_str()) != 0) {
|
|
LOG(FATAL) << "Fail to init config";
|
|
return;
|
|
}
|
|
|
|
int64_t t0 = butil::monotonic_time_ms();
|
|
int ret = -1;
|
|
for (;;) {
|
|
ret = Open4Qemu(filename);
|
|
if (ret == 0) {
|
|
LOG(INFO) << "Created file for test.";
|
|
break;
|
|
}
|
|
|
|
int64_t t1 = butil::monotonic_time_ms();
|
|
// Set timeout to 10 seconds
|
|
if (t1 - t0 > 10 * 1000) {
|
|
LOG(ERROR) << "Timed out retrying of creating file.";
|
|
break;
|
|
}
|
|
|
|
LOG(ERROR) << "Failed to create file, retrying again.";
|
|
usleep(100 * 1000);
|
|
}
|
|
ASSERT_EQ(ret, 0);
|
|
Close(ret);
|
|
}
|
|
|
|
void TearDown() {
|
|
mds_->UnInitialize();
|
|
|
|
UnInit();
|
|
delete mds_;
|
|
}
|
|
|
|
protected:
|
|
FakeMDS* mds_;
|
|
};
|
|
|
|
extern bool globalclientinited_;
|
|
extern curve::client::FileClient* globalclient;
|
|
TEST_F(TestLibcbdLibcurve, InitTest) {
|
|
int ret;
|
|
CurveOptions opt;
|
|
|
|
globalclient->UnInit();
|
|
globalclient = nullptr;
|
|
globalclientinited_ = false;
|
|
memset(&opt, 0, sizeof(opt));
|
|
// testing with no conf specified
|
|
opt.conf = const_cast<char*>("");
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_NE(ret, 0);
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
// testing with conf specified
|
|
opt.conf = const_cast<char*>(configpath.c_str());
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_EQ(ret, 0);
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, 0);
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, ExtendTest) {
|
|
int ret;
|
|
CurveOptions opt;
|
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
// testing with conf specified
|
|
opt.conf = const_cast<char*>(configpath.c_str());
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_EQ(ret, 0);
|
|
ret = cbd_lib_resize(filename, NEWSIZE);
|
|
ASSERT_EQ(ret, 0);
|
|
ret = cbd_lib_resize(filename, -1);
|
|
ASSERT_EQ(-LIBCURVE_ERROR::FAILED, ret);
|
|
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, ReadWriteTest) {
|
|
int ret;
|
|
int fd;
|
|
int i;
|
|
char buf[BUFSIZE];
|
|
CurveOptions opt;
|
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
memset(buf, 'a', BUFSIZE);
|
|
|
|
opt.conf = const_cast<char*>(configpath.c_str());
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
|
|
fd = cbd_lib_open(filename);
|
|
ASSERT_GE(fd, 0);
|
|
|
|
uint64_t size = cbd_lib_filesize(filename);
|
|
ASSERT_EQ(size, FILESIZE);
|
|
|
|
ret = cbd_lib_pwrite(fd, buf, 0, BUFSIZE);
|
|
ASSERT_EQ(ret, BUFSIZE);
|
|
|
|
ret = cbd_lib_sync(fd);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
ret = cbd_lib_pread(fd, buf, 0, BUFSIZE);
|
|
ASSERT_EQ(ret, BUFSIZE);
|
|
|
|
for (i = 0; i < BUFSIZE; i++) {
|
|
if (buf[i] != 'a') {
|
|
break;
|
|
}
|
|
}
|
|
ASSERT_EQ(i, BUFSIZE);
|
|
|
|
ret = cbd_lib_close(fd);
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, DiscardTest) {
|
|
int fd;
|
|
CurveOptions opts;
|
|
memset(&opts, 0, sizeof(opts));
|
|
|
|
opts.conf = const_cast<char*>(configpath.c_str());
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_init(&opts));
|
|
|
|
fd = cbd_lib_open(filename);
|
|
ASSERT_GE(fd, 0);
|
|
|
|
ASSERT_EQ(0, cbd_lib_pdiscard(fd, 0, 4096));
|
|
ASSERT_EQ(0, cbd_lib_pdiscard(fd, 1 * GiB, 1 * GiB));
|
|
|
|
sleep(1);
|
|
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_close(fd));
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_fini());
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, AioReadWriteTest) {
|
|
int ret;
|
|
int fd;
|
|
int i;
|
|
char buf[BUFSIZE];
|
|
CurveOptions opt;
|
|
CurveAioContext aioCtx;
|
|
|
|
aioCtx.buf = buf;
|
|
aioCtx.offset = 0;
|
|
aioCtx.length = BUFSIZE;
|
|
aioCtx.cb = LibcbdLibcurveTestCallback;
|
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
memset(buf, 'a', BUFSIZE);
|
|
|
|
opt.conf = const_cast<char*>(configpath.c_str());
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
|
|
fd = cbd_lib_open(filename);
|
|
ASSERT_GE(fd, 0);
|
|
|
|
uint64_t size = cbd_lib_filesize(filename);
|
|
ASSERT_EQ(size, FILESIZE);
|
|
|
|
aioCtx.op = LIBCURVE_OP_WRITE;
|
|
ret = cbd_lib_aio_pwrite(fd, &aioCtx);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
while (aioCtx.op == LIBCURVE_OP_WRITE) {
|
|
usleep(10 * 1000);
|
|
}
|
|
|
|
ret = cbd_lib_sync(fd);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
aioCtx.op = LIBCURVE_OP_READ;
|
|
ret = cbd_lib_aio_pread(fd, &aioCtx);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
while (aioCtx.op == LIBCURVE_OP_READ) {
|
|
usleep(10 * 1000);
|
|
}
|
|
|
|
for (i = 0; i < BUFSIZE; i++) {
|
|
if (buf[i] != 'a') {
|
|
break;
|
|
}
|
|
}
|
|
ASSERT_EQ(i, BUFSIZE);
|
|
|
|
ret = cbd_lib_close(fd);
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, TestAioDiscard) {
|
|
int fd;
|
|
CurveOptions opts;
|
|
memset(&opts, 0, sizeof(opts));
|
|
opts.conf = const_cast<char*>(configpath.c_str());
|
|
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_init(&opts));
|
|
|
|
fd = cbd_lib_open(filename);
|
|
ASSERT_GE(fd, 0);
|
|
|
|
{
|
|
CurveAioContext aioctx;
|
|
aioctx.op = LIBCURVE_OP_DISCARD;
|
|
aioctx.offset = 0;
|
|
aioctx.length = 4096;
|
|
aioctx.cb = AioDiscardCallback;
|
|
|
|
discardComplete.store(false);
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_aio_pdiscard(fd, &aioctx));
|
|
|
|
while (discardComplete.load(std::memory_order_consume) != true) {
|
|
usleep(100);
|
|
}
|
|
}
|
|
|
|
{
|
|
CurveAioContext aioctx;
|
|
aioctx.op = LIBCURVE_OP_DISCARD;
|
|
aioctx.offset = 1 * GiB;
|
|
aioctx.length = 1 * GiB;
|
|
aioctx.cb = AioDiscardCallback;
|
|
|
|
discardComplete.store(false);
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_aio_pdiscard(fd, &aioctx));
|
|
|
|
while (discardComplete.load(std::memory_order_consume) != true) {
|
|
usleep(100);
|
|
}
|
|
}
|
|
|
|
sleep(1);
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_close(fd));
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_fini());
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, StatFileTest) {
|
|
int64_t ret;
|
|
CurveOptions opt;
|
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
// testing with conf specified
|
|
opt.conf = const_cast<char*>(configpath.c_str());
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
ret = cbd_lib_filesize(filename);
|
|
ASSERT_EQ(ret, FILESIZE);
|
|
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, ReadAndCloseConcurrencyTest) {
|
|
char buffer[BUFSIZE];
|
|
CurveOptions opts;
|
|
|
|
const int closeFileSleepS = 20;
|
|
|
|
memset(&opts, 0, sizeof(opts));
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
opts.conf = const_cast<char*>(configpath.c_str());
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_init(&opts));
|
|
|
|
int fd1 = cbd_lib_open("/ReadWithCloseTest1_test_");
|
|
int fd2 = cbd_lib_open("/ReadWithCloseTest2_test_");
|
|
ASSERT_GE(fd1, 0);
|
|
ASSERT_GE(fd2, 0);
|
|
|
|
auto curvefsService = mds_->GetMDSService();
|
|
curvefsService->SetCloseFileTask([closeFileSleepS]() {
|
|
std::this_thread::sleep_for(std::chrono::seconds(closeFileSleepS));
|
|
});
|
|
|
|
auto closeThread = [](int fd) {
|
|
ASSERT_EQ(0, cbd_lib_close(fd));
|
|
LOG(INFO) << "here";
|
|
};
|
|
|
|
auto readThread = [buffer](int fd) {
|
|
auto start = curve::common::TimeUtility::GetTimeofDayMs();
|
|
ASSERT_EQ(BUFSIZE, cbd_lib_pread(fd, (void*)buffer, 0, BUFSIZE)); // NOLINT
|
|
auto end = curve::common::TimeUtility::GetTimeofDayMs();
|
|
|
|
ASSERT_LE(end - start, 1000);
|
|
};
|
|
|
|
std::thread t1(closeThread, fd1);
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
std::thread t2(readThread, fd2);
|
|
|
|
t1.join();
|
|
t2.join();
|
|
|
|
curvefsService->SetCloseFileTask(nullptr);
|
|
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_close(fd1));
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_close(fd2));
|
|
|
|
ASSERT_EQ(LIBCURVE_ERROR::OK, cbd_lib_fini());
|
|
}
|
|
|
|
TEST_F(TestLibcbdLibcurve, IncreaseEpochTest) {
|
|
int ret;
|
|
CurveOptions opt;
|
|
|
|
memset(&opt, 0, sizeof(opt));
|
|
|
|
// testing with conf specified
|
|
opt.conf = const_cast<char*>(configpath.c_str());
|
|
ret = cbd_lib_init(&opt);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
auto fakecurvefsservice = mds_->GetMDSService();
|
|
|
|
curve::mds::IncreaseFileEpochResponse response;
|
|
response.set_statuscode(curve::mds::StatusCode::kOK);
|
|
response.set_allocated_fileinfo(new curve::mds::FileInfo);
|
|
|
|
FakeReturn fakeIncreaseFileEpochret(nullptr, &response);
|
|
fakecurvefsservice->SetIncreaseFileEpochReturn(&fakeIncreaseFileEpochret);
|
|
|
|
ret = cbd_lib_increase_epoch(filename);
|
|
ASSERT_EQ(ret, 0);
|
|
|
|
ret = cbd_lib_fini();
|
|
ASSERT_EQ(ret, LIBCURVE_ERROR::OK);
|
|
}
|
|
|
|
std::string mdsMetaServerAddr = "127.0.0.1:9951"; // NOLINT
|
|
uint32_t segment_size = 1 * 1024 * 1024 * 1024ul; // NOLINT
|
|
uint32_t chunk_size = 4 * 1024 * 1024; // NOLINT
|
|
std::string configpath = "./test/client/configs/client_libcbd.conf"; // NOLINT
|
|
|
|
const std::vector<std::string> clientConf {
|
|
std::string("mds.listen.addr=127.0.0.1:9951"),
|
|
std::string("global.logPath=./runlog/"),
|
|
std::string("chunkserver.rpcTimeoutMS=1000"),
|
|
std::string("chunkserver.opMaxRetry=3"),
|
|
std::string("metacache.getLeaderRetry=3"),
|
|
std::string("metacache.getLeaderTimeOutMS=1000"),
|
|
std::string("global.fileMaxInFlightRPCNum=2048"),
|
|
std::string("metacache.rpcRetryIntervalUS=500"),
|
|
std::string("mds.rpcRetryIntervalUS=500"),
|
|
std::string("schedule.threadpoolSize=2"),
|
|
std::string("discard.discardTaskDelayMs=10")
|
|
};
|
|
|
|
int main(int argc, char ** argv) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
google::ParseCommandLineFlags(&argc, &argv, false);
|
|
|
|
curve::CurveCluster* cluster = new curve::CurveCluster();
|
|
|
|
cluster->PrepareConfig<curve::ClientConfigGenerator>(
|
|
configpath, clientConf);
|
|
|
|
int ret = RUN_ALL_TESTS();
|
|
return ret;
|
|
}
|