Skip to content

Commit 8de51c8

Browse files
authored
[libcxx] [test] Add a test for the range of file offsets (#122798)
This adds a test for an issue reported downstream at mstorsjo/llvm-mingw#462; this is known to fail on Windows right now, where the fseek/ftell calls end up truncated to 32 bits. The test for this, unfortunately, requires temporarily creating a 4 GB file.
1 parent 2c75bda commit 8de51c8

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===----------------------------------------------------------------------===//
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+
// <fstream>
10+
11+
// Test that we can seek using offsets larger than 32 bit, and that we can
12+
// retrieve file offsets larger than 32 bit.
13+
14+
// On MSVC targets, we only use the 32 bit fseek/ftell functions. For MinGW
15+
// targets, we use fseeko/ftello, but the user needs to define
16+
// _FILE_OFFSET_BITS=64 to make them 64 bit.
17+
//
18+
// XFAIL: target={{.*}}-windows{{.*}}
19+
20+
// On 32 bit Android platforms, off_t is 32 bit by default. By defining
21+
// _FILE_OFFSET_BITS=64, one gets a 64 bit off_t, but the corresponding
22+
// 64 bit ftello/fseeko functions are only available since Android API 24 (7.0).
23+
// (On 64 bit Android platforms, off_t has always been 64 bit.)
24+
//
25+
// XFAIL: target={{i686|arm.*}}-{{.+}}-android{{.*}}
26+
27+
// Writing the >4 GB test file fails on 32 bit AIX.
28+
//
29+
// XFAIL: target=powerpc-{{.+}}-aix{{.*}}
30+
31+
#include <fstream>
32+
#include <iostream>
33+
#include <cassert>
34+
#include <vector>
35+
36+
#include "assert_macros.h"
37+
#include "platform_support.h"
38+
#include "test_macros.h"
39+
40+
void test_tellg(std::streamoff total_size) {
41+
std::vector<char> data(8192);
42+
for (std::size_t i = 0; i < data.size(); ++i)
43+
data[i] = static_cast<char>(i % (1 << 8 * sizeof(char)));
44+
std::string p = get_temp_file_name();
45+
{
46+
std::ofstream ofs;
47+
ofs.open(p, std::ios::out | std::ios::binary);
48+
assert(ofs.is_open());
49+
for (std::streamoff size = 0; size < total_size;) {
50+
std::size_t n = std::min(static_cast<std::streamoff>(data.size()), total_size - size);
51+
ofs.write(data.data(), n);
52+
size += n;
53+
}
54+
assert(!ofs.fail());
55+
ofs.close();
56+
}
57+
{
58+
std::ifstream ifs;
59+
ifs.open(p, std::ios::binary);
60+
assert(ifs.is_open());
61+
std::streamoff in_off = ifs.tellg();
62+
TEST_REQUIRE(in_off == 0, "in_off not zero at start");
63+
ifs.seekg(total_size - 20, std::ios::beg);
64+
in_off = ifs.tellg();
65+
TEST_REQUIRE(in_off == total_size - 20, "in_off incorrect after >32 bit seek");
66+
ifs.seekg(10, std::ios::cur);
67+
in_off = ifs.tellg();
68+
TEST_REQUIRE(in_off == total_size - 10, "in_off incorrect after incremental seek");
69+
ifs.seekg(0, std::ios::end);
70+
in_off = ifs.tellg();
71+
TEST_REQUIRE(in_off == total_size, "in_off incorrect after seek to end");
72+
}
73+
std::remove(p.c_str());
74+
}
75+
76+
int main(int, char**) {
77+
// This test assumes and requires that std::streamoff is larger than
78+
// 32 bit - this is not required in the standard itself.
79+
static_assert(sizeof(std::streamoff) > 4, "");
80+
test_tellg(0x100000042ULL);
81+
return 0;
82+
}

0 commit comments

Comments
 (0)