Skip to content
Bitcoin Roots

v31.1-roots.1 · Commit 9: [PATCH 09/17] fix(roots): restore audited portability and runtime behavior

src/test/streams_tests.cpp

Before: src/test/streams_tests.cpp · After: src/test/streams_tests.cpp

File metadata
index dfddc415b50e846c95e938938f03f21ad9f08b78..9e37057dc53a39b311c55690ab258f52a1ce30ae 100644

Download original patch · Release notes

Diff rows 1–72 of 72. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.

src/test/streams_tests.cpp CHANGED
@@ -14,6 +14,12 @@
14
14
 
15
15
  #include <boost/test/unit_test.hpp>
16
16
 
17
+ #include <array>
18
+ #include <cstddef>
19
+ #include <cstdio>
20
+ #include <ios>
21
+ #include <span>
22
+
17
23
  using namespace std::string_literals;
18
24
  using namespace util::hex_literals;
19
25
 
@@ -88,6 +94,60 @@ BOOST_AUTO_TEST_CASE(obfuscation_empty)
88
94
  BOOST_CHECK(non_null_obf);
89
95
  }
90
96
 
97
+ BOOST_AUTO_TEST_CASE(autofile_empty_write)
98
+ {
99
+ // Inspect the close/check obligation without letting the pre-fix destructor
100
+ // assertion abort the whole suite after an empty write marks the file dirty.
101
+ struct WriteTrackingFile : AutoFile {
102
+ using AutoFile::AutoFile;
103
+ bool WasWritten() const { return m_was_written; }
104
+ bool HasError() const { return std::ferror(m_file) != 0; }
105
+ };
106
+ const fs::path path{m_args.GetDataDirBase() / "empty_write.bin"};
107
+ for (const Obfuscation& obfuscation : {Obfuscation{}, Obfuscation{"ff00ff00ff00ff00"_hex}}) {
108
+ WriteTrackingFile file{fsbridge::fopen(path, "w+b"), obfuscation};
109
+ BOOST_REQUIRE(!file.IsNull());
110
+ BOOST_CHECK(!file.WasWritten());
111
+ file.write({});
112
+ BOOST_CHECK(!file.WasWritten());
113
+ BOOST_CHECK_EQUAL(file.tell(), 0);
114
+ BOOST_CHECK_EQUAL(file.size(), 0);
115
+ BOOST_CHECK(!file.HasError());
116
+
117
+ file << std::byte{0x2a};
118
+ BOOST_CHECK(file.WasWritten());
119
+ file.write({});
120
+ BOOST_CHECK(file.WasWritten());
121
+ BOOST_CHECK_EQUAL(file.tell(), 1);
122
+ BOOST_CHECK_EQUAL(file.size(), 1);
123
+ file.seek(0, SEEK_SET);
124
+ std::byte value;
125
+ file >> value;
126
+ BOOST_CHECK_EQUAL(value, std::byte{0x2a});
127
+ BOOST_REQUIRE_EQUAL(file.fclose(), 0);
128
+ BOOST_CHECK_EXCEPTION(file.write({}), std::ios_base::failure, HasReason{"AutoFile::write: file handle is nullptr"});
129
+
130
+ WriteTrackingFile readonly{fsbridge::fopen(path, "rb"), obfuscation};
131
+ BOOST_REQUIRE(!readonly.IsNull());
132
+ readonly >> value;
133
+ readonly.write({});
134
+ BOOST_CHECK(!readonly.WasWritten());
135
+ BOOST_CHECK_EQUAL(readonly.tell(), 1);
136
+ BOOST_CHECK_EQUAL(readonly.size(), 1);
137
+ BOOST_CHECK_EQUAL(value, std::byte{0x2a});
138
+ BOOST_REQUIRE_EQUAL(readonly.fclose(), 0);
139
+ }
140
+ }
141
+
142
+ BOOST_AUTO_TEST_CASE(autofile_empty_write_null)
143
+ {
144
+ for (const Obfuscation& obfuscation : {Obfuscation{}, Obfuscation{"ff00ff00ff00ff00"_hex}}) {
145
+ AutoFile file{nullptr, obfuscation};
146
+ BOOST_CHECK_EXCEPTION(file.write({}), std::ios_base::failure, HasReason{"AutoFile::write: file handle is nullptr"});
147
+ BOOST_CHECK(file.IsNull());
148
+ }
149
+ }
150
+
91
151
  BOOST_AUTO_TEST_CASE(xor_file)
92
152
  {
93
153
  fs::path xor_path{m_args.GetDataDirBase() / "test_xor.bin"};