1 | //===-- Unittests for ftell -----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/stdio/fclose.h" |
10 | #include "src/stdio/fopen.h" |
11 | #include "src/stdio/fread.h" |
12 | #include "src/stdio/fseek.h" |
13 | #include "src/stdio/fseeko.h" |
14 | #include "src/stdio/ftell.h" |
15 | #include "src/stdio/ftello.h" |
16 | #include "src/stdio/fwrite.h" |
17 | #include "src/stdio/setvbuf.h" |
18 | #include "test/UnitTest/Test.h" |
19 | |
20 | #include <stdio.h> |
21 | |
22 | class LlvmLibcFTellTest : public LIBC_NAMESPACE::testing::Test { |
23 | protected: |
24 | void test_with_bufmode(int bufmode) { |
25 | constexpr char FILENAME[] = "testdata/ftell.test" ; |
26 | // We will set a special buffer to the file so that we guarantee buffering. |
27 | constexpr size_t BUFFER_SIZE = 1024; |
28 | char buffer[BUFFER_SIZE]; |
29 | ::FILE *file = LIBC_NAMESPACE::fopen(name: FILENAME, mode: "w+" ); |
30 | ASSERT_FALSE(file == nullptr); |
31 | ASSERT_EQ(LIBC_NAMESPACE::setvbuf(file, buffer, bufmode, BUFFER_SIZE), 0); |
32 | |
33 | // Include few '\n' chars to test when |bufmode| is _IOLBF. |
34 | constexpr char CONTENT[] = "12\n345\n6789" ; |
35 | constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1; |
36 | ASSERT_EQ(WRITE_SIZE, LIBC_NAMESPACE::fwrite(CONTENT, 1, WRITE_SIZE, file)); |
37 | // The above write should have buffered the written data and not have |
38 | // trasferred it to the underlying stream. But, ftell operation should |
39 | // still return the correct effective offset. |
40 | ASSERT_EQ(size_t(LIBC_NAMESPACE::ftell(file)), WRITE_SIZE); |
41 | |
42 | off_t offseto = 5; |
43 | ASSERT_EQ(0, LIBC_NAMESPACE::fseeko(file, offseto, SEEK_SET)); |
44 | ASSERT_EQ(LIBC_NAMESPACE::ftello(file), offseto); |
45 | ASSERT_EQ(0, LIBC_NAMESPACE::fseeko(file, -offseto, SEEK_END)); |
46 | ASSERT_EQ(size_t(LIBC_NAMESPACE::ftello(file)), |
47 | size_t(WRITE_SIZE - offseto)); |
48 | |
49 | long offset = 5; |
50 | ASSERT_EQ(0, LIBC_NAMESPACE::fseek(file, offset, SEEK_SET)); |
51 | ASSERT_EQ(LIBC_NAMESPACE::ftell(file), offset); |
52 | ASSERT_EQ(0, LIBC_NAMESPACE::fseek(file, -offset, SEEK_END)); |
53 | ASSERT_EQ(size_t(LIBC_NAMESPACE::ftell(file)), size_t(WRITE_SIZE - offset)); |
54 | |
55 | ASSERT_EQ(0, LIBC_NAMESPACE::fseek(file, 0, SEEK_SET)); |
56 | constexpr size_t READ_SIZE = WRITE_SIZE / 2; |
57 | char data[READ_SIZE]; |
58 | // Reading a small amount will actually read out much more data and |
59 | // buffer it. But, ftell should return the correct effective offset. |
60 | ASSERT_EQ(READ_SIZE, LIBC_NAMESPACE::fread(data, 1, READ_SIZE, file)); |
61 | ASSERT_EQ(size_t(LIBC_NAMESPACE::ftell(file)), READ_SIZE); |
62 | |
63 | ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); |
64 | } |
65 | }; |
66 | |
67 | TEST_F(LlvmLibcFTellTest, TellWithFBF) { test_with_bufmode(_IOFBF); } |
68 | |
69 | TEST_F(LlvmLibcFTellTest, TellWithNBF) { test_with_bufmode(_IONBF); } |
70 | |
71 | TEST_F(LlvmLibcFTellTest, TellWithLBF) { test_with_bufmode(_IOLBF); } |
72 | |