test-compile-time-formatting.cpp 19.4 KB
Newer Older
1
2
#include <sys/types.h>
#include <dirent.h>
3

4
#include "gtest/gtest.h"
5
#include "base-test-environment.h" // All unit test files need to import this!
6
testing::Environment* base_test_env = testing::AddGlobalTestEnvironment(new BaseEnvironment);
7
8
9
10

extern "C" {
#define DBUG_PREFIX "TEST-CTF"
#include "debug.h"
Michiel Verloop's avatar
Michiel Verloop committed
11
#include "ctformatting.h"
12
#include "globals.h"
13
#include "options.h"
14
15
16
#include "memory.h"
#include "str.h"
#include "str_buffer.h"
17
18
#include "types.h"
#include "ctinfo.h"
19
20
}

21
22
23
// A function to call CTFcreateMessageContinued more conveniently during the tests
// without exposing additional API.
static str_buf *
24
CTFcreateMessageContinuedRaw (const char *continuation_header, str_buf *remaining_lines)
25
26
27
28
29
{
    str_buf *primary_header;
    str_buf *message;
    
    primary_header = SBUFcreate (0);
30
    SBUFfree (CTFcreateMessageBegin (&primary_header, continuation_header, "%s", ""));
31
32
33
34
35
36
    message = CTFcreateMessageContinued (remaining_lines);
    SBUFfree (CTFcreateMessageEnd());

    return message;
}

37
38
39
40
/************************
* CTFcreateMessageBegin *
************************/

41
TEST (CTF, testCreateMessageBeginSingleLineNoWrapping)
42
{
43
44
    global.cti_single_line = true;
    global.cti_message_length = 0; // disables line wrapping
45
46
47
48
49
    CTFinitialize ();

    str_buf *header;
    str_buf *message;
    char *format;
50
51
52

    // Ensure that we don't get a trailing enter in the base case
    header = SBUFcreate (0);
53
    fprintf (stderr, "%s\n", SBUFgetBuffer (header));
Michiel Verloop's avatar
Michiel Verloop committed
54
    #pragma GCC diagnostic ignored "-Wformat-zero-length"
55
    message = CTFcreateMessageBegin (&header, "", "");
56
    SBUFfree (CTFcreateMessageEnd ()); // Free the continuation header that CTFcreateMessageBegin allocates
Michiel Verloop's avatar
Michiel Verloop committed
57
    #pragma GCC diagnostic warning "-Wformat-zero-length"
58
59
60
    EXPECT_TRUE (SBUFisEmpty (message));
    EXPECT_TRUE (header == NULL);
    SBUFfree (message);
61
62

    // Ensure that headerless normal messages are printed correctly
63
64
65
66
67
    header = SBUFcreate (0);
    message = CTFcreateMessageBegin (&header, "", "A %s yet %s test.", "normal", "fabulous");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("A normal yet fabulous test.", SBUFgetBuffer (message));
    SBUFfree (message);
68

69
    // Ensure that multi-line messages are still printed on one line
70
71
72
73
74
    header = SBUFcreate (0);
    message = CTFcreateMessageBegin (&header, "", "A\nmessage\ncontaining%sspaces", "\nmany\n");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("A message containing many spaces", SBUFgetBuffer (message));
    SBUFfree (message);
75
76

    // Ensure that if a non-empty header is given, it is prepended to the message.
77
    header = SBUFcreate (0);
78
    SBUFprint (header, "Some header: ");
79
80
81
82
    message = CTFcreateMessageBegin (&header, "", "A %s\nmessage", "neat");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("Some header: A neat message", SBUFgetBuffer (message));
    SBUFfree (message);
83
84
85
86
87
88
}

TEST (CTF, testCreateMessageBeginMultiLineNoWrapping)
{
    global.cti_single_line = false;
    global.cti_message_length = 0; // disables line wrapping
89
    CTFinitialize ();
90
91

    str_buf *header;
92
    str_buf *message;
93
94
95

    // Ensure that we still get a newline if we give empty inputs
    header = SBUFcreate (0);
Michiel Verloop's avatar
Michiel Verloop committed
96
    #pragma GCC diagnostic ignored "-Wformat-zero-length"
97
98
    message = CTFcreateMessageBegin (&header, "", "");
    SBUFfree (CTFcreateMessageEnd ());
Michiel Verloop's avatar
Michiel Verloop committed
99
    #pragma GCC diagnostic warning "-Wformat-zero-length"
100
101
    EXPECT_STREQ ("\n", SBUFgetBuffer (message));
    SBUFfree (message);
102
103

    // Ensure that normal messages are working correctly
104
105
106
107
108
    header = SBUFcreate (0);
    message = CTFcreateMessageBegin (&header, "", "A %s test.", "normal");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("A normal test.\n", SBUFgetBuffer (message));
    SBUFfree (message);
109

110
111
    // Ensure that the primary_header is prepended only to the first line
    // and that the continuation_header is prepended to the other lines
112
113
114
115
116
117
    header = SBUFcreate (0);
    SBUFprint (header, "Interesting header: ");
    message = CTFcreateMessageBegin (&header, "  ", "A\nMultiline\nTest");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("Interesting header: A\n  Multiline\n  Test\n", SBUFgetBuffer (message));
    SBUFfree (message);
118
119
120
121
122
123
}

TEST (CTF, testCreateMessageBeginSingleLineWrapping)
{
    global.cti_single_line = true;
    global.cti_message_length = 0;
124
    CTFinitialize ();
125
    
126
127
128
    str_buf *header;
    str_buf *message_no_wrap;
    str_buf *message_wrap;
129
130
131
    char *long_message;

    // c++ complains if we use a normal character array, so we use STRcpy to allocate it on the heap
132
    long_message = STRcpy ("A pretty long message that is longer than the header and then some! "
133
134
                           "If wrapping were enabled, it would surely work on this gigantic string.");

135
    header = SBUFcreate (0);
136
    message_no_wrap = CTFcreateMessageBegin (&header, "", "%s", long_message);
137
    SBUFfree (CTFcreateMessageEnd ());
138
139
140

    global.cti_single_line = true;
    global.cti_message_length = 25;
141
    CTFinitialize ();
142
143
144

    // Ensure that line wrapping is ignored when single_line is active:
    // The output should be equal to the output from single line with wrapping explicitly disabled
145
    header = SBUFcreate (0);
146
    message_wrap = CTFcreateMessageBegin (&header, "", "%s", long_message);
147
148
149
150
151
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ (SBUFgetBuffer (message_no_wrap), SBUFgetBuffer(message_wrap));
    SBUFfree (message_no_wrap);
    SBUFfree (message_wrap);

152
153
154
155
156
157
158
    MEMfree (long_message);
}

TEST (CTF, testCreateMessageBeginMultiLineWrapping)
{
    global.cti_single_line = false;
    global.cti_message_length = 30;
159
    CTFinitialize ();
160
161

    str_buf *header;
162
    str_buf *message;
163
164
165

    // Ensure that we get a trailing enter in the base case
    header = SBUFcreate (0);
Michiel Verloop's avatar
Michiel Verloop committed
166
    #pragma GCC diagnostic ignored "-Wformat-zero-length"
167
168
    message = CTFcreateMessageBegin (&header, "", "");
    SBUFfree (CTFcreateMessageEnd ());
Michiel Verloop's avatar
Michiel Verloop committed
169
    #pragma GCC diagnostic warning "-Wformat-zero-length"
170
171
    EXPECT_STREQ ("\n", SBUFgetBuffer (message));
    SBUFfree (message);
172
173

    // Ensure that message shorter than the message length aren't wrapped.
174
    header = SBUFcreate (0);
175
    SBUFprint (header, "Header: ");
176
177
178
179
    message = CTFcreateMessageBegin (&header, "", "A %s.", "string");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("Header: A string.\n", SBUFgetBuffer (message));
    SBUFfree (message);
180
181

    // Ensure that messages longer than the message length without any wrapping locations aren't wrapped.
182
183
184
185
186
    header = SBUFcreate (0);
    message = CTFcreateMessageBegin (&header, "", "0123456789012345678901234567890123456789");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("0123456789012345678901234567890123456789\n", SBUFgetBuffer (message));
    SBUFfree (message);
187
188
189

    // Ensure that messages longer than the message length with a valid wrapping location
    // are wrappped at the last possible location.
190
191
192
193
194
    header = SBUFcreate (0);
    message = CTFcreateMessageBegin (&header, "", " 123456789 123456789 123456789  23456789");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ (" 123456789 123456789 123456789\n 23456789\n", SBUFgetBuffer (message));
    SBUFfree (message);
195
196

    // Ensure that tabs are converted to spaces and potentially used for wrapping
197
198
199
200
201
    header = SBUFcreate (0);
    message = CTFcreateMessageBegin (&header, "", "\t123456789\t123456789\t123456789\t123456789");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ (" 123456789 123456789 123456789\n123456789\n", SBUFgetBuffer (message));
    SBUFfree (message);
202
203

    // Ensure that wrapping takes into account non-empty headers
204
    header = SBUFcreate (0);
205
    SBUFprint (header, "Header! ");
206
207
208
209
    message = CTFcreateMessageBegin (&header, "MultiHeader! ", "123456789 123456789 123456789 123456789");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("Header! 123456789 123456789\nMultiHeader! 123456789 123456789\n", SBUFgetBuffer (message));
    SBUFfree (message);
210
211
212
213

    // If message length is smaller than the header length + 20 characters, line wrapping will instead
    // be done at header length + 20 characters
    global.cti_message_length = 1;
214
    header = SBUFcreate (0);
215
    SBUFprint (header, "Ten chars:");
216
217
218
219
    message = CTFcreateMessageBegin (&header, "", " 123456789 123456789  ");
    SBUFfree (CTFcreateMessageEnd ());
    EXPECT_STREQ ("Ten chars: 123456789 123456789\n \n", SBUFgetBuffer (message));
    SBUFfree (message);
220
}
221
222

/****************************
223
* CTFcreateMessageContinuedRaw *
224
225
226
227
228
229
****************************/

TEST (CTF, testCreateMessageContinuedSingleLineNoWrapping)
{
    global.cti_single_line = true;
    global.cti_message_length = 0;
230
    CTFinitialize ();
231
232
233
234

    str_buf *message;
    str_buf *remaining_lines;

235
    // Base case - no contents means we get nothing back.
236
    remaining_lines = SBUFcreate (0);
237
    message = CTFcreateMessageContinuedRaw ("", remaining_lines);
238
    EXPECT_STREQ ("", SBUFgetBuffer (message));
239
240
241
242
243
    SBUFfree (message);

    // Ensure that the header is fully ignored and newlines are converted to spaces.
    remaining_lines = SBUFcreate (0);
    SBUFprint (remaining_lines, "Foo\nBar\nBaz");
244
    message = CTFcreateMessageContinuedRaw ("Header: ", remaining_lines);
245
246
247
248
249
250
251
252
    EXPECT_STREQ (" Foo Bar Baz", SBUFgetBuffer(message));
    SBUFfree (message);
}

TEST (CTF, testCreateMessageContinuedMultiLineNoWrapping)
{
    global.cti_single_line = false;
    global.cti_message_length = 0;
253
    CTFinitialize ();
254
255
256
257
258
259

    str_buf *message;
    str_buf *remaining_lines;

    // Base case - no contents means we only get a newline back
    remaining_lines = SBUFcreate (0);
260
    message = CTFcreateMessageContinuedRaw ("", remaining_lines);
261
262
263
264
265
266
    EXPECT_STREQ ("\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that all lines are prefixed with the header, even if they are empty.
    remaining_lines = SBUFcreate (0);
    SBUFprint (remaining_lines, "\n\n");
267
    message = CTFcreateMessageContinuedRaw ("Header: ", remaining_lines);
268
269
270
271
272
273
    EXPECT_STREQ ("Header: \nHeader: \nHeader: \n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that all lines are prefixed with the header, even if it is the only line.
    remaining_lines = SBUFcreate (0);
    SBUFprint (remaining_lines, "String contents");
274
    message = CTFcreateMessageContinuedRaw ("H: ", remaining_lines);
275
276
277
278
279
280
    EXPECT_STREQ ("H: String contents\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that all lines are prefixed with the header, even if there are multiple lines of various types.
    remaining_lines = SBUFcreate (0);
    SBUFprint (remaining_lines, "Two empty lines after this one.\n\nAnd then a normal line.");
281
    message = CTFcreateMessageContinuedRaw ("Foo: ", remaining_lines);
282
283
284
285
286
287
288
289
    EXPECT_STREQ ("Foo: Two empty lines after this one.\nFoo: \nFoo: And then a normal line.\n", SBUFgetBuffer (message));
    SBUFfree (message);
}

TEST (CTF, testCreateMessageContinuedSingleLineWrapping)
{
    global.cti_single_line = true;
    global.cti_message_length = 0;
290
    CTFinitialize ();
291
292
293
294
295
296
297
298
299
300
301
302
    
    str_buf *remaining_lines;
    str_buf *message_no_wrap;
    str_buf *message_wrap;
    char *long_message;

    // c++ complains if we use a normal character array, so we use STRcpy to allocate it on the heap
    long_message = STRcpy ("A pretty long message that is longer than the header and then some! "
                           "If wrapping were enabled, it would surely work on this gigantic string.");

    remaining_lines = SBUFcreate (0);
    SBUFprint (remaining_lines, long_message);
303
    message_no_wrap = CTFcreateMessageContinuedRaw ("Header: ", remaining_lines);
304
305
306
307
308
309
310
311

    global.cti_single_line = true;
    global.cti_message_length = 25;

    // Ensure that line wrapping is ignored when single_line is active:
    // The output should be equal to the output from single line with wrapping explicitly disabled
    remaining_lines = SBUFcreate (0);
    SBUFprint (remaining_lines, long_message);
312
    message_wrap = CTFcreateMessageContinuedRaw ("Header: ", remaining_lines);
313
314
315
316
317
318
319
320
321
322
323
    EXPECT_STREQ (SBUFgetBuffer (message_no_wrap), SBUFgetBuffer(message_wrap));
    SBUFfree (message_no_wrap);
    SBUFfree (message_wrap);

    MEMfree (long_message);
}

TEST (CTF, testCreateMessageContinuedMultiLineWrapping)
{
    global.cti_single_line = false;
    global.cti_message_length = 30;
324
    CTFinitialize ();
325
326
327
328
329
330

    str_buf *remaining_lines;
    str_buf *message;

    // Ensure that we get a trailing enter in the base case
    remaining_lines = SBUFcreate (0);
331
    message = CTFcreateMessageContinuedRaw ("", remaining_lines);
332
333
334
335
336
337
    EXPECT_STREQ ("\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that message shorter than the message length aren't wrapped
    remaining_lines = SBUFcreate (0);
    SBUFprintf (remaining_lines, "A %s.", "string");
338
    message = CTFcreateMessageContinuedRaw ("Header: ", remaining_lines);
339
340
341
342
343
344
    EXPECT_STREQ ("Header: A string.\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that newlines reset the wrap location.
    remaining_lines = SBUFcreate (0);
    SBUFprintf (remaining_lines, "A few characters\n 123456789 123456789 123456789 Start of line.");
345
    message = CTFcreateMessageContinuedRaw ("", remaining_lines);
346
347
348
349
350
351
    EXPECT_STREQ ("A few characters\n 123456789 123456789 123456789\nStart of line.\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that multiple wraps are done correctly, even with headers.
    remaining_lines = SBUFcreate (0);
    SBUFprintf (remaining_lines, "56789 123456789 123456789 Start of line.9 123456789 123456789");
352
    message = CTFcreateMessageContinuedRaw ("012: ", remaining_lines);
353
354
355
    EXPECT_STREQ ("012: 56789 123456789 123456789\n012: Start of line.9 123456789\n012: 123456789\n", 
                  SBUFgetBuffer (message));
    SBUFfree (message);
356
357
358
359
360
}

TEST (CTF, testCreateMessageEnd)
{
    str_buf *message;
361
362
    str_buf *primary_header;

363
364
365

    // Ensure a new line is returned when cti_single_line is enabled.
    global.cti_single_line = true;
366
    CTFinitialize ();
367
368
369
370
371
372
373

    message = CTFcreateMessageEnd ();
    EXPECT_STREQ ("\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure an empty string buffer is returned when cti_single_line is disabled.
    global.cti_single_line = false;
374
375
    CTFinitialize ();

376
377
378
    message = CTFcreateMessageEnd ();
    EXPECT_STREQ ("", SBUFgetBuffer (message));
    SBUFfree (message);
379
380
381
382
383
384
}

TEST (CTF, testCreateMessageSingleLineNoWrapping)
{
    global.cti_single_line = true;
    global.cti_message_length = 0;
385
    CTFinitialize ();
386
387
388
389
390
391
392
393
394
395
396
397
398

    str_buf *message;

    // Ensure that all newlines are converted to spaces except the final newline
    message = CTFcreateMessage ("First header: ", "Unused header!", "All\nnewlines\nbecome\nspaces.");
    EXPECT_STREQ ("First header: All newlines become spaces.\n", SBUFgetBuffer (message));
    SBUFfree (message);
}

TEST (CTF, testCreateMessageMultilineNoWrapping)
{
    global.cti_single_line = false;
    global.cti_message_length = 0;
399
    CTFinitialize ();
400
401
402
403

    str_buf *message;

    // Ensure that the headers are properly printed after each newline
404
405
406
    message = CTFcreateMessage ("First header: ", "Continuation header!", 
                                "After each\nnewline, we expect a\ncontinuation header.");
    EXPECT_STREQ ("First header: After each\nContinuation header!newline, we expect a\nContinuation header!continuation header.\n",
407
408
409
410
411
412
413
414
                  SBUFgetBuffer (message));
    SBUFfree (message);
}

TEST (CTF, testCreateMessageSingleLineWrapping)
{
    global.cti_single_line = true;
    global.cti_message_length = 30;
415
    CTFinitialize ();
416
417
418
419
420
421
422
423
424
425
426
427
428
429

    str_buf *message;

    // Ensure that line wrapping is completely ignored while single line is active
    message = CTFcreateMessage ("Header1: ", "Unused: ",
                                "0123456789 123456789 123456789 123456789\n123456789");
    EXPECT_STREQ ("Header1: 0123456789 123456789 123456789 123456789 123456789\n", SBUFgetBuffer (message));
    SBUFfree (message);
}

TEST (CTF, testCreateMessageMultiLineWrapping)
{
    global.cti_single_line = false;
    global.cti_message_length = 30;
430
    CTFinitialize ();
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
    
    str_buf *message;
    
    // Ensure that headers of varying lengths, smaller than cti_message_length - 20, the 
    // global message length of 30 is still respected
    message = CTFcreateMessage ("Tiny", "Longer",
                                " second space wraps ---->   second space wraps -->   Pretty neat.");
    EXPECT_STREQ ("Tiny second space wraps ----> \nLonger second space wraps --> \nLonger Pretty neat.\n",
                  SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that if one of the headers is larger than cti_message_length - 20, it
    // uses a line length of header_length + 20
    message = CTFcreateMessage ("20 character header:", "thirty character header:::::::",
                                " 123456789 123456789  123456789 123456789 123456789");
    EXPECT_STREQ ("20 character header: 123456789 123456789\n"
                  "thirty character header::::::: 123456789 123456789\n"
                  "thirty character header:::::::123456789\n",
                  SBUFgetBuffer (message));
    SBUFfree (message);
}
452
453


454
455
456
457
TEST (CTF, testCreateMessageLoc)
{
    global.cti_single_line = true;
    global.cti_message_length = 0;
458
459
460
461
    MEMfree (global.cti_primary_header_format);
    MEMfree (global.cti_continuation_header_format);
    global.cti_primary_header_format = STRcpy ("%s: ");
    global.cti_continuation_header_format = STRcpy ("%.0s  ");
Michiel Verloop's avatar
Michiel Verloop committed
462
    CTFinitialize ();
463

464
465
    str_buf *message;

466
    // Ensure that newlines are converted to spaces with cti_single_line enabled.
467
468
469
    message = CTFcreateMessageLoc (EMPTY_LOC, "Error", "foo %s\nbaz", "bar");
    EXPECT_STREQ ("Error: foo bar baz\n", SBUFgetBuffer (message));
    SBUFfree (message);
470

471
    // Ensure that newlines stay newlines when cti_single_line is disabled.
472
473
    global.cti_single_line = false;
    global.cti_message_length = 0;
Michiel Verloop's avatar
Michiel Verloop committed
474
    CTFinitialize ();
475
476
477
478
479
480

    message = CTFcreateMessageLoc (EMPTY_LOC, "Error", "foo %s\nbaz", "bar");
    EXPECT_STREQ ("Error: foo bar\n  baz\n", SBUFgetBuffer (message));
    SBUFfree (message);

    // Ensure that the location is properly converted into the header
481
    // Also ensure that "Warning" is decapitalized because there is a location before it
482
483
    message = CTFcreateMessageLoc (((struct location) {.fname = "testfile", .line = 3, .col = 87}),
                                   "Warning", "%s", "Message.");
484
    EXPECT_STREQ ("testfile:3:87: warning: Message.\n", SBUFgetBuffer (message));
485
    SBUFfree (message);
486
487
488
489
490

    // Ensure that *only* @ symbols in the header are converted 
    // to spaces if cti_single_line is enabled.
    global.cti_single_line = true;
    global.cti_message_length = 0;
491
492
    MEMfree (global.cti_primary_header_format);
    global.cti_primary_header_format = STRcpy ("%s:@");
493
494
495
496
497
498
    CTFinitialize ();

    message = CTFcreateMessageLoc (EMPTY_LOC, "Error", "foo\nbar");
    EXPECT_STREQ ("Error: foo bar\n", SBUFgetBuffer (message));
    SBUFfree (message);

499
500
    // Ensure that *only* @ symbols in the primary header are converted to newlines
    // and ensure that @ symbols in the continuation header remain @ symbols.
501
502
    global.cti_single_line = false;
    global.cti_message_length = 0;
503
504
505
506
    MEMfree (global.cti_primary_header_format);
    MEMfree (global.cti_continuation_header_format);
    global.cti_primary_header_format = STRcpy ("%s:@First:");
    global.cti_continuation_header_format = STRcpy ("%.0sContinued:@");
507
508
509
510
511
    CTFinitialize ();

    message = CTFcreateMessageLoc (EMPTY_LOC, "Error", "foo\nbar");
    EXPECT_STREQ ("Error:\nContinued:@First:foo\nContinued:@bar\n", SBUFgetBuffer (message));
    SBUFfree (message);
512
}