• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 21460395012

29 Jan 2026 12:02AM UTC coverage: 72.47% (-0.3%) from 72.793%
21460395012

push

github

yuwata
vmspawn: Add image format option to support qcow2

A QEMU qcow2 VM image can be internally sparse and compressed.
Support such images in vmspawn for both the main disk and any extra
disks.

0 of 43 new or added lines in 2 files covered. (0.0%)

1696 existing lines in 48 files now uncovered.

309976 of 427731 relevant lines covered (72.47%)

1246714.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.97
/src/test/test-format-table.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdlib.h>
4
#include <unistd.h>
5

6
#include "alloc-util.h"
7
#include "ansi-color.h"
8
#include "env-util.h"
9
#include "format-table.h"
10
#include "json-util.h"
11
#include "terminal-util.h"
12
#include "tests.h"
13
#include "time-util.h"
14

15
TEST(issue_9549) {
1✔
16
        _cleanup_(table_unrefp) Table *table = NULL;
×
17
        _cleanup_free_ char *formatted = NULL;
1✔
18

19
        ASSERT_NOT_NULL((table = table_new("name", "type", "ro", "usage", "created", "modified")));
1✔
20
        ASSERT_OK(table_set_align_percent(table, TABLE_HEADER_CELL(3), 100));
1✔
21
        ASSERT_OK(table_add_many(table,
1✔
22
                                 TABLE_STRING, "foooo",
23
                                 TABLE_STRING, "raw",
24
                                 TABLE_BOOLEAN, false,
25
                                 TABLE_SIZE, (uint64_t) (673.7*1024*1024),
26
                                 TABLE_STRING, "Wed 2018-07-11 00:10:33 JST",
27
                                 TABLE_STRING, "Wed 2018-07-11 00:16:00 JST"));
28

29
        table_set_width(table, 75);
1✔
30
        ASSERT_OK(table_format(table, &formatted));
1✔
31

32
        printf("%s\n", formatted);
1✔
33
        ASSERT_STREQ(formatted,
1✔
34
                     "NAME  TYPE RO  USAGE CREATED                    MODIFIED\n"
35
                     "foooo raw  no 673.6M Wed 2018-07-11 00:10:33 J… Wed 2018-07-11 00:16:00 JST\n");
36
}
1✔
37

38
TEST(multiline) {
1✔
39
        _cleanup_(table_unrefp) Table *table = NULL;
×
40
        _cleanup_free_ char *formatted = NULL;
×
41

42
        ASSERT_NOT_NULL((table = table_new("foo", "bar")));
1✔
43

44
        ASSERT_OK(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100));
1✔
45

46
        ASSERT_OK(table_add_many(table,
1✔
47
                                 TABLE_STRING, "three\ndifferent\nlines",
48
                                 TABLE_STRING, "two\nlines\n"));
49

50
        table_set_cell_height_max(table, 1);
1✔
51
        ASSERT_OK(table_format(table, &formatted));
1✔
52
        fputs(formatted, stdout);
1✔
53
        ASSERT_STREQ(formatted,
1✔
54
                     "FOO     BAR\n"
55
                     "three… two…\n");
56
        formatted = mfree(formatted);
1✔
57

58
        table_set_cell_height_max(table, 2);
1✔
59
        ASSERT_OK(table_format(table, &formatted));
1✔
60
        fputs(formatted, stdout);
1✔
61
        ASSERT_STREQ(formatted,
1✔
62
                     "FOO          BAR\n"
63
                     "three        two\n"
64
                     "different… lines\n");
65
        formatted = mfree(formatted);
1✔
66

67
        table_set_cell_height_max(table, 3);
1✔
68
        ASSERT_OK(table_format(table, &formatted));
1✔
69
        fputs(formatted, stdout);
1✔
70
        ASSERT_STREQ(formatted,
1✔
71
                     "FOO         BAR\n"
72
                     "three       two\n"
73
                     "different lines\n"
74
                     "lines     \n");
75
        formatted = mfree(formatted);
1✔
76

77
        table_set_cell_height_max(table, SIZE_MAX);
1✔
78
        ASSERT_OK(table_format(table, &formatted));
1✔
79
        fputs(formatted, stdout);
1✔
80
        ASSERT_STREQ(formatted,
1✔
81
                     "FOO         BAR\n"
82
                     "three       two\n"
83
                     "different lines\n"
84
                     "lines     \n");
85
        formatted = mfree(formatted);
1✔
86

87
        ASSERT_OK(table_add_many(table,
1✔
88
                                 TABLE_STRING, "short",
89
                                 TABLE_STRING, "a\npair"));
90

91
        ASSERT_OK(table_add_many(table,
1✔
92
                                 TABLE_STRING, "short2\n",
93
                                 TABLE_STRING, "a\nfour\nline\ncell"));
94

95
        table_set_cell_height_max(table, 1);
1✔
96
        ASSERT_OK(table_format(table, &formatted));
1✔
97
        fputs(formatted, stdout);
1✔
98
        ASSERT_STREQ(formatted,
1✔
99
                     "FOO     BAR\n"
100
                     "three… two…\n"
101
                     "short    a…\n"
102
                     "short2   a…\n");
103
        formatted = mfree(formatted);
1✔
104

105
        table_set_cell_height_max(table, 2);
1✔
106
        ASSERT_OK(table_format(table, &formatted));
1✔
107
        fputs(formatted, stdout);
1✔
108
        ASSERT_STREQ(formatted,
1✔
109
                     "FOO          BAR\n"
110
                     "three        two\n"
111
                     "different… lines\n"
112
                     "short          a\n"
113
                     "            pair\n"
114
                     "short2         a\n"
115
                     "           four…\n");
116
        formatted = mfree(formatted);
1✔
117

118
        table_set_cell_height_max(table, 3);
1✔
119
        ASSERT_OK(table_format(table, &formatted));
1✔
120
        fputs(formatted, stdout);
1✔
121
        ASSERT_STREQ(formatted,
1✔
122
                     "FOO         BAR\n"
123
                     "three       two\n"
124
                     "different lines\n"
125
                     "lines     \n"
126
                     "short         a\n"
127
                     "           pair\n"
128
                     "short2        a\n"
129
                     "           four\n"
130
                     "          line…\n");
131
        formatted = mfree(formatted);
1✔
132

133
        table_set_cell_height_max(table, SIZE_MAX);
1✔
134
        ASSERT_OK(table_format(table, &formatted));
1✔
135
        fputs(formatted, stdout);
1✔
136
        ASSERT_STREQ(formatted,
1✔
137
                     "FOO         BAR\n"
138
                     "three       two\n"
139
                     "different lines\n"
140
                     "lines     \n"
141
                     "short         a\n"
142
                     "           pair\n"
143
                     "short2        a\n"
144
                     "           four\n"
145
                     "           line\n"
146
                     "           cell\n");
147
        formatted = mfree(formatted);
1✔
148
}
1✔
149

150
TEST(strv) {
1✔
151
        _cleanup_(table_unrefp) Table *table = NULL;
×
152
        _cleanup_free_ char *formatted = NULL;
×
153

154
        ASSERT_NOT_NULL((table = table_new("foo", "bar")));
1✔
155

156
        ASSERT_OK(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100));
1✔
157

158
        ASSERT_OK(table_add_many(table,
1✔
159
                                 TABLE_STRV, STRV_MAKE("three", "different", "lines"),
160
                                 TABLE_STRV, STRV_MAKE("two", "lines")));
161

162
        table_set_cell_height_max(table, 1);
1✔
163
        ASSERT_OK(table_format(table, &formatted));
1✔
164
        fputs(formatted, stdout);
1✔
165
        ASSERT_STREQ(formatted,
1✔
166
                     "FOO     BAR\n"
167
                     "three… two…\n");
168
        formatted = mfree(formatted);
1✔
169

170
        table_set_cell_height_max(table, 2);
1✔
171
        ASSERT_OK(table_format(table, &formatted));
1✔
172
        fputs(formatted, stdout);
1✔
173
        ASSERT_STREQ(formatted,
1✔
174
                     "FOO          BAR\n"
175
                     "three        two\n"
176
                     "different… lines\n");
177
        formatted = mfree(formatted);
1✔
178

179
        table_set_cell_height_max(table, 3);
1✔
180
        ASSERT_OK(table_format(table, &formatted));
1✔
181
        fputs(formatted, stdout);
1✔
182
        ASSERT_STREQ(formatted,
1✔
183
                     "FOO         BAR\n"
184
                     "three       two\n"
185
                     "different lines\n"
186
                     "lines     \n");
187
        formatted = mfree(formatted);
1✔
188

189
        table_set_cell_height_max(table, SIZE_MAX);
1✔
190
        ASSERT_OK(table_format(table, &formatted));
1✔
191
        fputs(formatted, stdout);
1✔
192
        ASSERT_STREQ(formatted,
1✔
193
                     "FOO         BAR\n"
194
                     "three       two\n"
195
                     "different lines\n"
196
                     "lines     \n");
197
        formatted = mfree(formatted);
1✔
198

199
        ASSERT_OK(table_add_many(table,
1✔
200
                                 TABLE_STRING, "short",
201
                                 TABLE_STRV, STRV_MAKE("a", "pair")));
202

203
        ASSERT_OK(table_add_many(table,
1✔
204
                                 TABLE_STRV, STRV_MAKE("short2"),
205
                                 TABLE_STRV, STRV_MAKE("a", "four", "line", "cell")));
206

207
        table_set_cell_height_max(table, 1);
1✔
208
        ASSERT_OK(table_format(table, &formatted));
1✔
209
        fputs(formatted, stdout);
1✔
210
        ASSERT_STREQ(formatted,
1✔
211
                        "FOO     BAR\n"
212
                        "three… two…\n"
213
                        "short    a…\n"
214
                        "short2   a…\n");
215
        formatted = mfree(formatted);
1✔
216

217
        table_set_cell_height_max(table, 2);
1✔
218
        ASSERT_OK(table_format(table, &formatted));
1✔
219
        fputs(formatted, stdout);
1✔
220
        ASSERT_STREQ(formatted,
1✔
221
                     "FOO          BAR\n"
222
                     "three        two\n"
223
                     "different… lines\n"
224
                     "short          a\n"
225
                     "            pair\n"
226
                     "short2         a\n"
227
                     "           four…\n");
228
        formatted = mfree(formatted);
1✔
229

230
        table_set_cell_height_max(table, 3);
1✔
231
        ASSERT_OK(table_format(table, &formatted));
1✔
232
        fputs(formatted, stdout);
1✔
233
        ASSERT_STREQ(formatted,
1✔
234
                     "FOO         BAR\n"
235
                     "three       two\n"
236
                     "different lines\n"
237
                     "lines     \n"
238
                     "short         a\n"
239
                     "           pair\n"
240
                     "short2        a\n"
241
                     "           four\n"
242
                     "          line…\n");
243
        formatted = mfree(formatted);
1✔
244

245
        table_set_cell_height_max(table, SIZE_MAX);
1✔
246
        ASSERT_OK(table_format(table, &formatted));
1✔
247
        fputs(formatted, stdout);
1✔
248
        ASSERT_STREQ(formatted,
1✔
249
                     "FOO         BAR\n"
250
                     "three       two\n"
251
                     "different lines\n"
252
                     "lines     \n"
253
                     "short         a\n"
254
                     "           pair\n"
255
                     "short2        a\n"
256
                     "           four\n"
257
                     "           line\n"
258
                     "           cell\n");
259
        formatted = mfree(formatted);
1✔
260
}
1✔
261

262
TEST(strv_wrapped) {
1✔
263
        _cleanup_(table_unrefp) Table *table = NULL;
×
264
        _cleanup_free_ char *formatted = NULL;
×
265

266
        ASSERT_NOT_NULL((table = table_new("foo", "bar")));
1✔
267

268
        ASSERT_OK(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100));
1✔
269

270
        ASSERT_OK(table_add_many(table,
1✔
271
                                 TABLE_STRV_WRAPPED, STRV_MAKE("three", "different", "lines"),
272
                                 TABLE_STRV_WRAPPED, STRV_MAKE("two", "lines")));
273

274
        table_set_cell_height_max(table, 1);
1✔
275
        ASSERT_OK(table_format(table, &formatted));
1✔
276
        fputs(formatted, stdout);
1✔
277
        ASSERT_STREQ(formatted,
1✔
278
                     "FOO                         BAR\n"
279
                     "three different lines two lines\n");
280
        formatted = mfree(formatted);
1✔
281

282
        table_set_cell_height_max(table, 2);
1✔
283
        ASSERT_OK(table_format(table, &formatted));
1✔
284
        fputs(formatted, stdout);
1✔
285
        ASSERT_STREQ(formatted,
1✔
286
                     "FOO                         BAR\n"
287
                     "three different lines two lines\n");
288
        formatted = mfree(formatted);
1✔
289

290
        table_set_cell_height_max(table, 3);
1✔
291
        ASSERT_OK(table_format(table, &formatted));
1✔
292
        fputs(formatted, stdout);
1✔
293
        ASSERT_STREQ(formatted,
1✔
294
                     "FOO                         BAR\n"
295
                     "three different lines two lines\n");
296
        formatted = mfree(formatted);
1✔
297

298
        table_set_cell_height_max(table, SIZE_MAX);
1✔
299
        ASSERT_OK(table_format(table, &formatted));
1✔
300
        fputs(formatted, stdout);
1✔
301
        ASSERT_STREQ(formatted,
1✔
302
                     "FOO                         BAR\n"
303
                     "three different lines two lines\n");
304
        formatted = mfree(formatted);
1✔
305

306
        ASSERT_OK(table_add_many(table,
1✔
307
                                 TABLE_STRING, "short",
308
                                 TABLE_STRV_WRAPPED, STRV_MAKE("a", "pair")));
309

310
        ASSERT_OK(table_add_many(table,
1✔
311
                                 TABLE_STRV_WRAPPED, STRV_MAKE("short2"),
312
                                 TABLE_STRV_WRAPPED, STRV_MAKE("a", "eight", "line", "ćęłł",
313
                                                               "___5___", "___6___", "___7___", "___8___")));
314

315
        table_set_cell_height_max(table, 1);
1✔
316
        ASSERT_OK(table_format(table, &formatted));
1✔
317
        fputs(formatted, stdout);
1✔
318
        ASSERT_STREQ(formatted,
1✔
319
                     "FOO                             BAR\n"
320
                     "three different…          two lines\n"
321
                     "short                        a pair\n"
322
                     "short2           a eight line ćęłł…\n");
323
        formatted = mfree(formatted);
1✔
324

325
        table_set_cell_height_max(table, 2);
1✔
326
        ASSERT_OK(table_format(table, &formatted));
1✔
327
        fputs(formatted, stdout);
1✔
328
        ASSERT_STREQ(formatted,
1✔
329
                     "FOO                           BAR\n"
330
                     "three different         two lines\n"
331
                     "lines           \n"
332
                     "short                      a pair\n"
333
                     "short2          a eight line ćęłł\n"
334
                     "                 ___5___ ___6___…\n");
335
        formatted = mfree(formatted);
1✔
336

337
        table_set_cell_height_max(table, 3);
1✔
338
        ASSERT_OK(table_format(table, &formatted));
1✔
339
        fputs(formatted, stdout);
1✔
340
        ASSERT_STREQ(formatted,
1✔
341
                     "FOO                           BAR\n"
342
                     "three different         two lines\n"
343
                     "lines           \n"
344
                     "short                      a pair\n"
345
                     "short2          a eight line ćęłł\n"
346
                     "                  ___5___ ___6___\n"
347
                     "                  ___7___ ___8___\n");
348
        formatted = mfree(formatted);
1✔
349

350
        table_set_cell_height_max(table, SIZE_MAX);
1✔
351
        ASSERT_OK(table_format(table, &formatted));
1✔
352
        fputs(formatted, stdout);
1✔
353
        ASSERT_STREQ(formatted,
1✔
354
                     "FOO                           BAR\n"
355
                     "three different         two lines\n"
356
                     "lines           \n"
357
                     "short                      a pair\n"
358
                     "short2          a eight line ćęłł\n"
359
                     "                  ___5___ ___6___\n"
360
                     "                  ___7___ ___8___\n");
361
        formatted = mfree(formatted);
1✔
362
}
1✔
363

364
TEST(json) {
1✔
365
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL, *w = NULL;
1✔
366
        _cleanup_(table_unrefp) Table *t = NULL;
1✔
367

368
        ASSERT_NOT_NULL((t = table_new_raw(4)));
1✔
369

370
        ASSERT_OK(table_add_many(t,
1✔
371
                                 TABLE_HEADER, "foo bar",
372
                                 TABLE_HEADER, "quux",
373
                                 TABLE_HEADER, "piep miau",
374
                                 TABLE_HEADER, "asdf",
375
                                 TABLE_SET_JSON_FIELD_NAME, "asdf-custom"));
376
        ASSERT_OK(table_set_json_field_name(t, 2, "ZZZ"));
1✔
377
        ASSERT_OK(table_set_json_field_name(t, 2, NULL));
1✔
378
        ASSERT_OK(table_set_json_field_name(t, 2, "zzz"));
1✔
379

380
        ASSERT_OK(table_add_many(t,
1✔
381
                                 TABLE_STRING, "v1",
382
                                 TABLE_UINT64, UINT64_C(4711),
383
                                 TABLE_BOOLEAN, true,
384
                                 TABLE_EMPTY));
385

386
        ASSERT_OK(table_add_many(t,
1✔
387
                                 TABLE_STRV, STRV_MAKE("a", "b", "c"),
388
                                 TABLE_EMPTY,
389
                                 TABLE_MODE, 0755,
390
                                 TABLE_EMPTY));
391

392
        ASSERT_OK(table_to_json(t, &v));
1✔
393

394
        ASSERT_OK(sd_json_build(&w,
1✔
395
                             SD_JSON_BUILD_ARRAY(
396
                                             SD_JSON_BUILD_OBJECT(
397
                                                             SD_JSON_BUILD_PAIR("foo_bar", JSON_BUILD_CONST_STRING("v1")),
398
                                                             SD_JSON_BUILD_PAIR("quux", SD_JSON_BUILD_UNSIGNED(4711)),
399
                                                             SD_JSON_BUILD_PAIR("zzz", SD_JSON_BUILD_BOOLEAN(true)),
400
                                                             SD_JSON_BUILD_PAIR("asdf-custom", SD_JSON_BUILD_NULL)),
401
                                             SD_JSON_BUILD_OBJECT(
402
                                                             SD_JSON_BUILD_PAIR("foo_bar", SD_JSON_BUILD_STRV(STRV_MAKE("a", "b", "c"))),
403
                                                             SD_JSON_BUILD_PAIR("quux", SD_JSON_BUILD_NULL),
404
                                                             SD_JSON_BUILD_PAIR("zzz", SD_JSON_BUILD_UNSIGNED(0755)),
405
                                                             SD_JSON_BUILD_PAIR("asdf-custom", SD_JSON_BUILD_NULL)))));
406

407
        ASSERT_TRUE(sd_json_variant_equal(v, w));
1✔
408
}
1✔
409

410
TEST(json_mangling) {
1✔
411
        static const struct {
1✔
412
                const char *arg;
413
                const char *exp;
414
        } cases[] = {
415
                /* Not Mangled */
416
                { "foo", "foo" },
417
                { "foo_bar", "foo_bar" },
418
                { "fooBar", "fooBar" },
419
                { "fooBar123", "fooBar123" },
420
                { "foo_bar123", "foo_bar123" },
421
                { ALPHANUMERICAL, ALPHANUMERICAL },
422
                { "_123", "_123" },
423

424
                /* Mangled */
425
                { "Foo Bar", "foo_bar" },
426
                { "Foo-Bar", "foo_bar" },
427
                { "Foo@Bar", "foo_bar" },
428
                { "Foo (Bar)", "foo__bar_"},
429
                { "MixedCase ALLCAPS", "mixedCase_ALLCAPS" },
430
                { "_X", "_x" },
431
                { "_Foo", "_foo" },
432
        };
433

434
        FOREACH_ELEMENT(i, cases) {
15✔
435
                _cleanup_free_ char *ret = NULL;
14✔
436
                ASSERT_NOT_NULL((ret = table_mangle_to_json_field_name(i->arg)));
14✔
437
                printf("\"%s\" -> \"%s\"\n", i->arg, ret);
14✔
438
                ASSERT_STREQ(ret, i->exp);
14✔
439
        }
440
}
1✔
441

442
TEST(table) {
1✔
443
        _cleanup_(table_unrefp) Table *t = NULL;
×
444
        _cleanup_free_ char *formatted = NULL;
1✔
445

446
        ASSERT_NOT_NULL((t = table_new("one", "two", "three", "four")));
1✔
447

448
        ASSERT_OK(table_set_align_percent(t, TABLE_HEADER_CELL(3), 100));
1✔
449

450
        ASSERT_OK(table_add_many(t,
1✔
451
                                 TABLE_STRING, "xxx",
452
                                 TABLE_STRING, "yyy",
453
                                 TABLE_BOOLEAN, true,
454
                                 TABLE_INT, -1));
455

456
        ASSERT_OK(table_add_many(t,
1✔
457
                                 TABLE_STRING, "a long field",
458
                                 TABLE_STRING, "yyy",
459
                                 TABLE_SET_UPPERCASE, 1,
460
                                 TABLE_BOOLEAN, false,
461
                                 TABLE_INT, -999999));
462

463
        ASSERT_OK(table_format(t, &formatted));
1✔
464
        printf("%s\n", formatted);
1✔
465

466
        ASSERT_STREQ(formatted,
1✔
467
                     "ONE          TWO THREE    FOUR\n"
468
                     "xxx          yyy yes        -1\n"
469
                     "a long field YYY no    -999999\n");
470

471
        formatted = mfree(formatted);
1✔
472

473
        table_set_width(t, 40);
1✔
474

475
        ASSERT_OK(table_format(t, &formatted));
1✔
476
        printf("%s\n", formatted);
1✔
477

478
        ASSERT_STREQ(formatted,
1✔
479
                     "ONE            TWO   THREE          FOUR\n"
480
                     "xxx            yyy   yes              -1\n"
481
                     "a long field   YYY   no          -999999\n");
482

483
        formatted = mfree(formatted);
1✔
484

485
        table_set_width(t, 15);
1✔
486
        ASSERT_OK(table_format(t, &formatted));
1✔
487
        printf("%s\n", formatted);
1✔
488

489
        ASSERT_STREQ(formatted,
1✔
490
                     "ONE TWO TH… FO…\n"
491
                     "xxx yyy yes  -1\n"
492
                     "a … YYY no  -9…\n");
493

494
        formatted = mfree(formatted);
1✔
495

496
        table_set_width(t, 5);
1✔
497
        ASSERT_OK(table_format(t, &formatted));
1✔
498
        printf("%s\n", formatted);
1✔
499

500
        ASSERT_STREQ(formatted,
1✔
501
                     "… … … …\n"
502
                     "… … … …\n"
503
                     "… … … …\n");
504

505
        formatted = mfree(formatted);
1✔
506

507
        table_set_width(t, 3);
1✔
508
        ASSERT_OK(table_format(t, &formatted));
1✔
509
        printf("%s\n", formatted);
1✔
510

511
        ASSERT_STREQ(formatted,
1✔
512
                     "… … … …\n"
513
                     "… … … …\n"
514
                     "… … … …\n");
515

516
        formatted = mfree(formatted);
1✔
517

518
        table_set_width(t, SIZE_MAX);
1✔
519
        ASSERT_OK(table_set_sort(t, (size_t) 0, (size_t) 2, SIZE_MAX));
1✔
520

521
        ASSERT_OK(table_format(t, &formatted));
1✔
522
        printf("%s\n", formatted);
1✔
523

524
        ASSERT_STREQ(formatted,
1✔
525
                     "ONE          TWO THREE    FOUR\n"
526
                     "a long field YYY no    -999999\n"
527
                     "xxx          yyy yes        -1\n");
528

529
        formatted = mfree(formatted);
1✔
530

531
        table_set_header(t, false);
1✔
532

533
        ASSERT_OK(table_add_many(t,
1✔
534
                                 TABLE_STRING, "fäää",
535
                                 TABLE_STRING, "uuu",
536
                                 TABLE_BOOLEAN, true,
537
                                 TABLE_INT, 42));
538

539
        ASSERT_OK(table_add_many(t,
1✔
540
                                 TABLE_STRING, "fäää",
541
                                 TABLE_STRING, "zzz",
542
                                 TABLE_BOOLEAN, false,
543
                                 TABLE_INT, 0));
544

545
        ASSERT_OK(table_add_many(t,
1✔
546
                                 TABLE_EMPTY,
547
                                 TABLE_SIZE, (uint64_t) 4711,
548
                                 TABLE_TIMESPAN, (usec_t) 5*USEC_PER_MINUTE,
549
                                 TABLE_INT64, (uint64_t) -123456789));
550

551
        ASSERT_OK(table_format(t, &formatted));
1✔
552
        printf("%s\n", formatted);
1✔
553

554
        ASSERT_STREQ(formatted,
1✔
555
                     "a long field YYY  no      -999999\n"
556
                     "fäää         zzz  no            0\n"
557
                     "fäää         uuu  yes          42\n"
558
                     "xxx          yyy  yes          -1\n"
559
                     "             4.6K 5min -123456789\n");
560

561
        formatted = mfree(formatted);
1✔
562

563
        ASSERT_OK(table_set_display(t, (size_t) 2, (size_t) 0, (size_t) 2, (size_t) 0, (size_t) 0, SIZE_MAX));
1✔
564

565
        ASSERT_OK(table_format(t, &formatted));
1✔
566
        printf("%s\n", formatted);
1✔
567

568
        if (isatty_safe(STDOUT_FILENO))
1✔
569
                ASSERT_STREQ(formatted,
×
570
                             "no   a long f… no   a long f… a long fi…\n"
571
                             "no   fäää      no   fäää      fäää\n"
572
                             "yes  fäää      yes  fäää      fäää\n"
573
                             "yes  xxx       yes  xxx       xxx\n"
574
                             "5min           5min           \n");
575
        else
576
                ASSERT_STREQ(formatted,
1✔
577
                             "no   a long field no   a long field a long field\n"
578
                             "no   fäää         no   fäää         fäää\n"
579
                             "yes  fäää         yes  fäää         fäää\n"
580
                             "yes  xxx          yes  xxx          xxx\n"
581
                             "5min              5min              \n");
582
}
1✔
583

584
TEST(signed_integers) {
1✔
585
        _cleanup_(table_unrefp) Table *t = NULL;
×
586
        _cleanup_free_ char *formatted = NULL;
1✔
587

588
        ASSERT_NOT_NULL((t = table_new("int", "int8", "int16", "int32", "int64")));
1✔
589
        table_set_width(t, 0);
1✔
590

591
        ASSERT_OK(table_add_many(t,
1✔
592
                                 TABLE_INT, -1,
593
                                 TABLE_INT8, INT8_C(-1),
594
                                 TABLE_INT16, INT16_C(-1),
595
                                 TABLE_INT32, INT32_C(-1),
596
                                 TABLE_INT64, INT64_C(-1)));
597
        ASSERT_OK(table_add_many(t,
1✔
598
                                 TABLE_INT, INT_MAX,
599
                                 TABLE_INT8, INT8_MAX,
600
                                 TABLE_INT16, INT16_MAX,
601
                                 TABLE_INT32, INT32_MAX,
602
                                 TABLE_INT64, INT64_MAX));
603
        ASSERT_OK(table_add_many(t,
1✔
604
                                 TABLE_INT, INT_MIN,
605
                                 TABLE_INT8, INT8_MIN,
606
                                 TABLE_INT16, INT16_MIN,
607
                                 TABLE_INT32, INT32_MIN,
608
                                 TABLE_INT64, INT64_MIN));
609

610
        ASSERT_OK(table_format(t, &formatted));
1✔
611
        printf("%s\n", formatted);
1✔
612

613
        ASSERT_STREQ(formatted,
1✔
614
                     "INT         INT8 INT16  INT32       INT64\n"
615
                     "-1          -1   -1     -1          -1\n"
616
                     "2147483647  127  32767  2147483647  9223372036854775807\n"
617
                     "-2147483648 -128 -32768 -2147483648 -9223372036854775808\n");
618

619
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *a = NULL, *b = NULL;
2✔
620
        ASSERT_OK(table_to_json(t, &a));
1✔
621

622
        table_print_json(t, /* f= */ NULL, SD_JSON_FORMAT_NEWLINE);
1✔
623

624
        ASSERT_OK(sd_json_build(&b,
1✔
625
                                SD_JSON_BUILD_ARRAY(
626
                                  SD_JSON_BUILD_OBJECT(
627
                                    SD_JSON_BUILD_PAIR("int", SD_JSON_BUILD_INTEGER(-1)),
628
                                    SD_JSON_BUILD_PAIR("int8", SD_JSON_BUILD_INTEGER(-1)),
629
                                    SD_JSON_BUILD_PAIR("int16", SD_JSON_BUILD_INTEGER(-1)),
630
                                    SD_JSON_BUILD_PAIR("int32", SD_JSON_BUILD_INTEGER(-1)),
631
                                    SD_JSON_BUILD_PAIR("int64", SD_JSON_BUILD_INTEGER(-1))),
632
                                  SD_JSON_BUILD_OBJECT(
633
                                    SD_JSON_BUILD_PAIR("int", SD_JSON_BUILD_INTEGER(INT_MAX)),
634
                                    SD_JSON_BUILD_PAIR("int8", SD_JSON_BUILD_INTEGER(INT8_MAX)),
635
                                    SD_JSON_BUILD_PAIR("int16", SD_JSON_BUILD_INTEGER(INT16_MAX)),
636
                                    SD_JSON_BUILD_PAIR("int32", SD_JSON_BUILD_INTEGER(INT32_MAX)),
637
                                    SD_JSON_BUILD_PAIR("int64", SD_JSON_BUILD_INTEGER(INT64_MAX))),
638
                                  SD_JSON_BUILD_OBJECT(
639
                                    SD_JSON_BUILD_PAIR("int", SD_JSON_BUILD_INTEGER(INT_MIN)),
640
                                    SD_JSON_BUILD_PAIR("int8", SD_JSON_BUILD_INTEGER(INT8_MIN)),
641
                                    SD_JSON_BUILD_PAIR("int16", SD_JSON_BUILD_INTEGER(INT16_MIN)),
642
                                    SD_JSON_BUILD_PAIR("int32", SD_JSON_BUILD_INTEGER(INT32_MIN)),
643
                                    SD_JSON_BUILD_PAIR("int64", SD_JSON_BUILD_INTEGER(INT64_MIN))))));
644
        sd_json_variant_dump(b, SD_JSON_FORMAT_NEWLINE, stdout, NULL);
1✔
645

646
        ASSERT_TRUE(sd_json_variant_equal(a, b));
1✔
647
}
1✔
648

649
TEST(unsigned_integers) {
1✔
650
        _cleanup_(table_unrefp) Table *t = NULL;
×
651
        _cleanup_free_ char *formatted = NULL;
1✔
652

653
        ASSERT_NOT_NULL((t = table_new("uint", "uint8", "uint16", "uint32", "uhex32", "uint64", "uhex64")));
1✔
654
        table_set_width(t, 0);
1✔
655

656
        ASSERT_OK(table_add_many(t,
1✔
657
                                 TABLE_UINT, 0,
658
                                 TABLE_UINT8, UINT8_C(0),
659
                                 TABLE_UINT16, UINT16_C(0),
660
                                 TABLE_UINT32, UINT32_C(0),
661
                                 TABLE_UINT32_HEX, UINT32_C(0),
662
                                 TABLE_UINT64, UINT64_C(0),
663
                                 TABLE_UINT64_HEX, UINT64_C(0)));
664
        ASSERT_OK(table_add_many(t,
1✔
665
                                 TABLE_UINT, UINT_MAX,
666
                                 TABLE_UINT8, UINT8_MAX,
667
                                 TABLE_UINT16, UINT16_MAX,
668
                                 TABLE_UINT32, UINT32_MAX,
669
                                 TABLE_UINT32_HEX, UINT32_MAX,
670
                                 TABLE_UINT64, UINT64_MAX,
671
                                 TABLE_UINT64_HEX, UINT64_MAX));
672

673
        ASSERT_OK(table_format(t, &formatted));
1✔
674
        printf("%s\n", formatted);
1✔
675

676
        ASSERT_STREQ(formatted,
1✔
677
                     "UINT       UINT8 UINT16 UINT32     UHEX32   UINT64               UHEX64\n"
678
                     "0          0     0      0          0        0                    0\n"
679
                     "4294967295 255   65535  4294967295 ffffffff 18446744073709551615 ffffffffffffffff\n");
680

681
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *a = NULL, *b = NULL;
2✔
682
        ASSERT_OK(table_to_json(t, &a));
1✔
683

684
        table_print_json(t, /* f= */ NULL, SD_JSON_FORMAT_NEWLINE);
1✔
685

686
        ASSERT_OK(sd_json_build(&b,
1✔
687
                                SD_JSON_BUILD_ARRAY(
688
                                  SD_JSON_BUILD_OBJECT(
689
                                    SD_JSON_BUILD_PAIR("uint", SD_JSON_BUILD_UNSIGNED(0)),
690
                                    SD_JSON_BUILD_PAIR("uint8", SD_JSON_BUILD_UNSIGNED(0)),
691
                                    SD_JSON_BUILD_PAIR("uint16", SD_JSON_BUILD_UNSIGNED(0)),
692
                                    SD_JSON_BUILD_PAIR("uint32", SD_JSON_BUILD_UNSIGNED(0)),
693
                                    SD_JSON_BUILD_PAIR("uhex32", SD_JSON_BUILD_UNSIGNED(0)),
694
                                    SD_JSON_BUILD_PAIR("uint64", SD_JSON_BUILD_UNSIGNED(0)),
695
                                    SD_JSON_BUILD_PAIR("uhex64", SD_JSON_BUILD_UNSIGNED(0))),
696
                                  SD_JSON_BUILD_OBJECT(
697
                                    SD_JSON_BUILD_PAIR("uint", SD_JSON_BUILD_UNSIGNED(UINT_MAX)),
698
                                    SD_JSON_BUILD_PAIR("uint8", SD_JSON_BUILD_UNSIGNED(UINT8_MAX)),
699
                                    SD_JSON_BUILD_PAIR("uint16", SD_JSON_BUILD_UNSIGNED(UINT16_MAX)),
700
                                    SD_JSON_BUILD_PAIR("uint32", SD_JSON_BUILD_UNSIGNED(UINT32_MAX)),
701
                                    SD_JSON_BUILD_PAIR("uhex32", SD_JSON_BUILD_UNSIGNED(UINT32_MAX)),
702
                                    SD_JSON_BUILD_PAIR("uint64", SD_JSON_BUILD_UNSIGNED(UINT64_MAX)),
703
                                    SD_JSON_BUILD_PAIR("uhex64", SD_JSON_BUILD_UNSIGNED(UINT64_MAX))))));
704
        sd_json_variant_dump(b, SD_JSON_FORMAT_NEWLINE, stdout, NULL);
1✔
705

706
        ASSERT_TRUE(sd_json_variant_equal(a, b));
1✔
707
}
1✔
708

709
TEST(vertical) {
1✔
710
        _cleanup_(table_unrefp) Table *t = NULL;
×
711
        _cleanup_free_ char *formatted = NULL;
1✔
712

713
        ASSERT_NOT_NULL((t = table_new_vertical()));
1✔
714

715
        ASSERT_OK(table_add_many(t,
1✔
716
                                 TABLE_FIELD, "pfft aa", TABLE_STRING, "foo",
717
                                 TABLE_FIELD, "uuu o", TABLE_SIZE, UINT64_C(1024),
718
                                 TABLE_FIELD, "quux", TABLE_STRING, "asdf", TABLE_SET_JSON_FIELD_NAME, "custom-quux",
719
                                 TABLE_FIELD, "lllllllllllo", TABLE_STRING, "jjjjjjjjjjjjjjjjj"));
720

721
        ASSERT_OK(table_set_json_field_name(t, 1, "DIMPFELMOSER"));
1✔
722
        ASSERT_OK(table_set_json_field_name(t, 1, NULL));
1✔
723
        ASSERT_OK(table_set_json_field_name(t, 1, "dimpfelmoser"));
1✔
724

725
        ASSERT_OK(table_format(t, &formatted));
1✔
726

727
        ASSERT_STREQ(formatted,
1✔
728
                     "     pfft aa: foo\n"
729
                     "       uuu o: 1K\n"
730
                     "        quux: asdf\n"
731
                     "lllllllllllo: jjjjjjjjjjjjjjjjj\n");
732

733
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *a = NULL, *b = NULL;
2✔
734
        ASSERT_OK(table_to_json(t, &a));
1✔
735

736
        ASSERT_OK(sd_json_build(&b, SD_JSON_BUILD_OBJECT(
1✔
737
                                             SD_JSON_BUILD_PAIR("pfft_aa", SD_JSON_BUILD_STRING("foo")),
738
                                             SD_JSON_BUILD_PAIR("dimpfelmoser", SD_JSON_BUILD_UNSIGNED(1024)),
739
                                             SD_JSON_BUILD_PAIR("custom-quux", SD_JSON_BUILD_STRING("asdf")),
740
                                             SD_JSON_BUILD_PAIR("lllllllllllo", SD_JSON_BUILD_STRING("jjjjjjjjjjjjjjjjj")))));
741

742
        ASSERT_TRUE(sd_json_variant_equal(a, b));
1✔
743
}
1✔
744

745
TEST(path_basename) {
1✔
746
        _cleanup_(table_unrefp) Table *t = NULL;
×
747
        _cleanup_free_ char *formatted = NULL;
1✔
748

749
        ASSERT_NOT_NULL((t = table_new("x")));
1✔
750

751
        table_set_header(t, false);
1✔
752

753
        ASSERT_OK(table_add_many(t,
1✔
754
                                 TABLE_PATH_BASENAME, "/foo/bar",
755
                                 TABLE_PATH_BASENAME, "/quux/bar",
756
                                 TABLE_PATH_BASENAME, "/foo/baz"));
757

758
        ASSERT_OK(table_format(t, &formatted));
1✔
759

760
        ASSERT_STREQ(formatted, "bar\nbar\nbaz\n");
1✔
761
}
1✔
762

763
TEST(dup_cell) {
1✔
764
        _cleanup_(table_unrefp) Table *t = NULL;
×
765
        _cleanup_free_ char *formatted = NULL;
1✔
766

767
        ASSERT_NOT_NULL((t = table_new("foo", "bar", "x", "baz", ".", "%", "!", "~", "+")));
1✔
768
        table_set_width(t, 75);
1✔
769

770
        ASSERT_OK(table_add_many(t,
1✔
771
                                 TABLE_STRING, "hello",
772
                                 TABLE_UINT8, UINT8_C(42),
773
                                 TABLE_UINT16, UINT16_C(666),
774
                                 TABLE_UINT32, UINT32_C(253),
775
                                 TABLE_PERCENT, 0,
776
                                 TABLE_PATH_BASENAME, "/foo/bar",
777
                                 TABLE_STRING, "aaa",
778
                                 TABLE_STRING, "bbb",
779
                                 TABLE_STRING, "ccc"));
780

781
        /* Add the second row by duping cells */
782
        for (size_t i = 0; i < table_get_columns(t); i++)
10✔
783
                ASSERT_OK(table_dup_cell(t, table_get_cell(t, 1, i)));
9✔
784

785
        /* Another row, but dupe the last three strings from the same cell */
786
        ASSERT_OK(table_add_many(t,
1✔
787
                                 TABLE_STRING, "aaa",
788
                                 TABLE_UINT8, UINT8_C(0),
789
                                 TABLE_UINT16, UINT16_C(65535),
790
                                 TABLE_UINT32, UINT32_C(4294967295),
791
                                 TABLE_PERCENT, 100,
792
                                 TABLE_PATH_BASENAME, "../"));
793

794
        for (size_t i = 6; i < table_get_columns(t); i++)
4✔
795
                ASSERT_OK(table_dup_cell(t, table_get_cell(t, 2, 0)));
3✔
796

797
        ASSERT_OK(table_format(t, &formatted));
1✔
798
        printf("%s\n", formatted);
1✔
799
        ASSERT_STREQ(formatted,
1✔
800
                     "FOO     BAR   X       BAZ          .      %      !        ~        +\n"
801
                     "hello   42    666     253          0%     bar    aaa      bbb      ccc\n"
802
                     "hello   42    666     253          0%     bar    aaa      bbb      ccc\n"
803
                     "aaa     0     65535   4294967295   100%   ../    hello    hello    hello\n");
804
}
1✔
805

806
TEST(table_bps) {
1✔
807
        _cleanup_(table_unrefp) Table *table = NULL;
×
808
        _cleanup_free_ char *formatted = NULL;
1✔
809

810
        ASSERT_NOT_NULL((table = table_new("uint64", "size", "bps")));
1✔
811
        uint64_t v;
1✔
812
        FOREACH_ARGUMENT(v,
8✔
813
                         2500,
814
                         10000000,
815
                         20000000,
816
                         25000000,
817
                         1000000000,
818
                         2000000000,
819
                         2500000000)
820
                ASSERT_OK(table_add_many(table,
7✔
821
                                         TABLE_UINT64, v,
822
                                         TABLE_SIZE, v,
823
                                         TABLE_BPS, v));
824

825
        table_set_width(table, 50);
1✔
826
        ASSERT_OK(table_format(table, &formatted));
1✔
827

828
        printf("%s", formatted);
1✔
829
        ASSERT_STREQ(formatted,
1✔
830
                     "UINT64             SIZE           BPS\n"
831
                     "2500               2.4K           2.5Kbps\n"
832
                     "10000000           9.5M           10Mbps\n"
833
                     "20000000           19M            20Mbps\n"
834
                     "25000000           23.8M          25Mbps\n"
835
                     "1000000000         953.6M         1Gbps\n"
836
                     "2000000000         1.8G           2Gbps\n"
837
                     "2500000000         2.3G           2.5Gbps\n");
838
}
1✔
839

840
TEST(table_ansi) {
1✔
841
        _cleanup_(table_unrefp) Table *table = NULL;
×
842

843
        ASSERT_NOT_NULL((table = table_new("foo", "bar", "baz", "kkk")));
1✔
844

845
        ASSERT_OK(table_add_many(table,
1✔
846
                                 TABLE_STRING, "hallo",
847
                                 TABLE_STRING_WITH_ANSI, "knuerz" ANSI_HIGHLIGHT_RED "red" ANSI_HIGHLIGHT_GREEN "green",
848
                                 TABLE_STRING_WITH_ANSI, "noansi",
849
                                 TABLE_STRING_WITH_ANSI, ANSI_GREY "thisisgrey"));
850

851
        unsigned saved_columns = columns();
1✔
UNCOV
852
        _cleanup_free_ char *saved_term = NULL, *saved_color = NULL;
×
853
        const char *e;
1✔
854

855
        e = getenv("TERM");
1✔
856
        if (e)
1✔
UNCOV
857
                ASSERT_NOT_NULL((saved_term = strdup(e)));
×
858
        e = getenv("SYSTEMD_COLORS");
1✔
859
        if (e)
1✔
860
                ASSERT_NOT_NULL((saved_color = strdup(e)));
1✔
861

862
        ASSERT_OK_ERRNO(setenv("COLUMNS", "200", /* overwrite= */ true));
1✔
863
        ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "24bit", /* overwrite= */ true));
1✔
864
        ASSERT_OK_ERRNO(setenv("TERM", FALLBACK_TERM, /* overwrite= */ true));
1✔
865
        reset_terminal_feature_caches();
1✔
866

867
        _cleanup_free_ char *formatted = NULL;
1✔
868
        ASSERT_OK(table_format(table, &formatted));
1✔
869

870
        ASSERT_STREQ(formatted,
1✔
871
                     ANSI_ADD_UNDERLINE "FOO  " ANSI_NORMAL
872
                     ANSI_ADD_UNDERLINE " " ANSI_NORMAL
873
                     ANSI_ADD_UNDERLINE "BAR           " ANSI_NORMAL
874
                     ANSI_ADD_UNDERLINE " " ANSI_NORMAL
875
                     ANSI_ADD_UNDERLINE "BAZ   " ANSI_NORMAL
876
                     ANSI_ADD_UNDERLINE " " ANSI_NORMAL
877
                     ANSI_ADD_UNDERLINE "KKK       " ANSI_NORMAL "\n"
878
                     "hallo knuerz" ANSI_HIGHLIGHT_RED "red" ANSI_HIGHLIGHT_GREEN "green" ANSI_NORMAL
879
                     " noansi" ANSI_NORMAL
880
                     " " ANSI_GREY "thisisgrey" ANSI_NORMAL "\n");
881

882
        /* Validate that color is correctly stripped */
883
        ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "0", /* overwrite= */ true));
1✔
884
        reset_terminal_feature_caches();
1✔
885

886
        formatted = mfree(formatted);
1✔
887
        ASSERT_OK(table_format(table, &formatted));
1✔
888

889
        ASSERT_STREQ(formatted,
1✔
890
                     "FOO   BAR            BAZ    KKK\n"
891
                     "hallo knuerzredgreen noansi thisisgrey\n");
892

893
        ASSERT_OK(table_print(table, /* f= */ NULL));
1✔
894

895
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL, *jj = NULL;
2✔
896

897
        ASSERT_OK(table_to_json(table, &j));
1✔
898

899
        ASSERT_OK(sd_json_build(&jj,
1✔
900
                                SD_JSON_BUILD_ARRAY(
901
                                                SD_JSON_BUILD_OBJECT(
902
                                                                SD_JSON_BUILD_PAIR_STRING("foo", "hallo"),
903
                                                                SD_JSON_BUILD_PAIR_STRING("bar", "knuerzredgreen"),
904
                                                                SD_JSON_BUILD_PAIR_STRING("baz", "noansi"),
905
                                                                SD_JSON_BUILD_PAIR_STRING("kkk", "thisisgrey")))));
906
        ASSERT_TRUE(sd_json_variant_equal(j, jj));
1✔
907

908
        ASSERT_OK(sd_json_variant_dump(j, SD_JSON_FORMAT_COLOR_AUTO|SD_JSON_FORMAT_PRETTY_AUTO, /* f= */ NULL, /* prefix= */ NULL));
1✔
909

910
        ASSERT_OK(setenvf("COLUMNS", /* overwrite= */ true, "%u", saved_columns));
1✔
911
        ASSERT_OK(set_unset_env("SYSTEMD_COLORS", saved_color, /* overwrite= */ true));
1✔
912
        ASSERT_OK(set_unset_env("TERM", saved_term, /* overwrite= */ true));
1✔
913
}
1✔
914

915
static int intro(void) {
1✔
916
        ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "0", /* overwrite= */ true));
1✔
917
        ASSERT_OK_ERRNO(setenv("COLUMNS", "40", /* overwrite= */ true));
1✔
918
        return EXIT_SUCCESS;
1✔
919
}
920

921
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc