summaryrefslogtreecommitdiffstats
path: root/src/test/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/client')
-rw-r--r--src/test/client/CMakeLists.txt17
-rw-r--r--src/test/client/TestClient.h150
-rw-r--r--src/test/client/alternate_name.cc197
-rwxr-xr-xsrc/test/client/iozone.sh12
-rwxr-xr-xsrc/test/client/kernel_untar_build.sh13
-rw-r--r--src/test/client/main.cc28
-rw-r--r--src/test/client/ops.cc45
7 files changed, 462 insertions, 0 deletions
diff --git a/src/test/client/CMakeLists.txt b/src/test/client/CMakeLists.txt
new file mode 100644
index 000000000..1937bdd0b
--- /dev/null
+++ b/src/test/client/CMakeLists.txt
@@ -0,0 +1,17 @@
+if(${WITH_CEPHFS})
+ add_executable(ceph_test_client
+ main.cc
+ alternate_name.cc
+ ops.cc
+ )
+ target_link_libraries(ceph_test_client
+ client
+ global
+ ceph-common
+ ${UNITTEST_LIBS}
+ ${EXTRALIBS}
+ ${CMAKE_DL_LIBS}
+ )
+ install(TARGETS ceph_test_client
+ DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif(${WITH_CEPHFS})
diff --git a/src/test/client/TestClient.h b/src/test/client/TestClient.h
new file mode 100644
index 000000000..bf3b274af
--- /dev/null
+++ b/src/test/client/TestClient.h
@@ -0,0 +1,150 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2021 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "gtest/gtest.h"
+
+#include "common/async/context_pool.h"
+#include "global/global_context.h"
+
+#include "msg/Messenger.h"
+#include "mon/MonClient.h"
+#include "osdc/ObjectCacher.h"
+#include "client/MetaRequest.h"
+#include "client/Client.h"
+#include "messages/MClientReclaim.h"
+#include "messages/MClientSession.h"
+#include "common/async/blocked_completion.h"
+
+#define dout_subsys ceph_subsys_client
+
+namespace bs = boost::system;
+namespace ca = ceph::async;
+
+class ClientScaffold : public Client {
+public:
+ ClientScaffold(Messenger *m, MonClient *mc, Objecter *objecter_) : Client(m, mc, objecter_) {}
+ virtual ~ClientScaffold()
+ { }
+ int check_dummy_op(const UserPerm& perms){
+ RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
+ if (!mref_reader.is_state_satisfied()) {
+ return -CEPHFS_ENOTCONN;
+ }
+ std::scoped_lock l(client_lock);
+ MetaRequest *req = new MetaRequest(CEPH_MDS_OP_DUMMY);
+ int res = make_request(req, perms);
+ ldout(cct, 10) << __func__ << " result=" << res << dendl;
+ return res;
+ }
+ int send_unknown_session_op(int op) {
+ RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
+ if (!mref_reader.is_state_satisfied()) {
+ return -CEPHFS_ENOTCONN;
+ }
+ std::scoped_lock l(client_lock);
+ auto session = _get_or_open_mds_session(0);
+ auto msg = make_message<MClientSession>(op, session->seq);
+ int res = session->con->send_message2(std::move(msg));
+ ldout(cct, 10) << __func__ << " result=" << res << dendl;
+ return res;
+ }
+ bool check_client_blocklisted() {
+ RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
+ if (!mref_reader.is_state_satisfied()) {
+ return -CEPHFS_ENOTCONN;
+ }
+ std::scoped_lock l(client_lock);
+ bs::error_code ec;
+ ldout(cct, 20) << __func__ << ": waiting for latest osdmap" << dendl;
+ objecter->wait_for_latest_osdmap(ca::use_blocked[ec]);
+ ldout(cct, 20) << __func__ << ": got latest osdmap: " << ec << dendl;
+ const auto myaddrs = messenger->get_myaddrs();
+ return objecter->with_osdmap([&](const OSDMap& o) {return o.is_blocklisted(myaddrs);});
+ }
+ bool check_unknown_reclaim_flag(uint32_t flag) {
+ RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
+ if (!mref_reader.is_state_satisfied()) {
+ return -CEPHFS_ENOTCONN;
+ }
+ std::scoped_lock l(client_lock);
+ char uuid[256];
+ sprintf(uuid, "unknownreclaimflag:%x", getpid());
+ auto session = _get_or_open_mds_session(0);
+ auto m = make_message<MClientReclaim>(uuid, flag);
+ ceph_assert(session->con->send_message2(std::move(m)) == 0);
+ wait_on_list(waiting_for_reclaim);
+ return session->reclaim_state == MetaSession::RECLAIM_FAIL ? true : false;
+ }
+};
+
+class TestClient : public ::testing::Test {
+public:
+ static void SetUpTestSuite() {
+ icp.start(g_ceph_context->_conf.get_val<std::uint64_t>("client_asio_thread_count"));
+ }
+ static void TearDownTestSuite() {
+ icp.stop();
+ }
+ void SetUp() override {
+ messenger = Messenger::create_client_messenger(g_ceph_context, "client");
+ if (messenger->start() != 0) {
+ throw std::runtime_error("failed to start messenger");
+ }
+
+ mc = new MonClient(g_ceph_context, icp);
+ if (mc->build_initial_monmap() < 0) {
+ throw std::runtime_error("build monmap");
+ }
+ mc->set_messenger(messenger);
+ mc->set_want_keys(CEPH_ENTITY_TYPE_MDS | CEPH_ENTITY_TYPE_OSD);
+ if (mc->init() < 0) {
+ throw std::runtime_error("init monclient");
+ }
+
+ objecter = new Objecter(g_ceph_context, messenger, mc, icp);
+ objecter->set_client_incarnation(0);
+ objecter->init();
+ messenger->add_dispatcher_tail(objecter);
+ objecter->start();
+
+ client = new ClientScaffold(messenger, mc, objecter);
+ client->init();
+ client->mount("/", myperm, true);
+ }
+ void TearDown() override {
+ if (client->is_mounted())
+ client->unmount();
+ client->shutdown();
+ objecter->shutdown();
+ mc->shutdown();
+ messenger->shutdown();
+ messenger->wait();
+
+ delete client;
+ client = nullptr;
+ delete objecter;
+ objecter = nullptr;
+ delete mc;
+ mc = nullptr;
+ delete messenger;
+ messenger = nullptr;
+ }
+protected:
+ static inline ceph::async::io_context_pool icp;
+ static inline UserPerm myperm{0,0};
+ MonClient* mc = nullptr;
+ Messenger* messenger = nullptr;
+ Objecter* objecter = nullptr;
+ ClientScaffold* client = nullptr;
+};
diff --git a/src/test/client/alternate_name.cc b/src/test/client/alternate_name.cc
new file mode 100644
index 000000000..43f428012
--- /dev/null
+++ b/src/test/client/alternate_name.cc
@@ -0,0 +1,197 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2021 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <errno.h>
+
+#include <iostream>
+#include <string>
+
+#include <fmt/format.h>
+
+#include "test/client/TestClient.h"
+
+TEST_F(TestClient, AlternateNameRemount) {
+ auto altname = std::string("foo");
+ auto dir = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ ASSERT_EQ(0, client->mkdir(dir.c_str(), 0777, myperm, altname));
+
+ client->unmount();
+ TearDown();
+ SetUp();
+ client->mount("/", myperm, true);
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(dir.c_str(), &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname);
+ }
+
+ ASSERT_EQ(0, client->rmdir(dir.c_str(), myperm));
+}
+
+
+TEST_F(TestClient, AlternateNameMkdir) {
+ auto dir = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ ASSERT_EQ(0, client->mkdir(dir.c_str(), 0777, myperm, "foo"));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(dir.c_str(), &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, "foo");
+ }
+
+ ASSERT_EQ(0, client->rmdir(dir.c_str(), myperm));
+}
+
+TEST_F(TestClient, AlternateNameLong) {
+ auto altname = std::string(4096+1024, '-');
+ auto dir = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ ASSERT_EQ(0, client->mkdir(dir.c_str(), 0777, myperm, altname));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(dir.c_str(), &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname);
+ }
+
+ ASSERT_EQ(0, client->rmdir(dir.c_str(), myperm));
+}
+
+TEST_F(TestClient, AlternateNameCreat) {
+ auto altname = std::string("foo");
+ auto file = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ int fd = client->open(file.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(file, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname);
+ }
+}
+
+TEST_F(TestClient, AlternateNameSymlink) {
+ auto altname = std::string("foo");
+ auto file = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ int fd = client->open(file.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ auto file2 = file+"2";
+ auto altname2 = altname+"2";
+ ASSERT_EQ(0, client->symlink(file.c_str(), file2.c_str(), myperm, altname2));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(file2, &wdr, myperm, false));
+ ASSERT_EQ(wdr.alternate_name, altname2);
+ ASSERT_EQ(0, client->walk(file, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname);
+ }
+}
+
+TEST_F(TestClient, AlternateNameRename) {
+ auto altname = std::string("foo");
+ auto file = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ int fd = client->open(file.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ auto file2 = file+"2";
+ auto altname2 = altname+"2";
+
+ ASSERT_EQ(0, client->rename(file.c_str(), file2.c_str(), myperm, altname2));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(file2, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname2);
+ }
+}
+
+TEST_F(TestClient, AlternateNameRenameExistMatch) {
+ auto altname = std::string("foo");
+ auto file = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ int fd = client->open(file.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ auto file2 = file+"2";
+ auto altname2 = altname+"2";
+
+ fd = client->open(file2.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname2);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ ASSERT_EQ(0, client->rename(file.c_str(), file2.c_str(), myperm, altname2));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(file2, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname2);
+ }
+}
+
+TEST_F(TestClient, AlternateNameRenameExistMisMatch) {
+ auto altname = std::string("foo");
+ auto file = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ int fd = client->open(file.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ auto file2 = file+"2";
+ auto altname2 = altname+"2";
+
+ fd = client->open(file2.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname+"mismatch");
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ ASSERT_EQ(-EINVAL, client->rename(file.c_str(), file2.c_str(), myperm, altname2));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(file2, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname+"mismatch");
+ }
+}
+
+TEST_F(TestClient, AlternateNameLink) {
+ auto altname = std::string("foo");
+ auto file = fmt::format("{}_{}", ::testing::UnitTest::GetInstance()->current_test_info()->name(), getpid());
+ int fd = client->open(file.c_str(), O_CREAT|O_WRONLY, myperm, 0777, altname);
+ ASSERT_LE(0, fd);
+ ASSERT_EQ(3, client->write(fd, "baz", 3, 0));
+ ASSERT_EQ(0, client->close(fd));
+
+ auto file2 = file+"2";
+ auto altname2 = altname+"2";
+
+ ASSERT_EQ(0, client->link(file.c_str(), file2.c_str(), myperm, altname2));
+
+ {
+ Client::walk_dentry_result wdr;
+ ASSERT_EQ(0, client->walk(file2, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname2);
+ ASSERT_EQ(0, client->walk(file, &wdr, myperm));
+ ASSERT_EQ(wdr.alternate_name, altname);
+ }
+}
diff --git a/src/test/client/iozone.sh b/src/test/client/iozone.sh
new file mode 100755
index 000000000..31e955da7
--- /dev/null
+++ b/src/test/client/iozone.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -e
+name=`echo $0 | sed 's/\//_/g'`
+mkdir $name
+cd $name
+
+iozone -c -e -s 1024M -r 16K -t 1 -F f1 -i 0 -i 1
+iozone -c -e -s 1024M -r 1M -t 1 -F f2 -i 0 -i 1
+iozone -c -e -s 10240M -r 1M -t 1 -F f3 -i 0 -i 1
+
+cd ..
diff --git a/src/test/client/kernel_untar_build.sh b/src/test/client/kernel_untar_build.sh
new file mode 100755
index 000000000..1e9409202
--- /dev/null
+++ b/src/test/client/kernel_untar_build.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+set -e
+name=`echo $0 | sed 's/\//_/g'`
+mkdir $name
+cd $name
+
+tar jxvf /root/linux*
+cd linux*
+make defconfig
+make
+cd ..
+rm -r linux*
diff --git a/src/test/client/main.cc b/src/test/client/main.cc
new file mode 100644
index 000000000..dcd48acbb
--- /dev/null
+++ b/src/test/client/main.cc
@@ -0,0 +1,28 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ * Copyright (C) 2016 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "gtest/gtest.h"
+
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include "global/global_context.h"
+
+int main(int argc, char **argv)
+{
+ auto args = argv_to_vec(argc, argv);
+ [[maybe_unused]] auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/src/test/client/ops.cc b/src/test/client/ops.cc
new file mode 100644
index 000000000..e6e25135e
--- /dev/null
+++ b/src/test/client/ops.cc
@@ -0,0 +1,45 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2022 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <iostream>
+#include <errno.h>
+#include "TestClient.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-more-matchers.h"
+
+TEST_F(TestClient, CheckDummyOP) {
+ ASSERT_EQ(client->check_dummy_op(myperm), -EOPNOTSUPP);
+}
+
+TEST_F(TestClient, CheckUnknownSessionOp) {
+ ASSERT_EQ(client->send_unknown_session_op(-1), 0);
+ sleep(5);
+ ASSERT_EQ(client->check_client_blocklisted(), true);
+}
+
+TEST_F(TestClient, CheckZeroReclaimFlag) {
+ ASSERT_EQ(client->check_unknown_reclaim_flag(0), true);
+}
+TEST_F(TestClient, CheckUnknownReclaimFlag) {
+ ASSERT_EQ(client->check_unknown_reclaim_flag(2), true);
+}
+TEST_F(TestClient, CheckNegativeReclaimFlagUnmasked) {
+ ASSERT_EQ(client->check_unknown_reclaim_flag(-1 & ~MClientReclaim::FLAG_FINISH), true);
+}
+TEST_F(TestClient, CheckNegativeReclaimFlag) {
+ ASSERT_EQ(client->check_unknown_reclaim_flag(-1), true);
+}