1
16
17 package printers
18
19 import (
20 "bytes"
21 "regexp"
22 "testing"
23
24 corev1 "k8s.io/api/core/v1"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/runtime/schema"
29 )
30
31 var testPodName = "test-pod-name"
32 var testPodNamespace = "test-namespace"
33
34 var testPod = &corev1.Pod{
35 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
36 ObjectMeta: metav1.ObjectMeta{
37 Name: testPodName,
38 Namespace: testPodNamespace,
39 Labels: map[string]string{
40 "first-label": "12",
41 "second-label": "label-value",
42 },
43 },
44 }
45
46 var testStatus = &metav1.Status{
47 TypeMeta: metav1.TypeMeta{APIVersion: "metav1", Kind: "Status"},
48 Status: "Failure",
49 Message: "test-status-message",
50 Reason: "test-status-reason",
51 }
52
53 func TestPrintTable_MissingColumnsRows(t *testing.T) {
54 tests := []struct {
55 columns []metav1.TableColumnDefinition
56 rows []metav1.TableRow
57 options PrintOptions
58 expected string
59 }{
60
61 {
62 columns: []metav1.TableColumnDefinition{},
63 rows: []metav1.TableRow{},
64 options: PrintOptions{},
65 expected: "",
66 },
67
68 {
69 columns: []metav1.TableColumnDefinition{
70 {Name: "Name", Type: "string"},
71 {Name: "Ready", Type: "string"},
72 {Name: "Status", Type: "string"},
73 {Name: "Retries", Type: "integer"},
74 {Name: "Age", Type: "string"},
75 },
76 rows: []metav1.TableRow{},
77 options: PrintOptions{},
78 expected: "",
79 },
80 }
81
82 for _, test := range tests {
83
84 table := &metav1.Table{
85 ColumnDefinitions: test.columns,
86 Rows: test.rows,
87 }
88
89 out := bytes.NewBuffer([]byte{})
90 printer := NewTablePrinter(test.options)
91 printer.PrintObj(table, out)
92
93
94 if len(out.String()) > 0 {
95 t.Errorf("Error Printing Table. Should be empty; got (%s)", out.String())
96 }
97 }
98 }
99
100 func TestPrintTable_ColumnPriority(t *testing.T) {
101 tests := []struct {
102 columns []metav1.TableColumnDefinition
103 rows []metav1.TableRow
104 options PrintOptions
105 expected string
106 }{
107
108 {
109 columns: []metav1.TableColumnDefinition{
110 {Name: "Name", Type: "string"},
111 {Name: "Ready", Type: "string"},
112 {Name: "Status", Type: "string"},
113 {Name: "Retries", Type: "integer", Priority: 1},
114 {Name: "Age", Type: "string", Priority: 1},
115 },
116 rows: []metav1.TableRow{
117 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
118 },
119 options: PrintOptions{},
120 expected: "NAME READY STATUS\ntest1 1/1 podPhase\n",
121 },
122
123 {
124 columns: []metav1.TableColumnDefinition{
125 {Name: "Name", Type: "string"},
126 {Name: "Ready", Type: "string"},
127 {Name: "Status", Type: "string"},
128 {Name: "Retries", Type: "integer", Priority: 1},
129 {Name: "Age", Type: "string", Priority: 1},
130 },
131 rows: []metav1.TableRow{
132 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
133 {Cells: []interface{}{"test2", "1/2", "podPhase", int64(30), "21h"}},
134 {Cells: []interface{}{"test3", "4/4", "podPhase", int64(1), "22h"}},
135 },
136 options: PrintOptions{},
137 expected: `NAME READY STATUS
138 test1 1/1 podPhase
139 test2 1/2 podPhase
140 test3 4/4 podPhase
141 `,
142 },
143
144 {
145 columns: []metav1.TableColumnDefinition{
146 {Name: "Name", Type: "string"},
147 {Name: "Ready", Type: "string"},
148 {Name: "Status", Type: "string"},
149 {Name: "Retries", Type: "integer", Priority: 1},
150 {Name: "Age", Type: "string", Priority: 1},
151 },
152 rows: []metav1.TableRow{
153 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
154 },
155
156 options: PrintOptions{Wide: true},
157 expected: "NAME READY STATUS RETRIES AGE\ntest1 1/1 podPhase 5 20h\n",
158 },
159
160 {
161 columns: []metav1.TableColumnDefinition{
162 {Name: "Name", Type: "string"},
163 {Name: "Ready", Type: "string"},
164 {Name: "Status", Type: "string"},
165 {Name: "Retries", Type: "integer", Priority: 1},
166 {Name: "Age", Type: "string", Priority: 1},
167 },
168 rows: []metav1.TableRow{
169 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
170 {Cells: []interface{}{"test2", "1/2", "podPhase", int64(30), "21h"}},
171 {Cells: []interface{}{"test3", "4/4", "podPhase", int64(1), "22h"}},
172 },
173 options: PrintOptions{Wide: true},
174 expected: `NAME READY STATUS RETRIES AGE
175 test1 1/1 podPhase 5 20h
176 test2 1/2 podPhase 30 21h
177 test3 4/4 podPhase 1 22h
178 `,
179 },
180 }
181 for _, test := range tests {
182
183 table := &metav1.Table{
184 ColumnDefinitions: test.columns,
185 Rows: test.rows,
186 }
187
188 out := bytes.NewBuffer([]byte{})
189 printer := NewTablePrinter(test.options)
190 printer.PrintObj(table, out)
191
192 if test.expected != out.String() {
193 t.Errorf("Table printing error: expected (%s), got (%s)", test.expected, out.String())
194 }
195 }
196 }
197
198 func TestPrintTable_ColumnHeaders(t *testing.T) {
199 tests := []struct {
200 columns []metav1.TableColumnDefinition
201 rows []metav1.TableRow
202 options PrintOptions
203 expected string
204 }{
205
206 {
207 columns: []metav1.TableColumnDefinition{
208 {Name: "Name", Type: "string"},
209 {Name: "Ready", Type: "string"},
210 {Name: "Status", Type: "string"},
211 {Name: "Retries", Type: "integer"},
212 {Name: "Age", Type: "string"},
213 },
214 rows: []metav1.TableRow{
215 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
216 },
217 options: PrintOptions{},
218 expected: "NAME READY STATUS RETRIES AGE\ntest1 1/1 podPhase 5 20h\n",
219 },
220
221 {
222 columns: []metav1.TableColumnDefinition{
223 {Name: "Name", Type: "string"},
224 {Name: "Ready", Type: "string"},
225 {Name: "Status", Type: "string"},
226 {Name: "Retries", Type: "integer"},
227 {Name: "Age", Type: "string"},
228 },
229 rows: []metav1.TableRow{
230 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
231 {Cells: []interface{}{"test2", "1/2", "podPhase", int64(30), "21h"}},
232 {Cells: []interface{}{"test3", "4/4", "podPhase", int64(1), "22h"}},
233 },
234 options: PrintOptions{},
235 expected: `NAME READY STATUS RETRIES AGE
236 test1 1/1 podPhase 5 20h
237 test2 1/2 podPhase 30 21h
238 test3 4/4 podPhase 1 22h
239 `,
240 },
241
242 {
243 columns: []metav1.TableColumnDefinition{
244 {Name: "Name", Type: "string"},
245 {Name: "Ready", Type: "string"},
246 {Name: "Status", Type: "string"},
247 {Name: "Retries", Type: "integer"},
248 {Name: "Age", Type: "string"},
249 },
250 rows: []metav1.TableRow{
251 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
252 },
253
254 options: PrintOptions{NoHeaders: true},
255 expected: "test1 1/1 podPhase 5 20h\n",
256 },
257
258 {
259 columns: []metav1.TableColumnDefinition{
260 {Name: "Name", Type: "string"},
261 {Name: "Ready", Type: "string"},
262 {Name: "Status", Type: "string"},
263 {Name: "Retries", Type: "integer"},
264 {Name: "Age", Type: "string"},
265 },
266 rows: []metav1.TableRow{
267 {Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"}},
268 {Cells: []interface{}{"test2", "1/2", "podPhase", int64(30), "21h"}},
269 {Cells: []interface{}{"test3", "4/4", "podPhase", int64(1), "22h"}},
270 },
271 options: PrintOptions{NoHeaders: true},
272 expected: `test1 1/1 podPhase 5 20h
273 test2 1/2 podPhase 30 21h
274 test3 4/4 podPhase 1 22h
275 `,
276 },
277 }
278 for _, test := range tests {
279
280 table := &metav1.Table{
281 ColumnDefinitions: test.columns,
282 Rows: test.rows,
283 }
284
285 out := bytes.NewBuffer([]byte{})
286 printer := NewTablePrinter(test.options)
287 printer.PrintObj(table, out)
288
289 if test.expected != out.String() {
290 t.Errorf("Table printing error: expected (%s), got (%s)", test.expected, out.String())
291 }
292 }
293 }
294
295 func TestPrintTable_WithNamespace(t *testing.T) {
296 tests := []struct {
297 columns []metav1.TableColumnDefinition
298 rows []metav1.TableRow
299 options PrintOptions
300 expected string
301 }{
302
303 {
304 columns: []metav1.TableColumnDefinition{
305 {Name: "Name", Type: "string"},
306 {Name: "Ready", Type: "string"},
307 {Name: "Status", Type: "string"},
308 {Name: "Retries", Type: "integer"},
309 {Name: "Age", Type: "string"},
310 },
311 rows: []metav1.TableRow{
312 {
313 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
314 Object: runtime.RawExtension{Object: testPod},
315 },
316 },
317
318 options: PrintOptions{WithNamespace: true},
319 expected: `NAMESPACE NAME READY STATUS RETRIES AGE
320 test-namespace test1 1/1 podPhase 5 20h
321 `,
322 },
323 }
324 for _, test := range tests {
325
326 table := &metav1.Table{
327 ColumnDefinitions: test.columns,
328 Rows: test.rows,
329 }
330
331 out := bytes.NewBuffer([]byte{})
332 printer := NewTablePrinter(test.options)
333 printer.PrintObj(table, out)
334
335 if test.expected != out.String() {
336 t.Errorf("Table printing error: expected (%s), got (%s)", test.expected, out.String())
337 }
338 }
339 }
340
341 func TestPrintTable_WithKind(t *testing.T) {
342 tests := []struct {
343 columns []metav1.TableColumnDefinition
344 rows []metav1.TableRow
345 options PrintOptions
346 expected string
347 }{
348
349 {
350 columns: []metav1.TableColumnDefinition{
351 {Name: "Name", Type: "string", Format: "name"},
352 {Name: "Ready", Type: "string"},
353 {Name: "Status", Type: "string"},
354 {Name: "Retries", Type: "integer"},
355 {Name: "Age", Type: "string"},
356 },
357 rows: []metav1.TableRow{
358 {
359 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
360 },
361 },
362
363 options: PrintOptions{WithKind: true, Kind: schema.GroupKind{Kind: "Pod"}},
364 expected: `NAME READY STATUS RETRIES AGE
365 pod/test1 1/1 podPhase 5 20h
366 `,
367 },
368 }
369 for _, test := range tests {
370
371 table := &metav1.Table{
372 ColumnDefinitions: test.columns,
373 Rows: test.rows,
374 }
375
376 out := bytes.NewBuffer([]byte{})
377 printer := NewTablePrinter(test.options)
378 printer.PrintObj(table, out)
379
380 if test.expected != out.String() {
381 t.Errorf("Table printing error: expected (%s), got (%s)", test.expected, out.String())
382 }
383 }
384 }
385
386 func TestPrintTable_WithLabels(t *testing.T) {
387 tests := []struct {
388 columns []metav1.TableColumnDefinition
389 rows []metav1.TableRow
390 options PrintOptions
391 expected string
392 }{
393
394 {
395 columns: []metav1.TableColumnDefinition{
396 {Name: "Name", Type: "string"},
397 {Name: "Ready", Type: "string"},
398 {Name: "Status", Type: "string"},
399 {Name: "Retries", Type: "integer"},
400 {Name: "Age", Type: "string"},
401 },
402 rows: []metav1.TableRow{
403 {
404 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
405 Object: runtime.RawExtension{Object: testPod},
406 },
407 },
408 options: PrintOptions{ShowLabels: true},
409 expected: `NAME READY STATUS RETRIES AGE LABELS
410 test1 1/1 podPhase 5 20h first-label=12,second-label=label-value
411 `,
412 },
413
414 {
415 columns: []metav1.TableColumnDefinition{
416 {Name: "Name", Type: "string"},
417 {Name: "Ready", Type: "string"},
418 {Name: "Status", Type: "string"},
419 {Name: "Retries", Type: "integer"},
420 {Name: "Age", Type: "string"},
421 },
422 rows: []metav1.TableRow{
423 {
424 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
425 Object: runtime.RawExtension{Object: testPod},
426 },
427 },
428
429 options: PrintOptions{ColumnLabels: []string{"second-label"}},
430 expected: `NAME READY STATUS RETRIES AGE SECOND-LABEL
431 test1 1/1 podPhase 5 20h label-value
432 `,
433 },
434
435 {
436 columns: []metav1.TableColumnDefinition{
437 {Name: "Name", Type: "string"},
438 {Name: "Ready", Type: "string"},
439 {Name: "Status", Type: "string"},
440 {Name: "Retries", Type: "integer"},
441 {Name: "Age", Type: "string"},
442 },
443 rows: []metav1.TableRow{
444 {
445 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
446 Object: runtime.RawExtension{Object: testPod},
447 },
448 },
449
450 options: PrintOptions{ColumnLabels: []string{"first-label", "second-label"}},
451 expected: `NAME READY STATUS RETRIES AGE FIRST-LABEL SECOND-LABEL
452 test1 1/1 podPhase 5 20h 12 label-value
453 `,
454 },
455 }
456 for _, test := range tests {
457
458 table := &metav1.Table{
459 ColumnDefinitions: test.columns,
460 Rows: test.rows,
461 }
462
463 out := bytes.NewBuffer([]byte{})
464 printer := NewTablePrinter(test.options)
465 printer.PrintObj(table, out)
466
467 if test.expected != out.String() {
468 t.Errorf("Table printing error: expected (%s), got (%s)", test.expected, out.String())
469 }
470 }
471 }
472
473 func TestPrintTable_NonTable(t *testing.T) {
474 tests := []struct {
475 object runtime.Object
476 options PrintOptions
477 expected string
478 }{
479
480 {
481 object: testPod,
482 options: PrintOptions{},
483 expected: "NAME AGE\ntest-pod-name <unknown>\n",
484 },
485
486 {
487 object: testPod,
488 options: PrintOptions{NoHeaders: true},
489 expected: "test-pod-name <unknown>\n",
490 },
491
492 {
493 object: testPod,
494 options: PrintOptions{WithNamespace: true},
495 expected: "NAMESPACE NAME AGE\ntest-namespace test-pod-name <unknown>\n",
496 },
497
498 {
499 object: testPod,
500 options: PrintOptions{ShowLabels: true},
501 expected: `NAME AGE LABELS
502 test-pod-name <unknown> first-label=12,second-label=label-value
503 `,
504 },
505
506 {
507 object: testStatus,
508 options: PrintOptions{},
509 expected: `STATUS REASON MESSAGE
510 Failure test-status-reason test-status-message
511 `,
512 },
513
514 {
515 object: testStatus,
516 options: PrintOptions{NoHeaders: true},
517 expected: "Failure test-status-reason test-status-message\n",
518 },
519 }
520 for _, test := range tests {
521
522 out := bytes.NewBuffer([]byte{})
523 printer := NewTablePrinter(test.options)
524 printer.PrintObj(test.object, out)
525
526 if test.expected != out.String() {
527 t.Errorf("Table printing error: expected (%s), got (%s)", test.expected, out.String())
528 }
529 }
530 }
531
532 func TestPrintTable_WatchEvents(t *testing.T) {
533 tests := []struct {
534 columns []metav1.TableColumnDefinition
535 rows []metav1.TableRow
536 options PrintOptions
537 expected string
538 }{
539
540 {
541 columns: []metav1.TableColumnDefinition{
542 {Name: "Name", Type: "string"},
543 {Name: "Ready", Type: "string"},
544 {Name: "Status", Type: "string"},
545 {Name: "Retries", Type: "integer"},
546 {Name: "Age", Type: "string"},
547 },
548 rows: []metav1.TableRow{
549 {
550 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
551 Object: runtime.RawExtension{Object: testPod},
552 },
553 },
554 options: PrintOptions{},
555 expected: `EVENT NAME READY STATUS RETRIES AGE
556 Added test1 1/1 podPhase 5 20h
557 `,
558 },
559
560 {
561 columns: []metav1.TableColumnDefinition{
562 {Name: "Name", Type: "string"},
563 {Name: "Ready", Type: "string"},
564 {Name: "Status", Type: "string"},
565 {Name: "Retries", Type: "integer"},
566 {Name: "Age", Type: "string"},
567 },
568 rows: []metav1.TableRow{
569 {
570 Cells: []interface{}{"test1", "1/1", "podPhase", int64(5), "20h"},
571 Object: runtime.RawExtension{Object: testPod},
572 },
573 },
574 options: PrintOptions{NoHeaders: true, WithNamespace: true, ShowLabels: true},
575 expected: "Added test-namespace test1 1/1 podPhase 5 20h first-label=12,second-label=label-value\n",
576 },
577 }
578 for _, test := range tests {
579
580 table := &metav1.Table{
581 ColumnDefinitions: test.columns,
582 Rows: test.rows,
583 }
584
585 event := &metav1.WatchEvent{
586 Type: "Added",
587 Object: runtime.RawExtension{Object: table},
588 }
589
590 out := bytes.NewBuffer([]byte{})
591 printer := NewTablePrinter(test.options)
592 printer.PrintObj(event, out)
593
594 if test.expected != out.String() {
595 t.Errorf("Event/Table printing error: expected (%s), got (%s)", test.expected, out.String())
596 }
597 }
598 }
599
600 func TestPrintUnstructuredObject(t *testing.T) {
601 obj := &unstructured.Unstructured{
602 Object: map[string]interface{}{
603 "apiVersion": "v1",
604 "kind": "Test",
605 "dummy1": "present",
606 "dummy2": "present",
607 "metadata": map[string]interface{}{
608 "name": "MyName",
609 "namespace": "MyNamespace",
610 "creationTimestamp": "2017-04-01T00:00:00Z",
611 "resourceVersion": 123,
612 "uid": "00000000-0000-0000-0000-000000000001",
613 "dummy3": "present",
614 "labels": map[string]interface{}{"test": "other"},
615 },
616
622 "url": "http://localhost",
623 "status": "ok",
624 },
625 }
626
627 tests := []struct {
628 expected string
629 options PrintOptions
630 object runtime.Object
631 }{
632 {
633 expected: "NAME\\s+AGE\nMyName\\s+\\d+",
634 object: obj,
635 },
636 {
637 options: PrintOptions{
638 WithNamespace: true,
639 },
640 expected: "NAMESPACE\\s+NAME\\s+AGE\nMyNamespace\\s+MyName\\s+\\d+",
641 object: obj,
642 },
643 {
644 options: PrintOptions{
645 ShowLabels: true,
646 WithNamespace: true,
647 },
648 expected: "NAMESPACE\\s+NAME\\s+AGE\\s+LABELS\nMyNamespace\\s+MyName\\s+\\d+\\w+\\s+test\\=other",
649 object: obj,
650 },
651 {
652 expected: "NAME\\s+AGE\nMyName\\s+\\d+\\w+\nMyName2\\s+\\d+",
653 object: &unstructured.Unstructured{
654 Object: map[string]interface{}{
655 "apiVersion": "v1",
656 "kind": "Test",
657 "dummy1": "present",
658 "dummy2": "present",
659 "items": []interface{}{
660 map[string]interface{}{
661 "metadata": map[string]interface{}{
662 "name": "MyName",
663 "namespace": "MyNamespace",
664 "creationTimestamp": "2017-04-01T00:00:00Z",
665 "resourceVersion": 123,
666 "uid": "00000000-0000-0000-0000-000000000001",
667 "dummy3": "present",
668 "labels": map[string]interface{}{"test": "other"},
669 },
670 },
671 map[string]interface{}{
672 "metadata": map[string]interface{}{
673 "name": "MyName2",
674 "namespace": "MyNamespace",
675 "creationTimestamp": "2017-04-01T00:00:00Z",
676 "resourceVersion": 123,
677 "uid": "00000000-0000-0000-0000-000000000001",
678 "dummy3": "present",
679 "labels": "badlabel",
680 },
681 },
682 },
683 "url": "http://localhost",
684 "status": "ok",
685 },
686 },
687 },
688 }
689 out := bytes.NewBuffer([]byte{})
690
691 for _, test := range tests {
692 out.Reset()
693 printer := NewTablePrinter(test.options)
694 printer.PrintObj(test.object, out)
695
696 matches, err := regexp.MatchString(test.expected, out.String())
697 if err != nil {
698 t.Fatalf("unexpected error: %v", err)
699 }
700 if !matches {
701 t.Errorf("wanted:\n%s\ngot:\n%s", test.expected, out)
702 }
703 }
704 }
705
706 type TestUnknownType struct{}
707
708 func (obj *TestUnknownType) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
709 func (obj *TestUnknownType) DeepCopyObject() runtime.Object {
710 if obj == nil {
711 return nil
712 }
713 clone := *obj
714 return &clone
715 }
716
717 func TestUnknownTypePrinting(t *testing.T) {
718 printer := NewTablePrinter(PrintOptions{})
719 buffer := &bytes.Buffer{}
720 err := printer.PrintObj(&TestUnknownType{}, buffer)
721 if err == nil {
722 t.Errorf("An error was expected from printing unknown type")
723 }
724 }
725
726 func TestStringPrinting(t *testing.T) {
727 tests := []struct {
728 columns []metav1.TableColumnDefinition
729 rows []metav1.TableRow
730 expected string
731 }{
732
733 {
734 columns: []metav1.TableColumnDefinition{
735 {Name: "Name", Type: "string"},
736 {Name: "Age", Type: "string"},
737 {Name: "Description", Type: "string"},
738 },
739 rows: []metav1.TableRow{
740 {Cells: []interface{}{"test1", "20h", "This is first line\nThis is second line\nThis is third line\nand another one\n"}},
741 },
742 expected: `NAME AGE DESCRIPTION
743 test1 20h This is first line...
744 `,
745 },
746
747 {
748 columns: []metav1.TableColumnDefinition{
749 {Name: "Name", Type: "string"},
750 {Name: "Age", Type: "string"},
751 {Name: "Description", Type: "string"},
752 },
753 rows: []metav1.TableRow{
754 {Cells: []interface{}{"test1", "20h", "This is first line which is long and goes for on and on and on an on and on and on and on and on and on and on and on and on and on and on"}},
755 },
756 expected: `NAME AGE DESCRIPTION
757 test1 20h This is first line which is long and goes for on and on and on an on and on and on and on and on and on and on and on and on and on and on
758 `,
759 },
760
761 {
762 columns: []metav1.TableColumnDefinition{
763 {Name: "Name", Type: "string"},
764 {Name: "Age", Type: "string"},
765 {Name: "Description", Type: "string"},
766 },
767 rows: []metav1.TableRow{
768 {Cells: []interface{}{"test1", "20h", "This is first\n line which is long and goes for on and on and on an on and on and on and on and on and on and on and on and on and on and on"}},
769 },
770 expected: `NAME AGE DESCRIPTION
771 test1 20h This is first...
772 `,
773 },
774
775 {
776 columns: []metav1.TableColumnDefinition{
777 {Name: "Name", Type: "string"},
778 },
779 rows: []metav1.TableRow{
780 {Cells: []interface{}{"test1\x1b"}},
781 },
782 expected: `NAME
783 test1^[
784 `,
785 },
786 }
787
788 for _, test := range tests {
789
790 table := &metav1.Table{
791 ColumnDefinitions: test.columns,
792 Rows: test.rows,
793 }
794
795 out := bytes.NewBuffer([]byte{})
796 printer := NewTablePrinter(PrintOptions{})
797 printer.PrintObj(table, out)
798
799 if test.expected != out.String() {
800 t.Errorf("Table printing error: expected \n(%s), got \n(%s)", test.expected, out.String())
801 }
802 }
803 }
804
View as plain text