curve/test/chunkserver/clone/clone_copyer_test.cpp

369 lines
12 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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
* Created Date: Wednesday April 10th 2019
* Author: yangyaokai
*/
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <glog/logging.h>
#include "include/client/libcurve.h"
#include "src/chunkserver/clone_copyer.h"
#include "src/chunkserver/clone_core.h"
#include "test/chunkserver/clone/clone_test_util.h"
#include "test/client/mock/mock_file_client.h"
#include "test/common/mock_s3_adapter.h"
namespace curve {
namespace chunkserver {
using curve::client::MockFileClient;
using curve::common::MockS3Adapter;
const char CURVE_CONF[] = "client.conf";
const char S3_CONF[] = "s3.conf";
const char ROOT_OWNER[] = "root";
const char ROOT_PWD[] = "pwd";
const uint64_t EXPIRED_USE = 5;
class MockDownloadClosure : public DownloadClosure {
public:
explicit MockDownloadClosure(AsyncDownloadContext* context)
: DownloadClosure(nullptr, nullptr, context, nullptr)
, isRun_(false) {}
void Run() {
CHECK(!isRun_) << "closure has been invoked.";
isRun_ = true;
}
bool IsFailed() {
return isFailed_;
}
bool IsRun() {
return isRun_;
}
void Reset() {
isFailed_ = false;
isRun_ = false;
}
private:
bool isRun_;
};
class CloneCopyerTest : public testing::Test {
public:
void SetUp() {
curveClient_ = std::make_shared<MockFileClient>();
s3Client_ = std::make_shared<MockS3Adapter>();
Aws::InitAPI(awsOptions_);
}
void TearDown() {
Aws::ShutdownAPI(awsOptions_);
}
protected:
std::shared_ptr<MockFileClient> curveClient_;
std::shared_ptr<MockS3Adapter> s3Client_;
Aws::SDKOptions awsOptions_;
};
TEST_F(CloneCopyerTest, BasicTest) {
OriginCopyer copyer;
CopyerOptions options;
options.curveConf = CURVE_CONF;
options.s3Conf = S3_CONF;
options.curveUser.owner = ROOT_OWNER;
options.curveUser.password = ROOT_PWD;
options.curveClient = curveClient_;
options.s3Client = s3Client_;
options.curveFileTimeoutSec = EXPIRED_USE;
// init test
{
// curvefs init failed
EXPECT_CALL(*curveClient_, Init(StrEq(CURVE_CONF)))
.WillOnce(Return(LIBCURVE_ERROR::FAILED));
ASSERT_EQ(-1, copyer.Init(options));
// curvefs init success
EXPECT_CALL(*curveClient_, Init(StrEq(CURVE_CONF)))
.WillOnce(Return(LIBCURVE_ERROR::OK));
ASSERT_EQ(0, copyer.Init(options));
}
// Download test
{
char* buf = new char[4096];
AsyncDownloadContext context;
context.offset = 0;
context.size = 4096;
context.buf = buf;
MockDownloadClosure closure(&context);
// invalid location
context.location = "aaaaa";
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
// invalid location
context.location = "aaaaa@cs";
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
/* 用例:读curve上的数据读取成功
* 预期:调用Open和Read读取数据
*/
context.location = "test:0@cs";
EXPECT_CALL(*curveClient_, Open4ReadOnly("test", _, true))
.WillOnce(Return(1));
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.WillOnce(Invoke([](int fd, CurveAioContext* context,
curve::client::UserDataType dataType) {
context->ret = 1024;
context->cb(context);
return LIBCURVE_ERROR::OK;
}));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_FALSE(closure.IsFailed());
closure.Reset();
/* 用例:再次读前面的文件,但是ret值为-1
* 预期:直接Read返回失败
*/
context.location = "test:0@cs";
EXPECT_CALL(*curveClient_, Open4ReadOnly(_, _, true))
.Times(0);
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.WillOnce(Invoke([](int fd, CurveAioContext* context,
curve::client::UserDataType dataType) {
context->ret = -1;
context->cb(context);
return LIBCURVE_ERROR::OK;
}));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
/* 用例:读curve上的数据Open的时候失败
* 预期:返回-1
*/
context.location = "test2:0@cs";
EXPECT_CALL(*curveClient_, Open4ReadOnly("test2", _, true))
.WillOnce(Return(-1));
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.Times(0);
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
/* 用例:读curve上的数据Read的时候失败
* 预期:返回-1
*/
context.location = "test2:0@cs";
EXPECT_CALL(*curveClient_, Open4ReadOnly("test2", _, true))
.WillOnce(Return(2));
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.WillOnce(Return(-1 * LIBCURVE_ERROR::FAILED));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
/* 用例:读s3上的数据读取成功
* 预期:返回0
*/
context.location = "test@s3";
EXPECT_CALL(*s3Client_, GetObjectAsync(_))
.WillOnce(Invoke(
[&] (const std::shared_ptr<GetObjectAsyncContext>& context) {
context->retCode = 0;
context->cb(s3Client_.get(), context);
}));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_FALSE(closure.IsFailed());
closure.Reset();
/* 用例:读s3上的数据读取失败
* 预期:返回-1
*/
context.location = "test@s3";
EXPECT_CALL(*s3Client_, GetObjectAsync(_))
.WillOnce(Invoke(
[&] (const std::shared_ptr<GetObjectAsyncContext>& context) {
context->retCode = -1;
context->cb(s3Client_.get(), context);
}));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
delete [] buf;
}
// fini test
{
EXPECT_CALL(*curveClient_, Close(1))
.Times(1);
EXPECT_CALL(*curveClient_, Close(2))
.Times(1);
EXPECT_CALL(*curveClient_, UnInit())
.Times(1);
EXPECT_CALL(*s3Client_, Deinit())
.Times(1);
ASSERT_EQ(0, copyer.Fini());
}
}
TEST_F(CloneCopyerTest, DisableTest) {
OriginCopyer copyer;
CopyerOptions options;
options.curveConf = CURVE_CONF;
options.s3Conf = S3_CONF;
options.curveUser.owner = ROOT_OWNER;
options.curveUser.password = ROOT_PWD;
options.curveFileTimeoutSec = EXPIRED_USE;
// 禁用curveclient和s3adapter
options.curveClient = nullptr;
options.s3Client = nullptr;
// curvefs init success
EXPECT_CALL(*curveClient_, Init(_))
.Times(0);
ASSERT_EQ(0, copyer.Init(options));
// 从上s3或者curve请求下载数据会返回失败
{
char* buf = new char[4096];
AsyncDownloadContext context;
context.offset = 0;
context.size = 4096;
context.buf = buf;
MockDownloadClosure closure(&context);
/* 用例:读curve上的数据读取失败
*/
context.location = "test:0@cs";
EXPECT_CALL(*curveClient_, Open4ReadOnly(_, _, true))
.Times(0);
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.Times(0);
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
/* 用例:读s3上的数据读取失败
*/
context.location = "test@s3";
EXPECT_CALL(*s3Client_, GetObjectAsync(_))
.Times(0);
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_TRUE(closure.IsFailed());
closure.Reset();
delete [] buf;
}
// fini 可以成功
ASSERT_EQ(0, copyer.Fini());
}
TEST_F(CloneCopyerTest, ExpiredTest) {
OriginCopyer copyer;
CopyerOptions options;
options.curveConf = CURVE_CONF;
options.s3Conf = S3_CONF;
options.curveUser.owner = ROOT_OWNER;
options.curveUser.password = ROOT_PWD;
options.curveClient = curveClient_;
options.s3Client = s3Client_;
options.curveFileTimeoutSec = EXPIRED_USE;
// curvefs init success
EXPECT_CALL(*curveClient_, Init(StrEq(CURVE_CONF)))
.WillOnce(Return(LIBCURVE_ERROR::OK));
ASSERT_EQ(0, copyer.Init(options));
{
char* buf = new char[4096];
AsyncDownloadContext context;
context.offset = 0;
context.size = 4096;
context.buf = buf;
MockDownloadClosure closure(&context);
/* Case: Read the same chunk after it expired
* Expect: Re-Open the curve file
*/
context.location = "test:0@cs";
EXPECT_CALL(*curveClient_, Open4ReadOnly("test", _, true))
.WillOnce(Return(1));
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.WillOnce(Invoke([](int fd, CurveAioContext* context,
curve::client::UserDataType dataType) {
context->ret = 1024;
context->cb(context);
return LIBCURVE_ERROR::OK;
}));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
ASSERT_FALSE(closure.IsFailed());
closure.Reset();
std::this_thread::sleep_for(std::chrono::seconds(5));
context.location = "test:0@cs";
std::this_thread::sleep_for(std::chrono::seconds(1));
EXPECT_CALL(*curveClient_, Open4ReadOnly(_, _, true))
.WillOnce(Return(2));
EXPECT_CALL(*curveClient_, AioRead(_, _, _))
.WillOnce(Invoke([](int fd, CurveAioContext* context,
curve::client::UserDataType dataType) {
context->ret = 1024;
context->cb(context);
return LIBCURVE_ERROR::OK;
}));
copyer.DownloadAsync(&closure);
ASSERT_TRUE(closure.IsRun());
closure.Reset();
delete [] buf;
}
// fini
EXPECT_CALL(*curveClient_, Close(2))
.Times(1);
EXPECT_CALL(*curveClient_, UnInit())
.Times(1);
EXPECT_CALL(*s3Client_, Deinit())
.Times(1);
ASSERT_EQ(0, copyer.Fini());
}
} // namespace chunkserver
} // namespace curve