summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorCraig Chi <craigchi@google.com>2020-08-14 10:17:08 -0700
committerAndrei Vagin <avagin@gmail.com>2020-09-11 13:35:25 -0700
commit1cdca36e8f4af13a1fa73ea39452cd1eaa141abd (patch)
tree31e293ed070a67be970713a15fb4981682b76cd4
parent38c3fb66d7e6242d76aa332bf60a53ea307bab29 (diff)
Add function generating array of iovec with different FUSE structs
This commit adds a function in the newly created fuse_util library, which accepts a variable number of arguments and data structures. Fixes #3609
-rw-r--r--test/fuse/linux/BUILD2
-rw-r--r--test/fuse/linux/fuse_base.cc10
-rw-r--r--test/fuse/linux/stat_test.cc31
-rw-r--r--test/util/BUILD6
-rw-r--r--test/util/fuse_util.h67
5 files changed, 87 insertions, 29 deletions
diff --git a/test/fuse/linux/BUILD b/test/fuse/linux/BUILD
index 4871bb531..e4a614e11 100644
--- a/test/fuse/linux/BUILD
+++ b/test/fuse/linux/BUILD
@@ -12,6 +12,7 @@ cc_binary(
deps = [
gtest,
":fuse_base",
+ "//test/util:fuse_util",
"//test/util:test_main",
"//test/util:test_util",
],
@@ -24,6 +25,7 @@ cc_library(
hdrs = ["fuse_base.h"],
deps = [
gtest,
+ "//test/util:fuse_util",
"//test/util:posix_error",
"//test/util:temp_path",
"//test/util:test_util",
diff --git a/test/fuse/linux/fuse_base.cc b/test/fuse/linux/fuse_base.cc
index b1897cf88..c354e1dcb 100644
--- a/test/fuse/linux/fuse_base.cc
+++ b/test/fuse/linux/fuse_base.cc
@@ -26,6 +26,7 @@
#include "absl/strings/str_format.h"
#include "gtest/gtest.h"
+#include "test/util/fuse_util.h"
#include "test/util/posix_error.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"
@@ -137,7 +138,6 @@ PosixError FuseTest::ServerConsumeFuseInit() {
RETURN_ERROR_IF_SYSCALL_FAIL(
RetryEINTR(read)(dev_fd_, buf.data(), buf.size()));
- struct iovec iov_out[2];
struct fuse_out_header out_header = {
.len = sizeof(struct fuse_out_header) + sizeof(struct fuse_init_out),
.error = 0,
@@ -148,12 +148,10 @@ PosixError FuseTest::ServerConsumeFuseInit() {
struct fuse_init_out out_payload = {
.major = 7,
};
- iov_out[0].iov_len = sizeof(out_header);
- iov_out[0].iov_base = &out_header;
- iov_out[1].iov_len = sizeof(out_payload);
- iov_out[1].iov_base = &out_payload;
+ auto iov_out = FuseGenerateIovecs(out_header, out_payload);
- RETURN_ERROR_IF_SYSCALL_FAIL(RetryEINTR(writev)(dev_fd_, iov_out, 2));
+ RETURN_ERROR_IF_SYSCALL_FAIL(
+ RetryEINTR(writev)(dev_fd_, iov_out.data(), iov_out.size()));
return NoError();
}
diff --git a/test/fuse/linux/stat_test.cc b/test/fuse/linux/stat_test.cc
index c2e5bd1cf..9ab53f8d2 100644
--- a/test/fuse/linux/stat_test.cc
+++ b/test/fuse/linux/stat_test.cc
@@ -24,6 +24,7 @@
#include "gtest/gtest.h"
#include "test/fuse/linux/fuse_base.h"
+#include "test/util/fuse_util.h"
#include "test/util/test_util.h"
namespace gvisor {
@@ -43,16 +44,10 @@ class StatTest : public FuseTest {
TEST_F(StatTest, StatNormal) {
// Set up fixture.
- std::vector<struct iovec> iov_in(2);
- std::vector<struct iovec> iov_out(2);
mode_t expected_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
struct timespec atime = {.tv_sec = 1595436289, .tv_nsec = 134150844};
struct timespec mtime = {.tv_sec = 1595436290, .tv_nsec = 134150845};
struct timespec ctime = {.tv_sec = 1595436291, .tv_nsec = 134150846};
- struct fuse_out_header out_header = {
- .len = sizeof(struct fuse_out_header) + sizeof(struct fuse_attr_out),
- .error = 0,
- };
struct fuse_attr attr = {
.ino = 1,
.size = 512,
@@ -70,14 +65,13 @@ TEST_F(StatTest, StatNormal) {
.rdev = 12,
.blksize = 4096,
};
+ struct fuse_out_header out_header = {
+ .len = sizeof(struct fuse_out_header) + sizeof(struct fuse_attr_out),
+ };
struct fuse_attr_out out_payload = {
.attr = attr,
};
- iov_out[0].iov_len = sizeof(out_header);
- iov_out[0].iov_base = &out_header;
- iov_out[1].iov_len = sizeof(out_payload);
- iov_out[1].iov_base = &out_payload;
-
+ auto iov_out = FuseGenerateIovecs(out_header, out_payload);
SetServerResponse(FUSE_GETATTR, iov_out);
// Do integration test.
@@ -104,10 +98,7 @@ TEST_F(StatTest, StatNormal) {
// Check FUSE request.
struct fuse_in_header in_header;
struct fuse_getattr_in in_payload;
- iov_in[0].iov_len = sizeof(in_header);
- iov_in[0].iov_base = &in_header;
- iov_in[1].iov_len = sizeof(in_payload);
- iov_in[1].iov_base = &in_payload;
+ auto iov_in = FuseGenerateIovecs(in_header, in_payload);
GetServerActualRequest(iov_in);
EXPECT_EQ(in_header.opcode, FUSE_GETATTR);
@@ -117,14 +108,11 @@ TEST_F(StatTest, StatNormal) {
TEST_F(StatTest, StatNotFound) {
// Set up fixture.
- std::vector<struct iovec> iov_in(2);
- std::vector<struct iovec> iov_out(1);
struct fuse_out_header out_header = {
.len = sizeof(struct fuse_out_header),
.error = -ENOENT,
};
- iov_out[0].iov_len = sizeof(out_header);
- iov_out[0].iov_base = &out_header;
+ auto iov_out = FuseGenerateIovecs(out_header);
SetServerResponse(FUSE_GETATTR, iov_out);
// Do integration test.
@@ -135,10 +123,7 @@ TEST_F(StatTest, StatNotFound) {
// Check FUSE request.
struct fuse_in_header in_header;
struct fuse_getattr_in in_payload;
- iov_in[0].iov_len = sizeof(in_header);
- iov_in[0].iov_base = &in_header;
- iov_in[1].iov_len = sizeof(in_payload);
- iov_in[1].iov_base = &in_payload;
+ auto iov_in = FuseGenerateIovecs(in_header, in_payload);
GetServerActualRequest(iov_in);
EXPECT_EQ(in_header.opcode, FUSE_GETATTR);
diff --git a/test/util/BUILD b/test/util/BUILD
index 2a17c33ee..b0c2c2a5a 100644
--- a/test/util/BUILD
+++ b/test/util/BUILD
@@ -46,6 +46,12 @@ cc_library(
)
cc_library(
+ name = "fuse_util",
+ testonly = 1,
+ hdrs = ["fuse_util.h"],
+)
+
+cc_library(
name = "proc_util",
testonly = 1,
srcs = ["proc_util.cc"],
diff --git a/test/util/fuse_util.h b/test/util/fuse_util.h
new file mode 100644
index 000000000..5f5182b96
--- /dev/null
+++ b/test/util/fuse_util.h
@@ -0,0 +1,67 @@
+// Copyright 2020 The gVisor Authors.
+//
+// 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.
+
+#ifndef GVISOR_TEST_UTIL_FUSE_UTIL_H_
+#define GVISOR_TEST_UTIL_FUSE_UTIL_H_
+
+#include <sys/uio.h>
+
+#include <string>
+#include <vector>
+
+namespace gvisor {
+namespace testing {
+
+// The fundamental generation function with a single argument. If passed by
+// std::string or std::vector<char>, it will call specialized versions as
+// implemented below.
+template <typename T>
+std::vector<struct iovec> FuseGenerateIovecs(T &first) {
+ return {(struct iovec){.iov_base = &first, .iov_len = sizeof(first)}};
+}
+
+// If an argument is of type std::string, it must be used in read-only scenario.
+// Because we are setting up iovec, which contains the original address of a
+// data structure, we have to drop const qualification. Usually used with
+// variable-length payload data.
+template <typename T = std::string>
+std::vector<struct iovec> FuseGenerateIovecs(std::string &first) {
+ // Pad one byte for null-terminate c-string.
+ return {(struct iovec){.iov_base = const_cast<char *>(first.c_str()),
+ .iov_len = first.size() + 1}};
+}
+
+// If an argument is of type std::vector<char>, it must be used in write-only
+// scenario and the size of the variable must be greater than or equal to the
+// size of the expected data. Usually used with variable-length payload data.
+template <typename T = std::vector<char>>
+std::vector<struct iovec> FuseGenerateIovecs(std::vector<char> &first) {
+ return {(struct iovec){.iov_base = first.data(), .iov_len = first.size()}};
+}
+
+// A helper function to set up an array of iovec struct for testing purpose.
+// Use variadic class template to generalize different numbers and different
+// types of FUSE structs.
+template <typename T, typename... Types>
+std::vector<struct iovec> FuseGenerateIovecs(T &first, Types &...args) {
+ auto first_iovec = FuseGenerateIovecs(first);
+ auto iovecs = FuseGenerateIovecs(args...);
+ first_iovec.insert(std::end(first_iovec), std::begin(iovecs),
+ std::end(iovecs));
+ return first_iovec;
+}
+
+} // namespace testing
+} // namespace gvisor
+#endif // GVISOR_TEST_UTIL_FUSE_UTIL_H_