[libcxx-commits] [libcxx] [libcxx] [test] Add a test for the range of file offsets (PR #122798)

Martin Storsjö via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jan 14 03:54:12 PST 2025


https://github.com/mstorsjo updated https://github.com/llvm/llvm-project/pull/122798

>From 8f3ed43fb7f198fcc6db80d8f6a9e13b2128f9e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Sat, 11 Jan 2025 17:04:15 +0200
Subject: [PATCH 1/5] [libcxx] [test] Add a test for the range of file offsets

This adds a test for an issue reported downstream at
https://github.com/mstorsjo/llvm-mingw/issues/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.
---
 .../ifstream.members/offset_range.pass.cpp    | 67 +++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp

diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
new file mode 100644
index 00000000000000..99675ff7e3c81b
--- /dev/null
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <fstream>
+
+// XFAIL: target={{.*}}-windows{{.*}}
+
+#include <fstream>
+#include <iostream>
+#include <cassert>
+#include <vector>
+
+#include "assert_macros.h"
+#include "platform_support.h"
+#include "test_macros.h"
+
+void test_tellg(std::streamoff total_size) {
+  std::vector<char> data(8192);
+  for (std::size_t i = 0; i < data.size(); ++i)
+    data[i] = static_cast<char>(i % (1 << 8 * sizeof(char)));
+  std::string p = get_temp_file_name();
+  {
+    std::ofstream ofs;
+    ofs.open(p, std::ios::out | std::ios::binary);
+    assert(ofs.is_open());
+    for (std::streamoff size = 0; size < total_size;) {
+      std::size_t n = std::min(static_cast<std::streamoff>(data.size()), total_size - size);
+      ofs.write(data.data(), n);
+      size += n;
+    }
+    assert(!ofs.fail());
+    ofs.close();
+  }
+  {
+    std::ifstream ifs;
+    ifs.open(p, std::ios::binary);
+    assert(ifs.is_open());
+    std::streamoff in_off = ifs.tellg();
+    TEST_REQUIRE(in_off == 0, [&] { test_eprintf("in_off = %ld\n", in_off); });
+    ifs.seekg(total_size - 20, std::ios::beg);
+    in_off = ifs.tellg();
+    TEST_REQUIRE(in_off == total_size - 20, [&] {
+      test_eprintf("ref = %zu, in_off = %ld\n", total_size - 20, in_off);
+    });
+    ifs.seekg(10, std::ios::cur);
+    in_off = ifs.tellg();
+    TEST_REQUIRE(in_off == total_size - 10, [&] {
+      test_eprintf("ref = %zu, in_off = %ld\n", total_size - 10, in_off);
+    });
+    ifs.seekg(0, std::ios::end);
+    in_off = ifs.tellg();
+    TEST_REQUIRE(in_off == total_size, [&] { test_eprintf("ref = %zu, in_off = %ld\n", total_size, in_off); });
+  }
+  std::remove(p.c_str());
+}
+
+int main(int, char**) {
+  // TODO: What if std::streamoff is only 32 bit, which may be the case on
+  // some platforms?
+  test_tellg(0x100000042ULL);
+  return 0;
+}

>From cc0bbb3e34d4887a4badd0ffa6fe327de695e7f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Tue, 14 Jan 2025 00:15:49 +0200
Subject: [PATCH 2/5] Remove the TODO comment, add a static assert.

---
 .../fstreams/ifstream.members/offset_range.pass.cpp            | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
index 99675ff7e3c81b..f88a6992473fa4 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -60,8 +60,7 @@ void test_tellg(std::streamoff total_size) {
 }
 
 int main(int, char**) {
-  // TODO: What if std::streamoff is only 32 bit, which may be the case on
-  // some platforms?
+  static_assert(sizeof(std::streamoff) > 4);
   test_tellg(0x100000042ULL);
   return 0;
 }

>From a94308168121ebdb34c29037844e6a3fff1da33a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Tue, 14 Jan 2025 00:41:22 +0200
Subject: [PATCH 3/5] Add comments about the purpose of the test, and about the
 static assert.

---
 .../fstreams/ifstream.members/offset_range.pass.cpp          | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
index f88a6992473fa4..014c267499b151 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -8,6 +8,9 @@
 
 // <fstream>
 
+// Test that we can seek using offsets larger than 32 bit, and that we can
+// retrieve file offsets larger than 32 bit.
+
 // XFAIL: target={{.*}}-windows{{.*}}
 
 #include <fstream>
@@ -60,6 +63,8 @@ void test_tellg(std::streamoff total_size) {
 }
 
 int main(int, char**) {
+  // This test assumes and requires that std::streamoff is larger than
+  // 32 bit - this is not required in the standard itself.
   static_assert(sizeof(std::streamoff) > 4);
   test_tellg(0x100000042ULL);
   return 0;

>From 4f202cea4b784160e9218e0f2473d5ccebfb50bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Tue, 14 Jan 2025 11:38:06 +0200
Subject: [PATCH 4/5] Try to fix the static_assert() for pre-C++17

---
 .../fstreams/ifstream.members/offset_range.pass.cpp             | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
index 014c267499b151..620bc1ba06401d 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -65,7 +65,7 @@ void test_tellg(std::streamoff total_size) {
 int main(int, char**) {
   // This test assumes and requires that std::streamoff is larger than
   // 32 bit - this is not required in the standard itself.
-  static_assert(sizeof(std::streamoff) > 4);
+  static_assert(sizeof(std::streamoff) > 4, "");
   test_tellg(0x100000042ULL);
   return 0;
 }

>From 1683503623b4565092151202784cec44e0f8f2bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Tue, 14 Jan 2025 13:53:15 +0200
Subject: [PATCH 5/5] Don't use lambdas in TEST_REQUIRE

The macOS C++03 test configuration disallows lambdas in C++03.
---
 .../fstreams/ifstream.members/offset_range.pass.cpp  | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
index 620bc1ba06401d..b239b7c620789f 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -44,20 +44,16 @@ void test_tellg(std::streamoff total_size) {
     ifs.open(p, std::ios::binary);
     assert(ifs.is_open());
     std::streamoff in_off = ifs.tellg();
-    TEST_REQUIRE(in_off == 0, [&] { test_eprintf("in_off = %ld\n", in_off); });
+    TEST_REQUIRE(in_off == 0, "in_off not zero at start");
     ifs.seekg(total_size - 20, std::ios::beg);
     in_off = ifs.tellg();
-    TEST_REQUIRE(in_off == total_size - 20, [&] {
-      test_eprintf("ref = %zu, in_off = %ld\n", total_size - 20, in_off);
-    });
+    TEST_REQUIRE(in_off == total_size - 20, "in_off incorrect after >32 bit seek");
     ifs.seekg(10, std::ios::cur);
     in_off = ifs.tellg();
-    TEST_REQUIRE(in_off == total_size - 10, [&] {
-      test_eprintf("ref = %zu, in_off = %ld\n", total_size - 10, in_off);
-    });
+    TEST_REQUIRE(in_off == total_size - 10, "in_off incorrect after incremental seek");
     ifs.seekg(0, std::ios::end);
     in_off = ifs.tellg();
-    TEST_REQUIRE(in_off == total_size, [&] { test_eprintf("ref = %zu, in_off = %ld\n", total_size, in_off); });
+    TEST_REQUIRE(in_off == total_size, "in_off incorrect after seek to end");
   }
   std::remove(p.c_str());
 }



More information about the libcxx-commits mailing list