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 <cstring> 17#include <fcntl.h> 18#include <unistd.h> 19#include <gtest/gtest.h> 20#include <sys/types.h> 21#include <sys/uio.h> 22#include "securec.h" 23 24using namespace testing::ext; 25using namespace std; 26 27class PreadvApiTest : public testing::Test { 28public: 29 static void SetUpTestCase(); 30 static void TearDownTestCase(); 31 void SetUp(); 32 void TearDown(); 33 34private: 35}; 36 37static const char* TEST_DATA = "Hello, world!"; 38static const size_t TEST_LEN = strlen(TEST_DATA); 39static const int MAX_LEN = 128; 40static const char* TEST_FILE = "/data/local/tmp/test_file.txt"; 41static const char* EMPTY_FILE = "/data/local/tmp/empty_file.txt"; 42 43void PreadvApiTest::SetUpTestCase() 44{ 45} 46 47void PreadvApiTest::TearDownTestCase() 48{ 49} 50 51void PreadvApiTest::SetUp() 52{ 53 int fd = open(TEST_FILE, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 54 write(fd, TEST_DATA, TEST_LEN); 55 close(fd); 56} 57 58void PreadvApiTest::TearDown() 59{ 60 unlink(TEST_FILE); 61} 62 63/* 64 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0100 65 * @tc.name : PreadvReadSuccess_0001 66 * @tc.desc : Test basic read functionality of preadv. 67 * @tc.size : MediumTest 68 * @tc.type : Function 69 * @tc.level : Level 1 70 */ 71HWTEST_F(PreadvApiTest, PreadvReadSuccess_0001, Function | MediumTest | Level1) 72{ 73 ssize_t size; 74 int midLen = TEST_LEN / 2; 75 char buffer[MAX_LEN] = { 0 }; 76 struct iovec iov[2] = { 77 { 78 .iov_base = buffer, 79 .iov_len = TEST_LEN, 80 }, { 81 .iov_base = &buffer[TEST_LEN], 82 .iov_len = TEST_LEN, 83 } 84 }; 85 86 int fd = open(TEST_FILE, O_RDONLY); 87 88 // preadv from file start 89 size = preadv(fd, iov, 2, 0); 90 EXPECT_EQ(size, TEST_LEN); 91 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), TEST_DATA); 92 93 // preadv from file middle 94 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); 95 size = preadv(fd, iov, 1, midLen); 96 EXPECT_EQ(size, TEST_LEN - midLen); 97 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), &TEST_DATA[midLen]); 98 99 // preadv from file end 100 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); 101 size = preadv(fd, iov, 1, TEST_LEN); 102 EXPECT_EQ(size, 0); 103 104 close(fd); 105} 106 107/* 108 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0200 109 * @tc.name : PreadvInvalidFdFailed_0002 110 * @tc.desc : Test using an invalid file descriptor with preadv. 111 * @tc.size : MediumTest 112 * @tc.type : Function 113 * @tc.level : Level 2 114 */ 115HWTEST_F(PreadvApiTest, PreadvInvalidFdFailed_0002, Function | MediumTest | Level2) 116{ 117 ssize_t size; 118 char buffer[MAX_LEN] = { 0 }; 119 struct iovec iov = { 120 .iov_base = buffer, 121 .iov_len = sizeof(buffer), 122 }; 123 errno = 0; 124 size = preadv(-1, &iov, 1, 0); 125 EXPECT_EQ(size, -1); 126 EXPECT_EQ(errno, EBADF); 127} 128 129/* 130 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0300 131 * @tc.name : PreadvReadFromEmptyFileSuccess_0003 132 * @tc.desc : Test reading from an empty file with preadv. 133 * @tc.size : MediumTest 134 * @tc.type : Function 135 * @tc.level : Level 1 136 */ 137HWTEST_F(PreadvApiTest, PreadvReadFromEmptyFileSuccess_0003, Function | MediumTest | Level1) 138{ 139 ssize_t size; 140 char buffer[MAX_LEN] = { 0 }; 141 struct iovec iov = { 142 .iov_base = buffer, 143 .iov_len = sizeof(buffer), 144 }; 145 int fd = open(EMPTY_FILE, O_CREAT | O_RDWR, 0644); 146 size = preadv(fd, &iov, 1, 0); 147 EXPECT_EQ(size, 0); 148 close(fd); 149 unlink(EMPTY_FILE); 150} 151 152/* 153 * @tc.number : SUB_KERNEL_SYSCALL_PREADV_0400 154 * @tc.name : PreadvReadContinuousSuccess_0004 155 * @tc.desc : Test reading from a file with preadv continuously. 156 * @tc.size : MediumTest 157 * @tc.type : Function 158 * @tc.level : Level 1 159 */ 160HWTEST_F(PreadvApiTest, PreadvReadContinuousSuccess_0004, Function | MediumTest | Level1) 161{ 162 ssize_t size; 163 const char *context = "this is a test file."; 164 char buffer[MAX_LEN] = { 0 }; 165 struct iovec iov[2] = { 166 { 167 .iov_base = buffer, 168 .iov_len = TEST_LEN, 169 }, { 170 .iov_base = &buffer[MAX_LEN / 2], 171 .iov_len = strlen(context), 172 } 173 }; 174 175 int fd = open(TEST_FILE, O_RDWR | O_APPEND, 0644); 176 write(fd, context, strlen(context)); 177 178 // preadv context to 2 iovec 179 size = preadv(fd, iov, 2, 0); 180 EXPECT_EQ(size, TEST_LEN + strlen(context)); 181 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), TEST_DATA); 182 EXPECT_STREQ(static_cast<char *>(iov[1].iov_base), context); 183 184 close(fd); 185} 186 187/* 188 * @tc.number : SUB_KERNEL_SYSCALL_PREADV2_0500 189 * @tc.name : Preadv2ReadSuccess_0002 190 * @tc.desc : preadv2 read file success. 191 * @tc.size : MediumTest 192 * @tc.type : Function 193 * @tc.level : Level 1 194 */ 195HWTEST_F(PreadvApiTest, Preadv2ReadSuccess_0002, Function | MediumTest | Level1) 196{ 197 ssize_t size; 198 int midLen = TEST_LEN / 2; 199 char buffer[MAX_LEN] = { 0 }; 200 struct iovec iov[2] = { 201 { 202 .iov_base = buffer, 203 .iov_len = TEST_LEN, 204 }, { 205 .iov_base = &buffer[TEST_LEN], 206 .iov_len = TEST_LEN, 207 } 208 }; 209 210 int fd = open(TEST_FILE, O_RDONLY); 211 212 // preadv from file start 213 size = preadv(fd, iov, 2, 0); 214 EXPECT_EQ(size, TEST_LEN); 215 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), TEST_DATA); 216 217 // preadv from file middle 218 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); 219 size = preadv2(fd, iov, 1, midLen, 0); 220 EXPECT_EQ(size, TEST_LEN - midLen); 221 EXPECT_STREQ(static_cast<char *>(iov[0].iov_base), &TEST_DATA[midLen]); 222 223 // preadv from file end 224 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); 225 size = preadv2(fd, iov, 1, TEST_LEN, 0); 226 EXPECT_EQ(size, 0); 227 228 close(fd); 229} 230