xref: /glogg/tests/testlogdata.cpp (revision b76c5bcfe27c9f94f71fe9792f7ad4e7178aa24a)
1 #include <QSignalSpy>
2 #include <QMutexLocker>
3 #include <QFile>
4 
5 #include "testlogdata.h"
6 #include "logdata.h"
7 
8 #if QT_VERSION < 0x040500
9 #define QBENCHMARK
10 #endif
11 
12 #if !defined( TMPDIR )
13 #define TMPDIR "/tmp"
14 #endif
15 
16 static const qint64 VBL_NB_LINES = 4999999LL;
17 static const int VBL_LINE_PER_PAGE = 70;
18 static const char* vbl_format="LOGDATA is a part of glogg, we are going to test it thoroughly, this is line\t\t%07d\n";
19 static const int VBL_LINE_LENGTH = (76+2+7) ; // Without the final '\n' !
20 static const int VBL_VISIBLE_LINE_LENGTH = (76+8+4+7); // Without the final '\n' !
21 
22 static const qint64 SL_NB_LINES = 5000LL;
23 static const int SL_LINE_PER_PAGE = 70;
24 static const char* sl_format="LOGDATA is a part of glogg, we are going to test it thoroughly, this is line %06d\n";
25 static const int SL_LINE_LENGTH = 83; // Without the final '\n' !
26 
27 static const char* partial_line_begin = "123... beginning of line.";
28 static const char* partial_line_end = " end of line 123.\n";
29 
30 void TestLogData::initTestCase()
31 {
32     QVERIFY( generateDataFiles() );
33 }
34 
35 void TestLogData::simpleLoad()
36 {
37     LogData logData;
38     QSignalSpy progressSpy( &logData, SIGNAL( loadingProgressed( int ) ) );
39 
40     // Register for notification file is loaded
41     connect( &logData, SIGNAL( loadingFinished( bool ) ),
42             this, SLOT( loadingFinished() ) );
43 
44     QBENCHMARK {
45         logData.attachFile( TMPDIR "/verybiglog.txt" );
46         // Wait for the loading to be done
47         {
48             QApplication::exec();
49         }
50     }
51     QCOMPARE( (qint64) progressSpy.count(), logData.getFileSize() / (5LL*1024*1024) + 2 );
52     // Blocks of 5 MiB + 1 for the start notification (0%)
53     QCOMPARE( logData.getNbLine(), VBL_NB_LINES );
54     QCOMPARE( logData.getMaxLength(), VBL_VISIBLE_LINE_LENGTH );
55     QCOMPARE( logData.getLineLength( 123 ), VBL_VISIBLE_LINE_LENGTH );
56     QCOMPARE( logData.getFileSize(), VBL_NB_LINES * (VBL_LINE_LENGTH+1LL) );
57 
58     // Disconnect all signals
59     disconnect( &logData, 0 );
60 }
61 
62 void TestLogData::multipleLoad()
63 {
64     LogData logData;
65     QSignalSpy finishedSpy( &logData, SIGNAL( loadingFinished( bool ) ) );
66 
67     // Register for notification file is loaded
68     connect( &logData, SIGNAL( loadingFinished( bool ) ),
69             this, SLOT( loadingFinished() ) );
70 
71     // Start loading the VBL
72     logData.attachFile( TMPDIR "/verybiglog.txt" );
73 
74     // Immediately interrupt the loading
75     logData.interruptLoading();
76 
77     // and wait for the signal
78     QApplication::exec();
79 
80     // Check we have an empty file
81     QCOMPARE( finishedSpy.count(), 1 );
82     // TODO: check loadingFinished arg == false
83     QCOMPARE( logData.getNbLine(), 0LL );
84     QCOMPARE( logData.getMaxLength(), 0 );
85     QCOMPARE( logData.getFileSize(), 0LL );
86 
87     // Restart the VBL
88     logData.attachFile( TMPDIR "/verybiglog.txt" );
89 
90     // Ensure the counting has started
91     {
92         QMutex mutex;
93         QWaitCondition sleep;
94         // sleep.wait( &mutex, 10 );
95     }
96 
97     // Load the SL (should block until VBL is fully indexed)
98     logData.attachFile( TMPDIR "/smalllog.txt" );
99 
100     // and wait for the 2 signals (one for each file)
101     QApplication::exec();
102     QApplication::exec();
103 
104     // Check we have the small log loaded
105     QCOMPARE( finishedSpy.count(), 3 );
106     QCOMPARE( logData.getNbLine(), SL_NB_LINES );
107     QCOMPARE( logData.getMaxLength(), SL_LINE_LENGTH );
108     QCOMPARE( logData.getFileSize(), SL_NB_LINES * (SL_LINE_LENGTH+1LL) );
109 
110     // Restart the VBL again
111     logData.attachFile( TMPDIR "/verybiglog.txt" );
112 
113     // Immediately interrupt the loading
114     logData.interruptLoading();
115 
116     // and wait for the signal
117     QApplication::exec();
118 
119     // Check the small log has been restored
120     QCOMPARE( finishedSpy.count(), 4 );
121     QCOMPARE( logData.getNbLine(), SL_NB_LINES );
122     QCOMPARE( logData.getMaxLength(), SL_LINE_LENGTH );
123     QCOMPARE( logData.getFileSize(), SL_NB_LINES * (SL_LINE_LENGTH+1LL) );
124 
125     // Disconnect all signals
126     disconnect( &logData, 0 );
127 }
128 
129 void TestLogData::changingFile()
130 {
131     char newLine[90];
132     LogData logData;
133 
134     QSignalSpy finishedSpy( &logData, SIGNAL( loadingFinished( bool ) ) );
135     QSignalSpy progressSpy( &logData, SIGNAL( loadingProgressed( int ) ) );
136     QSignalSpy changedSpy( &logData,
137             SIGNAL( fileChanged( LogData::MonitoredFileStatus ) ) );
138 
139     // Register for notification file is loaded
140     connect( &logData, SIGNAL( loadingFinished( bool ) ),
141             this, SLOT( loadingFinished() ) );
142 
143     // Generate a small file
144     QFile file( TMPDIR "/changingfile.txt" );
145     if ( file.open( QIODevice::WriteOnly ) ) {
146         for (int i = 0; i < 200; i++) {
147             snprintf(newLine, 89, sl_format, i);
148             file.write( newLine, qstrlen(newLine) );
149         }
150     }
151     file.close();
152 
153     // Start loading it
154     logData.attachFile( TMPDIR "/changingfile.txt" );
155 
156     // and wait for the signal
157     QApplication::exec();
158 
159     // Check we have the small file
160     QCOMPARE( finishedSpy.count(), 1 );
161     QCOMPARE( logData.getNbLine(), 200LL );
162     QCOMPARE( logData.getMaxLength(), SL_LINE_LENGTH );
163     QCOMPARE( logData.getFileSize(), 200 * (SL_LINE_LENGTH+1LL) );
164 
165     // Add some data to it
166     if ( file.open( QIODevice::Append ) ) {
167         for (int i = 0; i < 200; i++) {
168             snprintf(newLine, 89, sl_format, i);
169             file.write( newLine, qstrlen(newLine) );
170         }
171         // To test the edge case when the final line is not complete
172         file.write( partial_line_begin, qstrlen( partial_line_begin ) );
173     }
174     file.close();
175 
176     // and wait for the signals
177     QApplication::exec();
178 
179     // Check we have a bigger file
180     QCOMPARE( changedSpy.count(), 1 );
181     QCOMPARE( finishedSpy.count(), 2 );
182     QCOMPARE( logData.getNbLine(), 401LL );
183     QCOMPARE( logData.getMaxLength(), SL_LINE_LENGTH );
184     QCOMPARE( logData.getFileSize(), 400 * (SL_LINE_LENGTH+1LL)
185             + strlen( partial_line_begin ) );
186 
187     // Add a couple more lines, including the end of the unfinished one.
188     if ( file.open( QIODevice::Append ) ) {
189         file.write( partial_line_end, qstrlen( partial_line_end ) );
190         for (int i = 0; i < 20; i++) {
191             snprintf(newLine, 89, sl_format, i);
192             file.write( newLine, qstrlen(newLine) );
193         }
194     }
195     file.close();
196 
197     // and wait for the signals
198     QApplication::exec();
199 
200     // Check we have a bigger file
201     QCOMPARE( changedSpy.count(), 2 );
202     QCOMPARE( finishedSpy.count(), 3 );
203     QCOMPARE( logData.getNbLine(), 421LL );
204     QCOMPARE( logData.getMaxLength(), SL_LINE_LENGTH );
205     QCOMPARE( logData.getFileSize(), 420 * (SL_LINE_LENGTH+1LL)
206             + strlen( partial_line_begin ) + strlen( partial_line_end ) );
207 
208     // Truncate the file
209     QVERIFY( file.open( QIODevice::WriteOnly ) );
210     file.close();
211 
212     // and wait for the signals
213     QApplication::exec();
214 
215     // Check we have an empty file
216     QCOMPARE( changedSpy.count(), 3 );
217     QCOMPARE( finishedSpy.count(), 4 );
218     QCOMPARE( logData.getNbLine(), 0LL );
219     QCOMPARE( logData.getMaxLength(), 0 );
220     QCOMPARE( logData.getFileSize(), 0LL );
221 }
222 
223 void TestLogData::sequentialRead()
224 {
225     LogData logData;
226 
227     // Register for notification file is loaded
228     connect( &logData, SIGNAL( loadingFinished( bool ) ),
229             this, SLOT( loadingFinished() ) );
230 
231     logData.attachFile( TMPDIR "/verybiglog.txt" );
232 
233     // Wait for the loading to be done
234     {
235         QApplication::exec();
236     }
237 
238     // Read all lines sequentially
239     QString s;
240     QBENCHMARK {
241         for (int i = 0; i < VBL_NB_LINES; i++) {
242             s = logData.getLineString(i);
243         }
244     }
245     QCOMPARE( s.length(), VBL_LINE_LENGTH );
246 
247 }
248 
249 void TestLogData::sequentialReadExpanded()
250 {
251     LogData logData;
252 
253     // Register for notification file is loaded
254     connect( &logData, SIGNAL( loadingFinished( bool ) ),
255             this, SLOT( loadingFinished() ) );
256 
257     logData.attachFile( TMPDIR "/verybiglog.txt" );
258 
259     // Wait for the loading to be done
260     {
261         QApplication::exec();
262     }
263 
264     // Read all expanded lines sequentially
265     QString s;
266     QBENCHMARK {
267         for (int i = 0; i < VBL_NB_LINES; i++) {
268             s = logData.getExpandedLineString(i);
269         }
270     }
271     QCOMPARE( s.length(), VBL_VISIBLE_LINE_LENGTH );
272 }
273 
274 void TestLogData::randomPageRead()
275 {
276     LogData logData;
277 
278     // Register for notification file is loaded
279     connect( &logData, SIGNAL( loadingFinished( bool ) ),
280             this, SLOT( loadingFinished() ) );
281 
282     logData.attachFile( TMPDIR "/verybiglog.txt" );
283     // Wait for the loading to be done
284     {
285         QApplication::exec();
286     }
287 
288     QWARN("Starting random page read test");
289 
290     // Read page by page from the beginning and the end, using the QStringList
291     // function
292     QStringList list;
293     QBENCHMARK {
294         for (int page = 0; page < (VBL_NB_LINES/VBL_LINE_PER_PAGE)-1; page++)
295         {
296             list = logData.getLines( page*VBL_LINE_PER_PAGE, VBL_LINE_PER_PAGE );
297             QCOMPARE(list.count(), VBL_LINE_PER_PAGE);
298             int page_from_end = (VBL_NB_LINES/VBL_LINE_PER_PAGE) - page - 1;
299             list = logData.getLines( page_from_end*VBL_LINE_PER_PAGE, VBL_LINE_PER_PAGE );
300             QCOMPARE(list.count(), VBL_LINE_PER_PAGE);
301         }
302     }
303 
304 }
305 
306 void TestLogData::randomPageReadExpanded()
307 {
308     LogData logData;
309 
310     // Register for notification file is loaded
311     connect( &logData, SIGNAL( loadingFinished( bool ) ),
312             this, SLOT( loadingFinished() ) );
313 
314     logData.attachFile( TMPDIR "/verybiglog.txt" );
315     // Wait for the loading to be done
316     {
317         QApplication::exec();
318     }
319 
320     QWARN("Starting random page read test (expanded lines)");
321 
322     // Read page by page from the beginning and the end, using the QStringList
323     // function
324     QStringList list;
325     QBENCHMARK {
326         for (int page = 0; page < (VBL_NB_LINES/VBL_LINE_PER_PAGE)-1; page++)
327         {
328             list = logData.getExpandedLines( page*VBL_LINE_PER_PAGE, VBL_LINE_PER_PAGE );
329             QCOMPARE(list.count(), VBL_LINE_PER_PAGE);
330             int page_from_end = (VBL_NB_LINES/VBL_LINE_PER_PAGE) - page - 1;
331             list = logData.getExpandedLines( page_from_end*VBL_LINE_PER_PAGE, VBL_LINE_PER_PAGE );
332             QCOMPARE(list.count(), VBL_LINE_PER_PAGE);
333         }
334     }
335 }
336 
337 //
338 // Private functions
339 //
340 void TestLogData::loadingFinished()
341 {
342     QApplication::quit();
343 }
344 
345 bool TestLogData::generateDataFiles()
346 {
347     char newLine[90];
348 
349     QFile file( TMPDIR "/verybiglog.txt" );
350     if ( file.open( QIODevice::WriteOnly ) ) {
351         for (int i = 0; i < VBL_NB_LINES; i++) {
352             snprintf(newLine, 89, vbl_format, i);
353             file.write( newLine, qstrlen(newLine) );
354         }
355     }
356     else {
357         return false;
358     }
359     file.close();
360 
361     file.setFileName( TMPDIR "/smalllog.txt" );
362     if ( file.open( QIODevice::WriteOnly ) ) {
363         for (int i = 0; i < SL_NB_LINES; i++) {
364             snprintf(newLine, 89, sl_format, i);
365             file.write( newLine, qstrlen(newLine) );
366         }
367     }
368     else {
369         return false;
370     }
371     file.close();
372 
373     return true;
374 }
375