12851c541SNicolas Bonnefon /* 22851c541SNicolas Bonnefon * Copyright (C) 2009, 2010 Nicolas Bonnefon and other contributors 32851c541SNicolas Bonnefon * 42851c541SNicolas Bonnefon * This file is part of glogg. 52851c541SNicolas Bonnefon * 62851c541SNicolas Bonnefon * glogg is free software: you can redistribute it and/or modify 72851c541SNicolas Bonnefon * it under the terms of the GNU General Public License as published by 82851c541SNicolas Bonnefon * the Free Software Foundation, either version 3 of the License, or 92851c541SNicolas Bonnefon * (at your option) any later version. 102851c541SNicolas Bonnefon * 112851c541SNicolas Bonnefon * glogg is distributed in the hope that it will be useful, 122851c541SNicolas Bonnefon * but WITHOUT ANY WARRANTY; without even the implied warranty of 132851c541SNicolas Bonnefon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 142851c541SNicolas Bonnefon * GNU General Public License for more details. 152851c541SNicolas Bonnefon * 162851c541SNicolas Bonnefon * You should have received a copy of the GNU General Public License 172851c541SNicolas Bonnefon * along with glogg. If not, see <http://www.gnu.org/licenses/>. 182851c541SNicolas Bonnefon */ 192851c541SNicolas Bonnefon 20f35c72b9SNicolas Bonnefon #include <QSignalSpy> 21f35c72b9SNicolas Bonnefon #include <QMutexLocker> 22f35c72b9SNicolas Bonnefon #include <QFile> 23f35c72b9SNicolas Bonnefon 24f35c72b9SNicolas Bonnefon #include "testlogfiltereddata.h" 25f35c72b9SNicolas Bonnefon #include "logdata.h" 2620ec540aSNicolas Bonnefon #include "logfiltereddata.h" 27f35c72b9SNicolas Bonnefon 28f35c72b9SNicolas Bonnefon #if QT_VERSION < 0x040500 29f35c72b9SNicolas Bonnefon #define QBENCHMARK 30f35c72b9SNicolas Bonnefon #endif 31f35c72b9SNicolas Bonnefon 32f35c72b9SNicolas Bonnefon #if !defined( TMPDIR ) 33f35c72b9SNicolas Bonnefon #define TMPDIR "/tmp" 34f35c72b9SNicolas Bonnefon #endif 35f35c72b9SNicolas Bonnefon 365f0a91faSNicolas Bonnefon static const qint64 ML_NB_LINES = 15000LL; 375fc7617dSNicolas Bonnefon static const char* ml_format="LOGDATA is a part of glogg, we are going to test it thoroughly, this is line\t\t%06d\n"; 385fc7617dSNicolas Bonnefon static const int ML_VISIBLE_LINE_LENGTH = (76+8+4+6); // Without the final '\n' ! 39f35c72b9SNicolas Bonnefon 405f0a91faSNicolas Bonnefon static const qint64 SL_NB_LINES = 2000LL; 41f35c72b9SNicolas Bonnefon static const char* sl_format="LOGDATA is a part of glogg, we are going to test it thoroughly, this is line %06d\n"; 42f35c72b9SNicolas Bonnefon 437ab70cd2SNicolas Bonnefon static const char* partial_line_begin = "123... beginning of line."; 447ab70cd2SNicolas Bonnefon static const char* partial_line_end = " end of line 123.\n"; 457ab70cd2SNicolas Bonnefon 467ab70cd2SNicolas Bonnefon static const char* partial_nonmatching_line_begin = "Beginning of line."; 477ab70cd2SNicolas Bonnefon 48f35c72b9SNicolas Bonnefon void TestLogFilteredData::initTestCase() 49f35c72b9SNicolas Bonnefon { 50f35c72b9SNicolas Bonnefon QVERIFY( generateDataFiles() ); 51f35c72b9SNicolas Bonnefon } 52f35c72b9SNicolas Bonnefon 53f35c72b9SNicolas Bonnefon void TestLogFilteredData::simpleSearch() 54f35c72b9SNicolas Bonnefon { 55f35c72b9SNicolas Bonnefon LogData logData; 56f35c72b9SNicolas Bonnefon 57f35c72b9SNicolas Bonnefon // First load the tests file 58f35c72b9SNicolas Bonnefon // Register for notification file is loaded 593ab7c5b5SNicolas Bonnefon connect( &logData, SIGNAL( loadingFinished( bool ) ), 60f35c72b9SNicolas Bonnefon this, SLOT( loadingFinished() ) ); 61f35c72b9SNicolas Bonnefon 625f0a91faSNicolas Bonnefon logData.attachFile( TMPDIR "/mediumlog.txt" ); 63f35c72b9SNicolas Bonnefon // Wait for the loading to be done 64f35c72b9SNicolas Bonnefon { 65f35c72b9SNicolas Bonnefon QApplication::exec(); 66f35c72b9SNicolas Bonnefon } 67f35c72b9SNicolas Bonnefon 68f35c72b9SNicolas Bonnefon QCOMPARE( logData.getNbLine(), ML_NB_LINES ); 69f35c72b9SNicolas Bonnefon 70f35c72b9SNicolas Bonnefon // Now perform a simple search 71f35c72b9SNicolas Bonnefon LogFilteredData* filteredData = logData.getNewFilteredData(); 72f35c72b9SNicolas Bonnefon connect( filteredData, SIGNAL( searchProgressed( int, int ) ), 73f35c72b9SNicolas Bonnefon this, SLOT( searchProgressed( int, int ) ) ); 74f35c72b9SNicolas Bonnefon 75f35c72b9SNicolas Bonnefon QSignalSpy progressSpy( filteredData, SIGNAL( searchProgressed( int, int ) ) ); 76f35c72b9SNicolas Bonnefon 775f0a91faSNicolas Bonnefon qint64 matches[] = { 0, 15, 20, 135 }; 780ed63e59SNicolas Bonnefon QBENCHMARK { 79f35c72b9SNicolas Bonnefon // Start the search 80f35c72b9SNicolas Bonnefon filteredData->runSearch( QRegExp( "123" ) ); 81f35c72b9SNicolas Bonnefon 82f35c72b9SNicolas Bonnefon // And check we receive data in 4 chunks (the first being empty) 83f35c72b9SNicolas Bonnefon for ( int i = 0; i < 4; i++ ) { 84f35c72b9SNicolas Bonnefon QApplication::exec(); 85f35c72b9SNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), matches[i] ); 86f35c72b9SNicolas Bonnefon } 870ed63e59SNicolas Bonnefon } 880ed63e59SNicolas Bonnefon 890ed63e59SNicolas Bonnefon QCOMPARE( progressSpy.count(), 4 ); 90f35c72b9SNicolas Bonnefon 91f35c72b9SNicolas Bonnefon // Check the search 9246291021SNicolas Bonnefon QCOMPARE( filteredData->isLineInMatchingList( 123 ), true ); 9346291021SNicolas Bonnefon QCOMPARE( filteredData->isLineInMatchingList( 124 ), false ); 945fc7617dSNicolas Bonnefon QCOMPARE( filteredData->getMaxLength(), ML_VISIBLE_LINE_LENGTH ); 955fc7617dSNicolas Bonnefon QCOMPARE( filteredData->getLineLength( 12 ), ML_VISIBLE_LINE_LENGTH ); 965fc7617dSNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), 135LL ); 97f35c72b9SNicolas Bonnefon // Line beyond limit 98f35c72b9SNicolas Bonnefon QCOMPARE( filteredData->isLineInMatchingList( 60000 ), false ); 995f0a91faSNicolas Bonnefon QCOMPARE( filteredData->getMatchingLineNumber( 0 ), 123LL ); 100f35c72b9SNicolas Bonnefon 1010ed63e59SNicolas Bonnefon // Now let's try interrupting a search 1020ed63e59SNicolas Bonnefon filteredData->runSearch( QRegExp( "123" ) ); 1030ed63e59SNicolas Bonnefon // ... wait for two chunks. 1040ed63e59SNicolas Bonnefon QApplication::exec(); 1050ed63e59SNicolas Bonnefon QApplication::exec(); 1060ed63e59SNicolas Bonnefon // and interrupt! 1070ed63e59SNicolas Bonnefon filteredData->interruptSearch(); 1080ed63e59SNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), matches[1] ); 1090ed63e59SNicolas Bonnefon QApplication::exec(); 1100ed63e59SNicolas Bonnefon // After interrupt: should be 100% and the same number of matches 111d0d26f4fSNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), matches[2] ); 1120ed63e59SNicolas Bonnefon 1130ed63e59SNicolas Bonnefon // (because there is no guarantee when the search is 1140ed63e59SNicolas Bonnefon // interrupted, we are not sure how many chunk of result 1150ed63e59SNicolas Bonnefon // we will get.) 1160ed63e59SNicolas Bonnefon 117f35c72b9SNicolas Bonnefon // Disconnect all signals 118f35c72b9SNicolas Bonnefon disconnect( &logData, 0 ); 119f35c72b9SNicolas Bonnefon 120f35c72b9SNicolas Bonnefon // Destroy the filtered data 121f35c72b9SNicolas Bonnefon delete filteredData; 122f35c72b9SNicolas Bonnefon } 123f35c72b9SNicolas Bonnefon 124f35c72b9SNicolas Bonnefon void TestLogFilteredData::multipleSearch() 125f35c72b9SNicolas Bonnefon { 126f35c72b9SNicolas Bonnefon LogData logData; 127f35c72b9SNicolas Bonnefon 128f35c72b9SNicolas Bonnefon // First load the tests file 129f35c72b9SNicolas Bonnefon // Register for notification file is loaded 1303ab7c5b5SNicolas Bonnefon connect( &logData, SIGNAL( loadingFinished( bool ) ), 131f35c72b9SNicolas Bonnefon this, SLOT( loadingFinished() ) ); 132f35c72b9SNicolas Bonnefon 1335f0a91faSNicolas Bonnefon logData.attachFile( TMPDIR "/smalllog.txt" ); 134f35c72b9SNicolas Bonnefon // Wait for the loading to be done 135f35c72b9SNicolas Bonnefon { 136f35c72b9SNicolas Bonnefon QApplication::exec(); 137f35c72b9SNicolas Bonnefon } 138f35c72b9SNicolas Bonnefon 139f35c72b9SNicolas Bonnefon QCOMPARE( logData.getNbLine(), SL_NB_LINES ); 140f35c72b9SNicolas Bonnefon 1410ed63e59SNicolas Bonnefon // Performs two searches in a row 142f35c72b9SNicolas Bonnefon LogFilteredData* filteredData = logData.getNewFilteredData(); 143f35c72b9SNicolas Bonnefon connect( filteredData, SIGNAL( searchProgressed( int, int ) ), 144f35c72b9SNicolas Bonnefon this, SLOT( searchProgressed( int, int ) ) ); 145f35c72b9SNicolas Bonnefon 1460ed63e59SNicolas Bonnefon QSignalSpy progressSpy( filteredData, 1470ed63e59SNicolas Bonnefon SIGNAL( searchProgressed( int, int ) ) ); 148f35c72b9SNicolas Bonnefon 149f35c72b9SNicolas Bonnefon // Start the search, and immediately another one 1500ed63e59SNicolas Bonnefon // (the second call should block until the first search is done) 151f35c72b9SNicolas Bonnefon filteredData->runSearch( QRegExp( "1234" ) ); 1520ed63e59SNicolas Bonnefon filteredData->runSearch( QRegExp( "123" ) ); 153f35c72b9SNicolas Bonnefon 1540ed63e59SNicolas Bonnefon for ( int i = 0; i < 3; i++ ) 155f35c72b9SNicolas Bonnefon QApplication::exec(); 156f35c72b9SNicolas Bonnefon 157f35c72b9SNicolas Bonnefon // We should have the result for the 2nd search 1585f0a91faSNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), 12LL ); 159f35c72b9SNicolas Bonnefon 1600ed63e59SNicolas Bonnefon QCOMPARE( progressSpy.count(), 4 ); 1610ed63e59SNicolas Bonnefon 1620ed63e59SNicolas Bonnefon // Now a tricky one: we run a search and immediately attach a new file 1630ed63e59SNicolas Bonnefon filteredData->runSearch( QRegExp( "123" ) ); 1640ed63e59SNicolas Bonnefon QApplication::exec(); 1650ed63e59SNicolas Bonnefon logData.attachFile( TMPDIR "/mediumlog.txt" ); 1660ed63e59SNicolas Bonnefon 1670ed63e59SNicolas Bonnefon // We don't expect meaningful results but it should not crash! 16846291021SNicolas Bonnefon for ( int i = 0; i < 2; i++ ) 1690ed63e59SNicolas Bonnefon QApplication::exec(); 1700ed63e59SNicolas Bonnefon 171f35c72b9SNicolas Bonnefon // Disconnect all signals 172f35c72b9SNicolas Bonnefon disconnect( &logData, 0 ); 173f35c72b9SNicolas Bonnefon 174f35c72b9SNicolas Bonnefon // Destroy the filtered data 175f35c72b9SNicolas Bonnefon delete filteredData; 176f35c72b9SNicolas Bonnefon } 177f35c72b9SNicolas Bonnefon 178ba40a297SNicolas Bonnefon void TestLogFilteredData::updateSearch() 179ba40a297SNicolas Bonnefon { 180ba40a297SNicolas Bonnefon LogData logData; 181ba40a297SNicolas Bonnefon 182ba40a297SNicolas Bonnefon // First load the tests file 183ba40a297SNicolas Bonnefon // Register for notification file is loaded 184ba40a297SNicolas Bonnefon connect( &logData, SIGNAL( loadingFinished( bool ) ), 185ba40a297SNicolas Bonnefon this, SLOT( loadingFinished() ) ); 186ba40a297SNicolas Bonnefon 187ba40a297SNicolas Bonnefon logData.attachFile( TMPDIR "/smalllog.txt" ); 188ba40a297SNicolas Bonnefon // Wait for the loading to be done 189ba40a297SNicolas Bonnefon { 190ba40a297SNicolas Bonnefon QApplication::exec(); 191ba40a297SNicolas Bonnefon } 192ba40a297SNicolas Bonnefon 193ba40a297SNicolas Bonnefon QCOMPARE( logData.getNbLine(), SL_NB_LINES ); 194ba40a297SNicolas Bonnefon 1955db60fd3SNicolas Bonnefon // Perform a first search 196ba40a297SNicolas Bonnefon LogFilteredData* filteredData = logData.getNewFilteredData(); 197ba40a297SNicolas Bonnefon connect( filteredData, SIGNAL( searchProgressed( int, int ) ), 198ba40a297SNicolas Bonnefon this, SLOT( searchProgressed( int, int ) ) ); 199ba40a297SNicolas Bonnefon 200ba40a297SNicolas Bonnefon QSignalSpy progressSpy( filteredData, 201ba40a297SNicolas Bonnefon SIGNAL( searchProgressed( int, int ) ) ); 202ba40a297SNicolas Bonnefon 203ba40a297SNicolas Bonnefon // Start a search 204ba40a297SNicolas Bonnefon filteredData->runSearch( QRegExp( "123" ) ); 205ba40a297SNicolas Bonnefon 206ba40a297SNicolas Bonnefon for ( int i = 0; i < 2; i++ ) 207ba40a297SNicolas Bonnefon QApplication::exec(); 208ba40a297SNicolas Bonnefon 209ba40a297SNicolas Bonnefon // Check the result 210ba40a297SNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), 12LL ); 211ba40a297SNicolas Bonnefon QCOMPARE( progressSpy.count(), 2 ); 212ba40a297SNicolas Bonnefon 213*7d862d7eSNicolas Bonnefon QWARN("Starting stage 2"); 214*7d862d7eSNicolas Bonnefon 215ba40a297SNicolas Bonnefon // Add some data to the file 216ba40a297SNicolas Bonnefon char newLine[90]; 217ba40a297SNicolas Bonnefon QFile file( TMPDIR "/smalllog.txt" ); 218ba40a297SNicolas Bonnefon if ( file.open( QIODevice::Append ) ) { 219ba40a297SNicolas Bonnefon for (int i = 0; i < 3000; i++) { 220ba40a297SNicolas Bonnefon snprintf(newLine, 89, sl_format, i); 221ba40a297SNicolas Bonnefon file.write( newLine, qstrlen(newLine) ); 222ba40a297SNicolas Bonnefon } 2237ab70cd2SNicolas Bonnefon // To test the edge case when the final line is not complete and matching 2247ab70cd2SNicolas Bonnefon file.write( partial_line_begin, qstrlen( partial_line_begin ) ); 225ba40a297SNicolas Bonnefon } 226ba40a297SNicolas Bonnefon file.close(); 227ba40a297SNicolas Bonnefon 2285db60fd3SNicolas Bonnefon // Let the system do the update 2295db60fd3SNicolas Bonnefon QApplication::exec(); 2305db60fd3SNicolas Bonnefon 231ba40a297SNicolas Bonnefon // Start an update search 232ba40a297SNicolas Bonnefon filteredData->updateSearch(); 233ba40a297SNicolas Bonnefon 2345db60fd3SNicolas Bonnefon for ( int i = 0; i < 2; i++ ) 235ba40a297SNicolas Bonnefon QApplication::exec(); 236ba40a297SNicolas Bonnefon 237ba40a297SNicolas Bonnefon // Check the result 2385db60fd3SNicolas Bonnefon QCOMPARE( logData.getNbLine(), 5001LL ); 2395db60fd3SNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), 26LL ); 240ba40a297SNicolas Bonnefon QCOMPARE( progressSpy.count(), 4 ); 2417ab70cd2SNicolas Bonnefon 242*7d862d7eSNicolas Bonnefon QWARN("Starting stage 3"); 243*7d862d7eSNicolas Bonnefon 2447ab70cd2SNicolas Bonnefon // Add a couple more lines, including the end of the unfinished one. 2457ab70cd2SNicolas Bonnefon if ( file.open( QIODevice::Append ) ) { 2467ab70cd2SNicolas Bonnefon file.write( partial_line_end, qstrlen( partial_line_end ) ); 2477ab70cd2SNicolas Bonnefon for (int i = 0; i < 20; i++) { 2487ab70cd2SNicolas Bonnefon snprintf(newLine, 89, sl_format, i); 2497ab70cd2SNicolas Bonnefon file.write( newLine, qstrlen(newLine) ); 2507ab70cd2SNicolas Bonnefon } 2517ab70cd2SNicolas Bonnefon // To test the edge case when the final line is not complete and not matching 2527ab70cd2SNicolas Bonnefon file.write( partial_nonmatching_line_begin, 2537ab70cd2SNicolas Bonnefon qstrlen( partial_nonmatching_line_begin ) ); 2547ab70cd2SNicolas Bonnefon } 2557ab70cd2SNicolas Bonnefon file.close(); 2567ab70cd2SNicolas Bonnefon 2577ab70cd2SNicolas Bonnefon // Start an update search 2587ab70cd2SNicolas Bonnefon filteredData->updateSearch(); 2597ab70cd2SNicolas Bonnefon 2607ab70cd2SNicolas Bonnefon for ( int i = 0; i < 3; i++ ) 2617ab70cd2SNicolas Bonnefon QApplication::exec(); 2627ab70cd2SNicolas Bonnefon 2637ab70cd2SNicolas Bonnefon // Check the result 2647ab70cd2SNicolas Bonnefon QCOMPARE( logData.getNbLine(), 5022LL ); 2657ab70cd2SNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), 26LL ); 2667ab70cd2SNicolas Bonnefon QCOMPARE( progressSpy.count(), 6 ); 2677ab70cd2SNicolas Bonnefon 268*7d862d7eSNicolas Bonnefon QWARN("Starting stage 4"); 269*7d862d7eSNicolas Bonnefon 2707ab70cd2SNicolas Bonnefon // Now test the case where a match is found at the end of an updated line. 2717ab70cd2SNicolas Bonnefon if ( file.open( QIODevice::Append ) ) { 2727ab70cd2SNicolas Bonnefon file.write( partial_line_end, qstrlen( partial_line_end ) ); 2737ab70cd2SNicolas Bonnefon for (int i = 0; i < 20; i++) { 2747ab70cd2SNicolas Bonnefon snprintf(newLine, 89, sl_format, i); 2757ab70cd2SNicolas Bonnefon file.write( newLine, qstrlen(newLine) ); 2767ab70cd2SNicolas Bonnefon } 2777ab70cd2SNicolas Bonnefon } 2787ab70cd2SNicolas Bonnefon file.close(); 2797ab70cd2SNicolas Bonnefon 2807ab70cd2SNicolas Bonnefon // Start an update search 2817ab70cd2SNicolas Bonnefon filteredData->updateSearch(); 2827ab70cd2SNicolas Bonnefon 2837ab70cd2SNicolas Bonnefon for ( int i = 0; i < 3; i++ ) 2847ab70cd2SNicolas Bonnefon QApplication::exec(); 2857ab70cd2SNicolas Bonnefon 2867ab70cd2SNicolas Bonnefon // Check the result 2877ab70cd2SNicolas Bonnefon QCOMPARE( logData.getNbLine(), 5042LL ); 2887ab70cd2SNicolas Bonnefon QCOMPARE( filteredData->getNbLine(), 27LL ); 2897ab70cd2SNicolas Bonnefon QCOMPARE( progressSpy.count(), 8 ); 290ba40a297SNicolas Bonnefon } 291ba40a297SNicolas Bonnefon 292f35c72b9SNicolas Bonnefon // 293f35c72b9SNicolas Bonnefon // Private functions 294f35c72b9SNicolas Bonnefon // 295f35c72b9SNicolas Bonnefon void TestLogFilteredData::loadingFinished() 296f35c72b9SNicolas Bonnefon { 297f35c72b9SNicolas Bonnefon QApplication::quit(); 298f35c72b9SNicolas Bonnefon } 299f35c72b9SNicolas Bonnefon 300f35c72b9SNicolas Bonnefon void TestLogFilteredData::searchProgressed( int nbMatches, int completion ) 301f35c72b9SNicolas Bonnefon { 302f35c72b9SNicolas Bonnefon QApplication::quit(); 303f35c72b9SNicolas Bonnefon } 304f35c72b9SNicolas Bonnefon 305f35c72b9SNicolas Bonnefon bool TestLogFilteredData::generateDataFiles() 306f35c72b9SNicolas Bonnefon { 307f35c72b9SNicolas Bonnefon char newLine[90]; 308f35c72b9SNicolas Bonnefon 309f35c72b9SNicolas Bonnefon QFile file( TMPDIR "/mediumlog.txt" ); 310f35c72b9SNicolas Bonnefon if ( file.open( QIODevice::WriteOnly ) ) { 311f35c72b9SNicolas Bonnefon for (int i = 0; i < ML_NB_LINES; i++) { 312f35c72b9SNicolas Bonnefon snprintf(newLine, 89, ml_format, i); 313f35c72b9SNicolas Bonnefon file.write( newLine, qstrlen(newLine) ); 314f35c72b9SNicolas Bonnefon } 315f35c72b9SNicolas Bonnefon } 316f35c72b9SNicolas Bonnefon else { 317f35c72b9SNicolas Bonnefon return false; 318f35c72b9SNicolas Bonnefon } 319f35c72b9SNicolas Bonnefon file.close(); 320f35c72b9SNicolas Bonnefon 321f35c72b9SNicolas Bonnefon file.setFileName( TMPDIR "/smalllog.txt" ); 322f35c72b9SNicolas Bonnefon if ( file.open( QIODevice::WriteOnly ) ) { 323f35c72b9SNicolas Bonnefon for (int i = 0; i < SL_NB_LINES; i++) { 324f35c72b9SNicolas Bonnefon snprintf(newLine, 89, sl_format, i); 325f35c72b9SNicolas Bonnefon file.write( newLine, qstrlen(newLine) ); 326f35c72b9SNicolas Bonnefon } 327f35c72b9SNicolas Bonnefon } 328f35c72b9SNicolas Bonnefon else { 329f35c72b9SNicolas Bonnefon return false; 330f35c72b9SNicolas Bonnefon } 331f35c72b9SNicolas Bonnefon file.close(); 332f35c72b9SNicolas Bonnefon 333f35c72b9SNicolas Bonnefon return true; 334f35c72b9SNicolas Bonnefon } 335