55#include < vector>
66
77
8- int testByteCount ()
8+ int unittestByteCount ()
99{
1010 int errors = 0 ;
1111 unsigned int expectedByteCounts = 1 ;
@@ -124,3 +124,104 @@ int testByteCount()
124124 std::cerr << " The end.\n " ;
125125 return errors;
126126}
127+
128+ struct LargeByteCountsFixture {
129+ std::size_t fSize {0 };
130+ void resize (size_t size) {
131+ fSize = size;
132+ }
133+ void Streamer (TBuffer &b) {
134+ // Bare minimum to trigger the large byte count mechanism,
135+ // we don't care about the content of the data.
136+ if (b.IsReading ()) {
137+ b >> fSize ;
138+ b.SetBufferOffset (b.GetCurrent () - b.Buffer () + fSize );
139+ } else {
140+ b << fSize ;
141+ b.SetBufferOffset (b.GetCurrent () - b.Buffer () + fSize );
142+ }
143+ }
144+ };
145+
146+ #ifdef __ROOTCLING__
147+ #pragma link C++ class LargeByteCountsFixture-;
148+ #endif
149+
150+ int readAndCheck (const std::string &msg, TBufferFile &b, size_t expected_size)
151+ {
152+ // Same as b >> ptr;
153+ auto obj = b.ReadObjectAny (TClass::GetClass (typeid (LargeByteCountsFixture)));
154+ if (!obj) {
155+ std::cerr << msg << " : Failed to read back the object\n " ;
156+ return 1 ;
157+ } else {
158+ auto * readFixture = static_cast <LargeByteCountsFixture*>(obj);
159+ if (readFixture->fSize != expected_size ) {
160+ std::cerr << msg << " : The size of the data vectors do not match the original ones\n " ;
161+ delete readFixture;
162+ return 1 ;
163+ }
164+ delete readFixture;
165+ }
166+ return 0 ;
167+ }
168+
169+
170+ char *DoNothingAllocator (char * input, size_t , size_t )
171+ {
172+ // We 'could' check that the requested memory in under what we
173+ // preallocated.
174+ return input;
175+ }
176+
177+ int testReadWriteObjectAny ()
178+ {
179+ int errors = 0 ;
180+
181+ // TBufferFile currently reject size larger than 2GB.
182+ // SetBufferOffset does not check against the size,
183+ // so we can provide and use a larger buffer.
184+ std::vector<char > databuffer{};
185+ databuffer.reserve (8 * 1024 * 1024 * 1024ll );
186+ TBufferFile b (TBuffer::kWrite , 8 * 1024 * 1024 * 1024ll - 100 , databuffer.data (), false /* don't adopt */ , DoNothingAllocator);
187+
188+ LargeByteCountsFixture fixture;
189+ fixture.resize (100 ); // Small object, should be written with the regular byte count mechanism.
190+
191+ auto startPos = b.GetCurrent () - b.Buffer ();
192+ b.WriteObject (&fixture, false /* cacheReuse */ );
193+ b.SetReadMode ();
194+ b.SetBufferOffset (startPos);
195+
196+ errors += readAndCheck (" Small object written in regular section" , b, 100 );
197+
198+ // Large object, should be written with the large byte count mechanism
199+ b.SetWriteMode ();
200+ startPos = b.GetCurrent () - b.Buffer ();
201+ fixture.resize (1024 * 1024 * 256 ); // 1GB of data
202+ b.WriteObject (&fixture, false /* cacheReuse */ );
203+ b.SetReadMode ();
204+ b.SetBufferOffset (startPos);
205+ errors += readAndCheck (" Large object written in regular section" , b, 1024 * 1024 * 256 );
206+
207+ // Large object written in long range section, should be written with
208+ // the large byte count mechanism
209+ b.SetWriteMode ();
210+ b.SetBufferOffset (4 * 1024 * 1024 * 1024ll + 100 );
211+ startPos = b.GetCurrent () - b.Buffer ();
212+ fixture.resize (1024 * 1024 * 256 ); // 1GB of data
213+ b.WriteObject (&fixture, false /* cacheReuse */ );
214+ b.SetReadMode ();
215+ b.SetBufferOffset (startPos);
216+ errors += readAndCheck (" Large object written in long range section" , b, 1024 * 1024 * 256 );
217+
218+ return errors;
219+ }
220+
221+
222+ int testByteCount ()
223+ {
224+ int res = unittestByteCount ();
225+ res += testReadWriteObjectAny ();
226+ return res;
227+ }
0 commit comments