diff options
author | Craig Chi <craigchi@google.com> | 2020-08-14 10:17:08 -0700 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2020-09-11 13:35:25 -0700 |
commit | 1cdca36e8f4af13a1fa73ea39452cd1eaa141abd (patch) | |
tree | 31e293ed070a67be970713a15fb4981682b76cd4 | |
parent | 38c3fb66d7e6242d76aa332bf60a53ea307bab29 (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/BUILD | 2 | ||||
-rw-r--r-- | test/fuse/linux/fuse_base.cc | 10 | ||||
-rw-r--r-- | test/fuse/linux/stat_test.cc | 31 | ||||
-rw-r--r-- | test/util/BUILD | 6 | ||||
-rw-r--r-- | test/util/fuse_util.h | 67 |
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_ |