1 #include <iostream>
2
3 #include <QTest>
4 #include <QSignalSpy>
5
6 #include "log.h"
7 #include "test_utils.h"
8
9 #include "data/logdata.h"
10
11 #include "gmock/gmock.h"
12
13 #define TMPDIR "/tmp"
14
15 static const qint64 SL_NB_LINES = 5000LL;
16 static const int SL_LINE_PER_PAGE = 70;
17 static const char* sl_format="LOGDATA is a part of glogg, we are going to test it thoroughly, this is line %06d\n";
18 static const int SL_LINE_LENGTH = 83; // Without the final '\n' !
19
20 static const char* partial_line_begin = "123... beginning of line.";
21 static const char* partial_line_end = " end of line 123.\n";
22
23
24 class LogDataChanging : public testing::Test {
25 public:
26 };
27
TEST_F(LogDataChanging,changingFile)28 TEST_F( LogDataChanging, changingFile ) {
29 char newLine[90];
30 LogData log_data;
31
32 SafeQSignalSpy finishedSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
33 SafeQSignalSpy progressSpy( &log_data, SIGNAL( loadingProgressed( int ) ) );
34 SafeQSignalSpy changedSpy( &log_data,
35 SIGNAL( fileChanged( LogData::MonitoredFileStatus ) ) );
36
37 // Generate a small file
38 QFile file( TMPDIR "/changingfile.txt" );
39 if ( file.open( QIODevice::WriteOnly ) ) {
40 for (int i = 0; i < 200; i++) {
41 snprintf(newLine, 89, sl_format, i);
42 file.write( newLine, qstrlen(newLine) );
43 }
44 }
45 file.close();
46
47 // Start loading it
48 log_data.attachFile( TMPDIR "/changingfile.txt" );
49
50 // and wait for the signal
51 ASSERT_TRUE( finishedSpy.safeWait() );
52
53 // Check we have the small file
54 ASSERT_THAT( finishedSpy.count(), 1 );
55 ASSERT_THAT( log_data.getNbLine(), 200LL );
56 ASSERT_THAT( log_data.getMaxLength(), SL_LINE_LENGTH );
57 ASSERT_THAT( log_data.getFileSize(), 200 * (SL_LINE_LENGTH+1LL) );
58
59 // Add some data to it
60 if ( file.open( QIODevice::Append ) ) {
61 for (int i = 0; i < 200; i++) {
62 snprintf(newLine, 89, sl_format, i);
63 file.write( newLine, qstrlen(newLine) );
64 }
65 // To test the edge case when the final line is not complete
66 file.write( partial_line_begin, qstrlen( partial_line_begin ) );
67 }
68 file.close();
69
70 // and wait for the signals
71 ASSERT_TRUE( finishedSpy.wait( 1000 ) );
72
73 // Check we have a bigger file
74 ASSERT_THAT( changedSpy.count(), 1 );
75 ASSERT_THAT( finishedSpy.count(), 2 );
76 ASSERT_THAT( log_data.getNbLine(), 401LL );
77 ASSERT_THAT( log_data.getMaxLength(), SL_LINE_LENGTH );
78 ASSERT_THAT( log_data.getFileSize(), (qint64) (400 * (SL_LINE_LENGTH+1LL)
79 + strlen( partial_line_begin ) ) );
80
81 {
82 SafeQSignalSpy finishedSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
83
84 // Add a couple more lines, including the end of the unfinished one.
85 if ( file.open( QIODevice::Append ) ) {
86 file.write( partial_line_end, qstrlen( partial_line_end ) );
87 for (int i = 0; i < 20; i++) {
88 snprintf(newLine, 89, sl_format, i);
89 file.write( newLine, qstrlen(newLine) );
90 }
91 }
92 file.close();
93
94 // and wait for the signals
95 ASSERT_TRUE( finishedSpy.wait( 1000 ) );
96
97 // Check we have a bigger file
98 ASSERT_THAT( changedSpy.count(), 2 );
99 ASSERT_THAT( finishedSpy.count(), 1 );
100 ASSERT_THAT( log_data.getNbLine(), 421LL );
101 ASSERT_THAT( log_data.getMaxLength(), SL_LINE_LENGTH );
102 ASSERT_THAT( log_data.getFileSize(), (qint64) ( 420 * (SL_LINE_LENGTH+1LL)
103 + strlen( partial_line_begin ) + strlen( partial_line_end ) ) );
104 }
105
106 {
107 SafeQSignalSpy finishedSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
108
109 // Truncate the file
110 QVERIFY( file.open( QIODevice::WriteOnly ) );
111 file.close();
112
113 // and wait for the signals
114 ASSERT_TRUE( finishedSpy.safeWait() );
115
116 // Check we have an empty file
117 ASSERT_THAT( changedSpy.count(), 3 );
118 ASSERT_THAT( finishedSpy.count(), 1 );
119 ASSERT_THAT( log_data.getNbLine(), 0LL );
120 ASSERT_THAT( log_data.getMaxLength(), 0 );
121 ASSERT_THAT( log_data.getFileSize(), 0LL );
122 }
123 }
124
125 class LogDataBehaviour : public testing::Test {
126 public:
LogDataBehaviour()127 LogDataBehaviour() {
128 generateDataFiles();
129 }
130
generateDataFiles()131 bool generateDataFiles() {
132 char newLine[90];
133
134 QFile file( TMPDIR "/smalllog.txt" );
135 if ( file.open( QIODevice::WriteOnly ) ) {
136 for (int i = 0; i < SL_NB_LINES; i++) {
137 snprintf(newLine, 89, sl_format, i);
138 file.write( newLine, qstrlen(newLine) );
139 }
140 }
141 else {
142 return false;
143 }
144 file.close();
145
146 return true;
147 }
148 };
149
TEST_F(LogDataBehaviour,interruptLoadYieldsAnEmptyFile)150 TEST_F( LogDataBehaviour, interruptLoadYieldsAnEmptyFile ) {
151 LogData log_data;
152 SafeQSignalSpy endSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
153
154 // Start loading the VBL
155 log_data.attachFile( TMPDIR "/verybiglog.txt" );
156
157 // Immediately interrupt the loading
158 log_data.interruptLoading();
159
160 ASSERT_TRUE( endSpy.safeWait( 10000 ) );
161
162 // Check we have an empty file
163 ASSERT_THAT( endSpy.count(), 1 );
164 QList<QVariant> arguments = endSpy.takeFirst();
165 ASSERT_THAT( arguments.at(0).toInt(),
166 static_cast<int>( LoadingStatus::Interrupted ) );
167
168 ASSERT_THAT( log_data.getNbLine(), 0LL );
169 ASSERT_THAT( log_data.getMaxLength(), 0 );
170 ASSERT_THAT( log_data.getFileSize(), 0LL );
171 }
172
TEST_F(LogDataBehaviour,cannotBeReAttached)173 TEST_F( LogDataBehaviour, cannotBeReAttached ) {
174 LogData log_data;
175 SafeQSignalSpy endSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
176
177 log_data.attachFile( TMPDIR "/smalllog.txt" );
178 endSpy.safeWait( 10000 );
179
180 ASSERT_THROW( log_data.attachFile( TMPDIR "/verybiglog.txt" ), CantReattachErr );
181 }
182
TEST_F(LogDataBehaviour,readFunctions)183 TEST_F( LogDataBehaviour, readFunctions ) {
184 LogData log_data;
185 SafeQSignalSpy endSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
186
187 log_data.attachFile( TMPDIR "/smalllog.txt" );
188 endSpy.safeWait( 10000 );
189
190 QString ref = QString::fromUtf8( "LOGDATA is a part of glogg, we are going to test it thoroughly, this is line 000012" );
191
192 ASSERT_THAT( QString::compare( log_data.getLineString( 12 ), ref ), 0 );
193 ASSERT_THAT( QString::compare( log_data.getExpandedLineString( 12 ), ref ), 0 );
194 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 1 ), ref ), 0 );
195 ASSERT_THAT( QString::compare( log_data.getExpandedLines( 12, 2 ).at( 0 ), ref ), 0 );
196 }
197
198 class LogDataMultiByte : public testing::Test {
199 public:
LogDataMultiByte()200 LogDataMultiByte() {
201 generateDataFiles();
202 }
203
generateDataFiles()204 bool generateDataFiles() {
205 const QString text = QString::fromUtf8( u8"DOM JUAN\n\
206 ou LE FESTIN DE PIERRE\n\
207 COMÉDIE\n\
208 1665\n\
209 Molière\n\
210 \n\
211 \n\
212 Représentée pour la première fois le 15 février 1665 sur le Théâtre de la salle du Palais-Royal par la Troupe de Monsieur, frère unique du Roi.\n\
213 PERSONNAGES\n\
214 DOM JUAN, fils de Dom Louis.\n\
215 SGANARELLE, valet de Dom Juan.\n\
216 ELVIRE, femme de Dom Juan.\n\
217 GUSMAN, écuyer d'Elvire.\n\
218 DOM CARLOS, frère d'Elvire.\n\
219 DOM ALFONSE, frère d'Elvire\n\
220 DOM LOUIS, père de Dom Juan.\n" );
221
222 QFile file_utf16le( TMPDIR "/utf16le.txt" );
223 QTextCodec *codec_utf16le = QTextCodec::codecForName( "UTF16LE" );
224 if ( file_utf16le.open( QIODevice::WriteOnly ) ) {
225 file_utf16le.write( codec_utf16le->fromUnicode( text ) );
226 }
227 else {
228 return false;
229 }
230 file_utf16le.close();
231
232 QFile file_utf16be( TMPDIR "/utf16be.txt" );
233 QTextCodec *codec_utf16be = QTextCodec::codecForName( "UTF16BE" );
234 if ( file_utf16be.open( QIODevice::WriteOnly ) ) {
235 file_utf16be.write( codec_utf16be->fromUnicode( text ) );
236 }
237 else {
238 return false;
239 }
240 file_utf16be.close();
241
242 return true;
243 }
244 };
245
TEST_F(LogDataMultiByte,readUtf16LE)246 TEST_F( LogDataMultiByte, readUtf16LE ) {
247 LogData log_data;
248 SafeQSignalSpy endSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
249
250 log_data.attachFile( TMPDIR "/utf16le.txt" );
251 endSpy.safeWait( 10000 );
252
253 log_data.setDisplayEncoding( Encoding::ENCODING_UTF16LE );
254
255 ASSERT_THAT( log_data.getDetectedEncoding(), EncodingSpeculator::Encoding::UTF16LE );
256 ASSERT_THAT( QString::compare( log_data.getLineString( 3 ), QStringLiteral( "1665" ) ), 0 );
257 ASSERT_THAT( QString::compare( log_data.getExpandedLineString( 4 ), QStringLiteral( "Molière" ) ), 0 );
258 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 0 ), QStringLiteral( "ELVIRE, femme de Dom Juan." ) ), 0 );
259 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 1 ), QStringLiteral( "GUSMAN, écuyer d'Elvire." ) ), 0 );
260 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 2 ), QStringLiteral( "DOM CARLOS, frère d'Elvire." ) ), 0 );
261 ASSERT_THAT( QString::compare( log_data.getExpandedLines( 0, 3 ).at( 2 ), QStringLiteral( "COMÉDIE" ) ), 0 );
262 }
263
TEST_F(LogDataMultiByte,readUtf16BE)264 TEST_F( LogDataMultiByte, readUtf16BE ) {
265 LogData log_data;
266 SafeQSignalSpy endSpy( &log_data, SIGNAL( loadingFinished( LoadingStatus ) ) );
267
268 log_data.attachFile( TMPDIR "/utf16be.txt" );
269 endSpy.safeWait( 10000 );
270
271 log_data.setDisplayEncoding( Encoding::ENCODING_UTF16BE );
272
273 ASSERT_THAT( log_data.getDetectedEncoding(), EncodingSpeculator::Encoding::UTF16BE );
274 ASSERT_THAT( QString::compare( log_data.getLineString( 3 ), QStringLiteral( "1665" ) ), 0 );
275 ASSERT_THAT( QString::compare( log_data.getExpandedLineString( 4 ), QStringLiteral( "Molière" ) ), 0 );
276 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 0 ), QStringLiteral( "ELVIRE, femme de Dom Juan." ) ), 0 );
277 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 1 ), QStringLiteral( "GUSMAN, écuyer d'Elvire." ) ), 0 );
278 ASSERT_THAT( QString::compare( log_data.getLines( 11, 3 ).at( 2 ), QStringLiteral( "DOM CARLOS, frère d'Elvire." ) ), 0 );
279 ASSERT_THAT( QString::compare( log_data.getExpandedLines( 0, 3 ).at( 2 ), QStringLiteral( "COMÉDIE" ) ), 0 );
280 }
281