1/* 2 * Copyright (C) 2024 HiHope Open Source Organization. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <cerrno> 17#include <cstdio> 18#include <cstdlib> 19#include <string> 20#include <vector> 21#include <fcntl.h> 22#include <unistd.h> 23#include <arpa/inet.h> 24#include <gtest/gtest.h> 25#include <netinet/in.h> 26#include <sys/stat.h> 27#include <sys/socket.h> 28#include <sys/types.h> 29#include "securec.h" 30 31using namespace testing::ext; 32 33static const char *TEST_READ_FILE = "/data/local/tmp/splice_read_file.txt"; 34static const char *TEST_WRITE_FILE = "/data/local/tmp/splice_write_file.txt"; 35static const char *TEST_DATA = "Hello World!"; 36static const int TEST_DATA_LEN = strlen(TEST_DATA); 37static const int MAX_LEN = 128; 38 39class HatsSpliceTest : public testing::Test { 40public: 41static void SetUpTestCase(); 42static void TearDownTestCase(); 43void SetUp(); 44void TearDown(); 45private: 46}; 47void HatsSpliceTest::SetUp() 48{ 49 int fd = open(TEST_READ_FILE, O_WRONLY | O_CREAT, 0644); 50 write(fd, TEST_DATA, TEST_DATA_LEN); 51 close(fd); 52} 53void HatsSpliceTest::TearDown() 54{ 55 (void)remove(TEST_READ_FILE); 56 (void)remove(TEST_WRITE_FILE); 57} 58void HatsSpliceTest::SetUpTestCase() 59{ 60} 61void HatsSpliceTest::TearDownTestCase() 62{ 63} 64 65/* 66 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0100 67 * @tc.name : SpliceMoveFileDataToPipeSuccess_0001 68 * @tc.desc : Splice move data from file to pipe success. 69 * @tc.size : MediumTest 70 * @tc.type : Function 71 * @tc.level : Level 1 72 */ 73HWTEST_F(HatsSpliceTest, SpliceMoveFileDataToPipeSuccess_0001, Function | MediumTest | Level1) 74{ 75 int ret; 76 char buffer[MAX_LEN] = { 0 }; 77 int pipeFd[2]; 78 int fdIn = open(TEST_READ_FILE, O_RDONLY); 79 EXPECT_TRUE(fdIn > 0); 80 81 // move common fd data to pipe success. 82 ret = pipe(pipeFd); 83 EXPECT_EQ(ret, 0); 84 85 ssize_t size = splice(fdIn, nullptr, pipeFd[1], nullptr, TEST_DATA_LEN, SPLICE_F_MOVE | SPLICE_F_MORE); 86 EXPECT_EQ(size, TEST_DATA_LEN); 87 88 size = read(pipeFd[0], buffer, MAX_LEN); 89 EXPECT_EQ(size, TEST_DATA_LEN); 90 EXPECT_STREQ(buffer, TEST_DATA); 91 92 close(fdIn); 93 close(pipeFd[0]); 94 close(pipeFd[1]); 95} 96 97/* 98 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0200 99 * @tc.name : SpliceMovePipeDataToFileSuccess_0002 100 * @tc.desc : Splice move pipe data to file success. 101 * @tc.size : MediumTest 102 * @tc.type : Function 103 * @tc.level : Level 1 104 */ 105HWTEST_F(HatsSpliceTest, SpliceMoveFileDataToPipeSuccess_0002, Function | MediumTest | Level1) 106{ 107 int ret; 108 off64_t offset = 0; 109 char buffer[MAX_LEN] = { 0 }; 110 int pipeFd[2]; 111 int fdOut = open(TEST_WRITE_FILE, O_RDWR | O_CREAT, 0644); 112 EXPECT_TRUE(fdOut > 0); 113 114 // move common fd data to pipe success. 115 ret = pipe(pipeFd); 116 EXPECT_EQ(ret, 0); 117 ssize_t size = write(pipeFd[1], TEST_DATA, TEST_DATA_LEN); 118 EXPECT_EQ(size, TEST_DATA_LEN); 119 120 ret = splice(pipeFd[0], nullptr, fdOut, &offset, TEST_DATA_LEN, SPLICE_F_MOVE | SPLICE_F_MORE); 121 EXPECT_EQ(ret, TEST_DATA_LEN); 122 123 off_t pos = lseek(fdOut, 0, SEEK_SET); 124 EXPECT_EQ(pos, 0); 125 126 size = read(fdOut, buffer, MAX_LEN); 127 EXPECT_EQ(size, TEST_DATA_LEN); 128 EXPECT_STREQ(buffer, TEST_DATA); 129 130 close(fdOut); 131 close(pipeFd[0]); 132 close(pipeFd[1]); 133} 134 135/* 136 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0300 137 * @tc.name : SpliceInvalidFdFailed_0003 138 * @tc.desc : Splice was provided invalid file fd return failed, errno EBADF. 139 * @tc.size : MediumTest 140 * @tc.type : Function 141 * @tc.level : Level 2 142 */ 143HWTEST_F(HatsSpliceTest, SpliceInvalidFdFailed_0003, Function | MediumTest | Level2) 144{ 145 int ret; 146 off64_t offset = 0; 147 int pipeFd[2]; 148 149 ret = pipe(pipeFd); 150 EXPECT_EQ(ret, 0); 151 ssize_t size = write(pipeFd[1], TEST_DATA, TEST_DATA_LEN); 152 EXPECT_EQ(size, TEST_DATA_LEN); 153 154 // fdOut is invalid fd, failed 155 errno = 0; 156 ret = splice(pipeFd[0], nullptr, -1, &offset, TEST_DATA_LEN, SPLICE_F_NONBLOCK); 157 EXPECT_EQ(ret, -1); 158 EXPECT_EQ(errno, EBADF); 159 160 // fdIn is invalid fd, failed 161 errno = 0; 162 ret = splice(-1, &offset, pipeFd[1], nullptr, TEST_DATA_LEN, SPLICE_F_NONBLOCK); 163 EXPECT_EQ(ret, -1); 164 EXPECT_EQ(errno, EBADF); 165 166 close(pipeFd[0]); 167 close(pipeFd[1]); 168} 169 170/* 171 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0400 172 * @tc.name : SpliceNoPipeFdFailed_0004 173 * @tc.desc : Splice neither fds refer to a pipe return failed, errno EINVAL. 174 * @tc.size : MediumTest 175 * @tc.type : Function 176 * @tc.level : Level 2 177 */ 178HWTEST_F(HatsSpliceTest, SpliceNoPipeFdFailed_0004, Function | MediumTest | Level2) 179{ 180 int ret; 181 off64_t offset = 0; 182 int fdIn = open(TEST_READ_FILE, O_RDONLY); 183 EXPECT_TRUE(fdIn > 0); 184 int fdOut = open(TEST_WRITE_FILE, O_RDWR | O_TRUNC | O_CREAT, 0644); 185 EXPECT_TRUE(fdOut > 0); 186 errno = 0; 187 ret = splice(fdIn, &offset, fdOut, &offset, TEST_DATA_LEN, SPLICE_F_NONBLOCK); 188 EXPECT_EQ(ret, -1); 189 EXPECT_EQ(errno, EINVAL); 190 191 close(fdIn); 192 close(fdOut); 193} 194 195/* 196 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0500 197 * @tc.name : SplicePipeOffsetNotNullFailed_0005 198 * @tc.desc : Splice pipeFd offset is not nullptr return failed, errno ESPIPE. 199 * @tc.size : MediumTest 200 * @tc.type : Function 201 * @tc.level : Level 2 202 */ 203HWTEST_F(HatsSpliceTest, SplicePipeOffsetNotNullFailed_0005, Function | MediumTest | Level2) 204{ 205 int ret; 206 off64_t offset = 0; 207 int pipeFd[2]; 208 int fdIn = open(TEST_READ_FILE, O_RDONLY); 209 EXPECT_TRUE(fdIn > 0); 210 211 ret = pipe(pipeFd); 212 EXPECT_EQ(ret, 0); 213 214 errno = 0; 215 ret = splice(fdIn, nullptr, pipeFd[1], &offset, TEST_DATA_LEN, SPLICE_F_MOVE | SPLICE_F_MORE); 216 EXPECT_EQ(ret, -1); 217 EXPECT_EQ(errno, ESPIPE); 218 219 close(fdIn); 220 close(pipeFd[0]); 221 close(pipeFd[1]); 222} 223 224/* 225 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0600 226 * @tc.name : SpliceFdOpenAsAppendFailed_0006 227 * @tc.desc : Splice file fd was opened in append mode failed, errno EINVAL. 228 * @tc.size : MediumTest 229 * @tc.type : Function 230 * @tc.level : Level 2 231 */ 232HWTEST_F(HatsSpliceTest, SpliceFdOpenAsAppendFailed_0006, Function | MediumTest | Level2) 233{ 234 int ret; 235 int pipeFd[2]; 236 off64_t offset = 0; 237 238 int fd = open(TEST_WRITE_FILE, O_RDWR | O_APPEND | O_CREAT, 0644); 239 EXPECT_TRUE(fd > 0); 240 241 ret = pipe(pipeFd); 242 EXPECT_EQ(ret, 0); 243 ssize_t size = write(pipeFd[1], TEST_DATA, TEST_DATA_LEN); 244 EXPECT_EQ(size, TEST_DATA_LEN); 245 246 errno = 0; 247 ret = splice(pipeFd[0], nullptr, fd, &offset, TEST_DATA_LEN, SPLICE_F_NONBLOCK); 248 EXPECT_EQ(ret, -1); 249 EXPECT_EQ(errno, EINVAL); 250 251 close(fd); 252 close(pipeFd[0]); 253 close(pipeFd[1]); 254} 255 256/* 257 * @tc.number : SUB_KERNEL_SYSCALL_SPLICE_0700 258 * @tc.name : SpliceUseTheSamePipeFdFailed_0007 259 * @tc.desc : Splice fdIn and fdOut from the same pipe failed, errno EINVAL. 260 * @tc.size : MediumTest 261 * @tc.type : Function 262 * @tc.level : Level 2 263 */ 264HWTEST_F(HatsSpliceTest, SpliceUseTheSamePipeFdFailed_0007, Function | MediumTest | Level2) 265{ 266 int ret; 267 int pipeFd[2]; 268 269 ret = pipe(pipeFd); 270 EXPECT_EQ(ret, 0); 271 ssize_t size = write(pipeFd[1], TEST_DATA, TEST_DATA_LEN); 272 EXPECT_EQ(size, TEST_DATA_LEN); 273 274 errno = 0; 275 ret = splice(pipeFd[0], nullptr, pipeFd[1], nullptr, TEST_DATA_LEN, SPLICE_F_NONBLOCK); 276 EXPECT_EQ(ret, -1); 277 EXPECT_EQ(errno, EINVAL); 278 279 close(pipeFd[0]); 280 close(pipeFd[1]); 281}