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