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 <cstdio>
17#include <cstdlib>
18#include <fcntl.h>
19#include <string>
20#include <unistd.h>
21#include <vector>
22#include <gtest/gtest.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <sys/xattr.h>
26#include "securec.h"
27
28using namespace testing::ext;
29using namespace std;
30
31static const char *TEST_FILE = "/data/local/tmp/test_file.txt";
32static const char *TEST_DATA = "Hello, world!";
33static const size_t TEST_LEN = strlen(TEST_DATA);
34
35class LseekApiTest : public testing::Test {
36public:
37    static void SetUpTestCase();
38    static void TearDownTestCase();
39    void SetUp();
40    void TearDown();
41private:
42};
43void LseekApiTest::SetUp()
44{
45    int fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
46    write(fd, TEST_DATA, TEST_LEN);
47    close(fd);
48}
49void LseekApiTest::TearDown()
50{
51    (void)remove(TEST_FILE);
52}
53void LseekApiTest::SetUpTestCase()
54{
55}
56void LseekApiTest::TearDownTestCase()
57{
58}
59
60/*
61 * @tc.number : SUB_KERNEL_SYSCALL_LSEEK_0100
62 * @tc.name   : LseekSetOffsetTestSuccess_0001
63 * @tc.desc   : lseek set the offset of the file test success.
64 * @tc.size   : MediumTest
65 * @tc.type   : Function
66 * @tc.level  : Level 1
67 */
68HWTEST_F(LseekApiTest, LseekSetOffsetTestSuccess_0001, Function | MediumTest | Level1)
69{
70    int fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
71    EXPECT_TRUE(fd > 0);
72
73    // file middle position test
74    off_t offset = TEST_LEN / 2;
75    off_t pos = lseek(fd, offset, SEEK_SET);
76    EXPECT_EQ(pos, offset);
77
78    // file start position test
79    offset = 0;
80    pos = lseek(fd, offset, SEEK_SET);
81    EXPECT_EQ(pos, offset);
82
83    // file end position test
84    offset = TEST_LEN;
85    pos = lseek(fd, offset, SEEK_SET);
86    EXPECT_EQ(pos, offset);
87
88    // position larger than file length test
89    offset = TEST_LEN * 2;
90    errno = 0;
91    pos = lseek(fd, offset, SEEK_SET);
92    EXPECT_EQ(pos, offset);
93
94    close(fd);
95}
96
97/*
98 * @tc.number : SUB_KERNEL_SYSCALL_LSEEK_0200
99 * @tc.name   : LseekSetNegativePositionFailed_0002
100 * @tc.desc   : lseek sets a negative position failed, errno EINVAL.
101 * @tc.size   : MediumTest
102 * @tc.type   : Function
103 * @tc.level  : Level 2
104 */
105HWTEST_F(LseekApiTest, LseekSetNegativePositionFailed_0002, Function | MediumTest | Level2)
106{
107    int fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
108    EXPECT_TRUE(fd > 0);
109
110    // -1 position test failed, errno EINVAL
111    off_t offset = -1;
112    errno = 0;
113    off_t pos = lseek(fd, offset, SEEK_SET);
114    EXPECT_EQ(pos, -1);
115    EXPECT_EQ(errno, EINVAL);
116    close(fd);
117}
118
119/*
120 * @tc.number : SUB_KERNEL_SYSCALL_LSEEK_0300
121 * @tc.name   : LseekSEEK_CURTestSuccess_0003
122 * @tc.desc   : lseek set position from current pos success.
123 * @tc.size   : MediumTest
124 * @tc.type   : Function
125 * @tc.level  : Level 1
126 */
127HWTEST_F(LseekApiTest, LseekSEEK_CURTestSuccess_0003, Function | MediumTest | Level1)
128{
129    int fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
130    EXPECT_TRUE(fd > 0);
131
132    // set pos to middle position
133    off_t start = TEST_LEN / 2;
134    off_t initPos = lseek(fd, start, SEEK_SET);
135    EXPECT_EQ(initPos, start);
136
137    // set positive pos to offset from current position
138    off_t offset = TEST_LEN / 2;
139    off_t pos = lseek(fd, offset, SEEK_CUR);
140    EXPECT_EQ(pos, initPos + offset);
141
142    // set negative pos to offset from current position
143    offset = (TEST_LEN / 2) * (-1);
144    initPos = pos;
145    pos = lseek(fd, offset, SEEK_CUR);
146    EXPECT_EQ(pos, initPos + offset);
147
148    // set positive pos to offset from current position
149    offset = TEST_LEN * 2;
150    initPos = pos;
151    pos = lseek(fd, offset, SEEK_CUR);
152    EXPECT_EQ(pos, initPos + offset);
153
154    close(fd);
155}
156
157/*
158 * @tc.number : SUB_KERNEL_SYSCALL_LSEEK_0400
159 * @tc.name   : LseekSEEK_CURNegativeTestFailed_0004
160 * @tc.desc   : lseek set negative position from current pos failed, errno EINVAL.
161 * @tc.size   : MediumTest
162 * @tc.type   : Function
163 * @tc.level  : Level 2
164 */
165HWTEST_F(LseekApiTest, LseekSEEK_CURNegativeTestFailed_0004, Function | MediumTest | Level2)
166{
167    int fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
168    EXPECT_TRUE(fd > 0);
169
170    // set negative pos to offset from current position
171    off_t offset = -1;
172    errno = 0;
173    off_t pos = lseek(fd, offset, SEEK_CUR);
174    EXPECT_EQ(pos, -1);
175    EXPECT_EQ(errno, EINVAL);
176
177    close(fd);
178}
179
180/*
181 * @tc.number : SUB_KERNEL_SYSCALL_LSEEK_0500
182 * @tc.name   : LseekSEEK_ENDTestSuccess_0005
183 * @tc.desc   : lseek use SEEK_END set the position to file end success.
184 * @tc.size   : MediumTest
185 * @tc.type   : Function
186 * @tc.level  : Level 1
187 */
188HWTEST_F(LseekApiTest, LseekSEEK_ENDTestSuccess_0005, Function | MediumTest | Level1)
189{
190    int fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
191    EXPECT_TRUE(fd > 0);
192
193    off_t pos = lseek(fd, 0, SEEK_END);
194    EXPECT_EQ(pos, TEST_LEN);
195
196    close(fd);
197}
198
199/*
200 * @tc.number : SUB_KERNEL_SYSCALL_LSEEK_0600
201 * @tc.name   : LseekInvalidFdTestFailed_0006
202 * @tc.desc   : lseek used invalid fd test failed, errno EBADF.
203 * @tc.size   : MediumTest
204 * @tc.type   : Function
205 * @tc.level  : Level 2
206 */
207HWTEST_F(LseekApiTest, LseekInvalidFdTestFailed_0006, Function | MediumTest | Level2)
208{
209    errno = 0;
210    off_t pos = lseek(-1, 0, SEEK_SET);
211    EXPECT_EQ(pos, -1);
212    EXPECT_EQ(errno, EBADF);
213}