aboutsummaryrefslogtreecommitdiff
path: root/src/unit
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/unit/myriad.unit385
1 files changed, 385 insertions, 0 deletions
diff --git a/src/unit/myriad.unit b/src/unit/myriad.unit
new file mode 100644
index 0000000..f7bea97
--- /dev/null
+++ b/src/unit/myriad.unit
@@ -0,0 +1,385 @@
1// vim: syntax=cpp
2/*
3 * Copyright (C) 2007-2023 Xagasoft, All rights reserved.
4 *
5 * This file is part of the libbu++ library and is released under the
6 * terms of the license contained in the file LICENSE.
7 */
8
9#include "bu/string.h"
10#include "bu/file.h"
11#include "bu/myriad.h"
12#include "bu/myriadstream.h"
13#include "bu/array.h"
14
15#include "bu/sio.h"
16#include "bu/archive.h"
17#include "bu/md5.h"
18#include "bu/unitsuite.h"
19
20#include <stdlib.h>
21
22using namespace Bu;
23
24class VerifyObject
25{
26friend Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo );
27friend Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo );
28public:
29 VerifyObject( int iUnits ) :
30 iUnits( iUnits ),
31 iBytesWritten( 0 )
32 {
33 }
34
35 virtual ~VerifyObject()
36 {
37 }
38
39 int getBytesWritten()
40 {
41 return iBytesWritten;
42 }
43
44private:
45 int iUnits;
46 mutable int iBytesWritten;
47};
48
49Bu::ArchiveBase &operator<<( Bu::ArchiveBase &ar, const VerifyObject &vo )
50{
51 Md5 sum;
52 ar << vo.iUnits;
53 vo.iBytesWritten = sizeof(int);
54 sum.addData( &vo.iUnits, sizeof(int) );
55 for( int j = 0; j < vo.iUnits; j++ )
56 {
57 int iRand = random()%128;
58// ar << iRand;
59 Bu::String sDat( iRand );
60 for( int j = 0; j < iRand; j++ )
61 sDat[j] = (char)((uint8_t)(random()%256));
62 ar << sDat;
63 sum.addData( &iRand, sizeof(int) );
64 sum.addData( sDat.getStr(), iRand );
65 vo.iBytesWritten += sizeof(long) + iRand;
66 }
67 Bu::String sRes = sum.getResult();
68 ar << sRes;
69 vo.iBytesWritten += sizeof(long) + sRes.getSize();
70 return ar;
71}
72
73Bu::ArchiveBase &operator>>( Bu::ArchiveBase &ar, VerifyObject &vo )
74{
75 Md5 sum;
76 ar >> vo.iUnits;
77 sum.addData( &vo.iUnits, sizeof(int) );
78 for( int j = 0; j < vo.iUnits; j++ )
79 {
80 int iRand;
81// ar >> iRand;
82 Bu::String sStr;
83 ar >> sStr;
84 iRand = sStr.getSize();
85 sum.addData( &iRand, sizeof(int) );
86 sum.addData( sStr.getStr(), iRand );
87 }
88 Bu::String sSum;
89 ar >> sSum;
90 unitTest( sSum == sum.getResult() );
91 int iTooMuch;
92 try
93 {
94 ar >> iTooMuch;
95 unitFailed("should have thrown an exception.");
96 }
97 catch( Bu::ExceptionBase &e )
98 {
99 }
100 return ar;
101}
102
103suite Myriad
104{
105 test setSize
106 {
107 String sFileName("myriad-XXXXXXX");
108
109 File fMyriad = tempFile( sFileName );
110 Myriad m( fMyriad, 32 );
111
112 MyriadStream ms = m.create( Myriad::ReadWrite );
113 ms.setSize( 150 );
114 ms.setPos( 145 );
115 char stuff[10];
116 unitTest( ms.read( stuff, 10 ) == 5 );
117
118 ms.setSize( 12 );
119 unitTest( ms.read( stuff, 10 ) == 0 );
120 unitTest( ms.write( "hello", 5 ) == 5 );
121 unitTest( ms.tell() == 17 );
122
123 ms.setSize( 500 );
124 unitTest( ms.tell() == 17 );
125 }
126
127 void addBlock( Stream &s, bool bAppend=true )
128 {
129 if( bAppend )
130 s.setPosEnd( 0 );
131 int iSize = (random()%1016)+8;
132 s.write( &iSize, 4 );
133 char *buf = new char[iSize-8];
134 for( int j = 0; j < iSize-8; j++ )
135 {
136 buf[j] = (j+iSize)%256;
137 }
138 if( random()%2 == 0 )
139 {
140 s.write( buf, iSize-8 );
141 }
142 else
143 {
144 for( int j = 0; j < iSize-8; )
145 {
146 int iAmnt = (random()%8)+1;
147 if( iAmnt+j > iSize-8 )
148 iAmnt = iSize-8-j;
149 iAmnt = s.write( buf+j, iAmnt );
150 j += iAmnt;
151 }
152 }
153 delete[] buf;
154 iSize = ~iSize;
155 s.write( &iSize, 4 );
156 }
157
158 void verifyBlock( Stream &s )
159 {
160 int iSize, iInv;
161 if( s.read( &iSize, 4 ) == 0 )
162 return;
163 if( iSize < 8 || iSize > 1024 )
164 throw ExceptionBase("Read bad data, %d", iSize );
165 char *buf = new char[iSize-8];
166 if( s.read( buf, iSize-8 ) < (Bu::size)iSize-8 )
167 {
168 delete[] buf;
169 throw ExceptionBase("Block failed verify (insuffient block data).");
170 }
171 for( int j = 0; j < iSize-8; j++ )
172 {
173 if( buf[j] != (char)((j+iSize)%256) )
174 {
175 char b = buf[j];
176 delete[] buf;
177 throw ExceptionBase("Block failed computed data verify "
178 "(%02X==%02X).", b, (char)((j+iSize)%256) );
179 }
180 }
181 delete[] buf;
182 if( s.read( &iInv, 4 ) < 4 )
183 throw ExceptionBase("Block failed verify (insufficient data).");
184 if( iInv != ~iSize )
185 throw ExceptionBase("Block failed inversion verify.");
186 }
187
188 void verifyStream( Stream &s )
189 {
190 s.setPos( 0 );
191 while( !s.isEos() )
192 verifyBlock( s );
193 }
194
195 test stressGrow
196 {
197 String sFileName("myriad-XXXXXXX");
198
199 File fMyriad = tempFile( sFileName );
200 Myriad m( fMyriad, 64 );
201
202 Array<int> aStreams;
203 for( int j = 0; j < 5; j++ )
204 {
205 aStreams.append( m.create( Bu::Myriad::Read ).getId() );
206 }
207
208 srandom( 512 );
209
210 for( int j = 0; j < 2500; j++ )
211 {
212 switch( random()%5 )
213 {
214 case 0:
215 aStreams.append( m.create( Bu::Myriad::Read ).getId() );
216 break;
217
218 case 1:
219 if( aStreams.getSize() > 0 )
220 {
221 int iStream = random()%aStreams.getSize();
222 {
223 MyriadStream ms = m.open( aStreams[iStream], Myriad::Read );
224 verifyStream( ms );
225 }
226 m.erase( aStreams[iStream] );
227 Array<int>::iterator i = aStreams.begin();
228 for( int k = 0; k < iStream; k++ )
229 i++;
230 aStreams.erase( i );
231 }
232 break;
233
234 default:
235 if( aStreams.getSize() == 0 )
236 {
237 aStreams.append(
238 m.create( Bu::Myriad::Read ).getId()
239 );
240 }
241 {
242 int iStream = random()%aStreams.getSize();
243 MyriadStream ms = m.open( aStreams[iStream], Myriad::ReadWrite );
244 addBlock( ms );
245 verifyStream( ms );
246 }
247 break;
248 }
249 }
250
251 for( Array<int>::iterator i = aStreams.begin(); i; i++ )
252 {
253 MyriadStream ms = m.open( *i, Myriad::Read );
254 verifyStream( ms );
255 }
256 }
257
258 test stressTruncate
259 {
260 String sFileName("myriad-XXXXXXX");
261
262 File fMyriad = tempFile( sFileName );
263 Myriad m( fMyriad, 128 );
264
265 Array<int> aStream;
266
267 for( int j = 0; j < 5; j++ )
268 {
269 aStream.append( m.create( Bu::Myriad::Read ).getId() );
270 }
271
272 srandom( 1024 );
273
274 char b;
275 for( int iter = 0; iter < 2500; iter++ )
276 {
277 for( Array<int>::iterator i = aStream.begin(); i; i++ )
278 {
279 MyriadStream ms = m.open( *i, Myriad::ReadWrite );
280 addBlock( ms, false );
281 ms.setSize( ms.tell() );
282 unitTest( ms.read( &b, 1 ) == 0 );
283 ms.setPos( 0 );
284 verifyBlock( ms );
285 unitTest( ms.read( &b, 1 ) == 0 );
286 }
287 }
288 }
289
290 test stressTruncate2
291 {
292 String sFileName("myriad-XXXXXXX");
293
294 Array<int> aStream;
295
296 setStepCount( 5*2500 + 5 );
297
298 {
299 File fMyriad = tempFile( sFileName );
300 Myriad m( fMyriad, 128 );
301
302 for( int j = 0; j < 5; j++ )
303 {
304 aStream.append( m.create( Bu::Myriad::Read ).getId() );
305 incProgress();
306 }
307 }
308
309 srandom( 1024 );
310
311 char b;
312 for( int iter = 0; iter < 2500; iter++ )
313 {
314 File fMyriad( sFileName, File::ReadWrite );
315 Myriad m( fMyriad );
316 for( Array<int>::iterator i = aStream.begin(); i; i++ )
317 {
318 MyriadStream ms = m.open( *i, Myriad::ReadWrite );
319 addBlock( ms, false );
320 ms.setSize( ms.tell() );
321 unitTest( ms.read( &b, 1 ) == 0 );
322 ms.setPos( 0 );
323 verifyBlock( ms );
324 unitTest( ms.read( &b, 1 ) == 0 );
325 incProgress();
326 }
327 }
328 }
329
330 test stressArchive
331 {
332 String sFileName("myriad-XXXXXX");
333 Array<int> aStream;
334
335 srandom( 2096 );
336
337 setStepCount( 15*250 + 15 );
338
339 {
340 File fMyriad = tempFile( sFileName );
341 Myriad m( fMyriad, 1024 );
342
343 for( int j = 0; j < 15; j++ )
344 {
345 MyriadStream ms = m.create( Myriad::Write );
346 int iStream = ms.getId();
347 aStream.append( iStream );
348 VerifyObject vo( random()%1024 );
349 {
350 Archive ar( ms, Archive::save );
351 ar << vo;
352 unitTest( ms.tell() == vo.getBytesWritten() );
353 ms.setSize( ms.tell() );
354 }
355 unitTest( m.getSize( iStream ) == vo.getBytesWritten() );
356 incProgress();
357 }
358 }
359
360 for( int iter = 0; iter < 250; iter++ )
361 {
362 File fMyriad( sFileName, File::ReadWrite );
363 Myriad m( fMyriad );
364 for( Array<int>::iterator i = aStream.begin(); i; i++ )
365 {
366 VerifyObject vo( random()%1024 );
367 {
368 MyriadStream ms = m.open( *i, Myriad::Read );
369 Archive ar( ms, Archive::load );
370 ar >> vo;
371 }
372 {
373 MyriadStream ms = m.open( *i, Myriad::WriteNew );
374 Archive ar( ms, Archive::save );
375 ar << vo;
376 unitTest( ms.tell() == vo.getBytesWritten() );
377 ms.setSize( ms.tell() );
378 }
379 unitTest( m.getSize( *i ) == vo.getBytesWritten() );
380 incProgress();
381 }
382 }
383 }
384}
385