1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements.  See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership.  The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License.  You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied.  See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 #include <cstdint>
19 #include <cstring>
20 #include <memory>
21 #include <sstream>
22 #include <string>
23 #include <vector>
24 
25 #include <gtest/gtest.h>
26 
27 #include "arrow/array.h"
28 #include "arrow/builder.h"
29 #include "arrow/pretty_print.h"
30 #include "arrow/table.h"
31 #include "arrow/testing/gtest_util.h"
32 #include "arrow/type.h"
33 #include "arrow/util/key_value_metadata.h"
34 
35 namespace arrow {
36 
37 class TestPrettyPrint : public ::testing::Test {
38  public:
SetUp()39   void SetUp() {}
40 
Print(const Array & array)41   void Print(const Array& array) {}
42 
43  private:
44   std::ostringstream sink_;
45 };
46 
47 template <typename T>
CheckStream(const T & obj,const PrettyPrintOptions & options,const char * expected)48 void CheckStream(const T& obj, const PrettyPrintOptions& options, const char* expected) {
49   std::ostringstream sink;
50   ASSERT_OK(PrettyPrint(obj, options, &sink));
51   std::string result = sink.str();
52   ASSERT_EQ(std::string(expected, strlen(expected)), result);
53 }
54 
CheckArray(const Array & arr,const PrettyPrintOptions & options,const char * expected,bool check_operator=true)55 void CheckArray(const Array& arr, const PrettyPrintOptions& options, const char* expected,
56                 bool check_operator = true) {
57   CheckStream(arr, options, expected);
58 
59   if (options.indent == 0 && check_operator) {
60     std::stringstream ss;
61     ss << arr;
62     std::string result = std::string(expected, strlen(expected));
63     ASSERT_EQ(result, ss.str());
64   }
65 }
66 
67 template <typename T>
Check(const T & obj,const PrettyPrintOptions & options,const char * expected)68 void Check(const T& obj, const PrettyPrintOptions& options, const char* expected) {
69   std::string result;
70   ASSERT_OK(PrettyPrint(obj, options, &result));
71   ASSERT_EQ(std::string(expected, strlen(expected)), result);
72 }
73 
74 template <typename TYPE, typename C_TYPE>
CheckPrimitive(const std::shared_ptr<DataType> & type,const PrettyPrintOptions & options,const std::vector<bool> & is_valid,const std::vector<C_TYPE> & values,const char * expected,bool check_operator=true)75 void CheckPrimitive(const std::shared_ptr<DataType>& type,
76                     const PrettyPrintOptions& options, const std::vector<bool>& is_valid,
77                     const std::vector<C_TYPE>& values, const char* expected,
78                     bool check_operator = true) {
79   std::shared_ptr<Array> array;
80   ArrayFromVector<TYPE, C_TYPE>(type, is_valid, values, &array);
81   CheckArray(*array, options, expected, check_operator);
82 }
83 
84 template <typename TYPE, typename C_TYPE>
CheckPrimitive(const PrettyPrintOptions & options,const std::vector<bool> & is_valid,const std::vector<C_TYPE> & values,const char * expected,bool check_operator=true)85 void CheckPrimitive(const PrettyPrintOptions& options, const std::vector<bool>& is_valid,
86                     const std::vector<C_TYPE>& values, const char* expected,
87                     bool check_operator = true) {
88   CheckPrimitive<TYPE, C_TYPE>(TypeTraits<TYPE>::type_singleton(), options, is_valid,
89                                values, expected, check_operator);
90 }
91 
TEST_F(TestPrettyPrint,PrimitiveType)92 TEST_F(TestPrettyPrint, PrimitiveType) {
93   std::vector<bool> is_valid = {true, true, false, true, false};
94 
95   std::vector<int32_t> values = {0, 1, 2, 3, 4};
96   static const char* expected = R"expected([
97   0,
98   1,
99   null,
100   3,
101   null
102 ])expected";
103   CheckPrimitive<Int32Type, int32_t>({0, 10}, is_valid, values, expected);
104 
105   static const char* expected_na = R"expected([
106   0,
107   1,
108   NA,
109   3,
110   NA
111 ])expected";
112   CheckPrimitive<Int32Type, int32_t>({0, 10, 2, "NA"}, is_valid, values, expected_na,
113                                      false);
114 
115   static const char* ex_in2 = R"expected(  [
116     0,
117     1,
118     null,
119     3,
120     null
121   ])expected";
122   CheckPrimitive<Int32Type, int32_t>({2, 10}, is_valid, values, ex_in2);
123   static const char* ex_in2_w2 = R"expected(  [
124     0,
125     1,
126     ...
127     3,
128     null
129   ])expected";
130   CheckPrimitive<Int32Type, int32_t>({2, 2}, is_valid, values, ex_in2_w2);
131 
132   std::vector<double> values2 = {0., 1., 2., 3., 4.};
133   static const char* ex2 = R"expected([
134   0,
135   1,
136   null,
137   3,
138   null
139 ])expected";
140   CheckPrimitive<DoubleType, double>({0, 10}, is_valid, values2, ex2);
141   static const char* ex2_in2 = R"expected(  [
142     0,
143     1,
144     null,
145     3,
146     null
147   ])expected";
148   CheckPrimitive<DoubleType, double>({2, 10}, is_valid, values2, ex2_in2);
149 
150   std::vector<std::string> values3 = {"foo", "bar", "", "baz", ""};
151   static const char* ex3 = R"expected([
152   "foo",
153   "bar",
154   null,
155   "baz",
156   null
157 ])expected";
158   CheckPrimitive<StringType, std::string>({0, 10}, is_valid, values3, ex3);
159   CheckPrimitive<LargeStringType, std::string>({0, 10}, is_valid, values3, ex3);
160   static const char* ex3_in2 = R"expected(  [
161     "foo",
162     "bar",
163     null,
164     "baz",
165     null
166   ])expected";
167   CheckPrimitive<StringType, std::string>({2, 10}, is_valid, values3, ex3_in2);
168   CheckPrimitive<LargeStringType, std::string>({2, 10}, is_valid, values3, ex3_in2);
169 }
170 
TEST_F(TestPrettyPrint,Int8)171 TEST_F(TestPrettyPrint, Int8) {
172   static const char* expected = R"expected([
173   0,
174   127,
175   -128
176 ])expected";
177   CheckPrimitive<Int8Type, int8_t>({0, 10}, {true, true, true}, {0, 127, -128}, expected);
178 }
179 
TEST_F(TestPrettyPrint,UInt8)180 TEST_F(TestPrettyPrint, UInt8) {
181   static const char* expected = R"expected([
182   0,
183   255
184 ])expected";
185   CheckPrimitive<UInt8Type, uint8_t>({0, 10}, {true, true}, {0, 255}, expected);
186 }
187 
TEST_F(TestPrettyPrint,Int64)188 TEST_F(TestPrettyPrint, Int64) {
189   static const char* expected = R"expected([
190   0,
191   9223372036854775807,
192   -9223372036854775808
193 ])expected";
194   CheckPrimitive<Int64Type, int64_t>(
195       {0, 10}, {true, true, true}, {0, 9223372036854775807LL, -9223372036854775807LL - 1},
196       expected);
197 }
198 
TEST_F(TestPrettyPrint,UInt64)199 TEST_F(TestPrettyPrint, UInt64) {
200   static const char* expected = R"expected([
201   0,
202   9223372036854775803,
203   18446744073709551615
204 ])expected";
205   CheckPrimitive<UInt64Type, uint64_t>(
206       {0, 10}, {true, true, true}, {0, 9223372036854775803ULL, 18446744073709551615ULL},
207       expected);
208 }
209 
TEST_F(TestPrettyPrint,DateTimeTypes)210 TEST_F(TestPrettyPrint, DateTimeTypes) {
211   std::vector<bool> is_valid = {true, true, false, true, false};
212 
213   {
214     std::vector<int32_t> values = {0, 1, 2, 31, 4};
215     static const char* expected = R"expected([
216   1970-01-01,
217   1970-01-02,
218   null,
219   1970-02-01,
220   null
221 ])expected";
222     CheckPrimitive<Date32Type, int32_t>({0, 10}, is_valid, values, expected);
223   }
224 
225   {
226     constexpr int64_t ms_per_day = 24 * 60 * 60 * 1000;
227     std::vector<int64_t> values = {0 * ms_per_day, 1 * ms_per_day, 2 * ms_per_day,
228                                    31 * ms_per_day, 4 * ms_per_day};
229     static const char* expected = R"expected([
230   1970-01-01,
231   1970-01-02,
232   null,
233   1970-02-01,
234   null
235 ])expected";
236     CheckPrimitive<Date64Type, int64_t>({0, 10}, is_valid, values, expected);
237   }
238 
239   {
240     std::vector<int64_t> values = {
241         0, 1, 2, 678 + 1000000 * (5 + 60 * (4 + 60 * (3 + 24 * int64_t(1)))), 4};
242     static const char* expected = R"expected([
243   1970-01-01 00:00:00.000000,
244   1970-01-01 00:00:00.000001,
245   null,
246   1970-01-02 03:04:05.000678,
247   null
248 ])expected";
249     CheckPrimitive<TimestampType, int64_t>(timestamp(TimeUnit::MICRO, "Transylvania"),
250                                            {0, 10}, is_valid, values, expected);
251   }
252 
253   {
254     std::vector<int32_t> values = {1, 62, 2, 3 + 60 * (2 + 60 * 1), 4};
255     static const char* expected = R"expected([
256   00:00:01,
257   00:01:02,
258   null,
259   01:02:03,
260   null
261 ])expected";
262     CheckPrimitive<Time32Type, int32_t>(time32(TimeUnit::SECOND), {0, 10}, is_valid,
263                                         values, expected);
264   }
265 
266   {
267     std::vector<int64_t> values = {
268         0, 1, 2, 678 + int64_t(1000000000) * (5 + 60 * (4 + 60 * 3)), 4};
269     static const char* expected = R"expected([
270   00:00:00.000000000,
271   00:00:00.000000001,
272   null,
273   03:04:05.000000678,
274   null
275 ])expected";
276     CheckPrimitive<Time64Type, int64_t>(time64(TimeUnit::NANO), {0, 10}, is_valid, values,
277                                         expected);
278   }
279 }
280 
TEST_F(TestPrettyPrint,StructTypeBasic)281 TEST_F(TestPrettyPrint, StructTypeBasic) {
282   auto simple_1 = field("one", int32());
283   auto simple_2 = field("two", int32());
284   auto simple_struct = struct_({simple_1, simple_2});
285 
286   auto array = ArrayFromJSON(simple_struct, "[[11, 22]]");
287 
288   static const char* ex = R"expected(-- is_valid: all not null
289 -- child 0 type: int32
290   [
291     11
292   ]
293 -- child 1 type: int32
294   [
295     22
296   ])expected";
297   CheckStream(*array, {0, 10}, ex);
298 
299   static const char* ex_2 = R"expected(  -- is_valid: all not null
300   -- child 0 type: int32
301     [
302       11
303     ]
304   -- child 1 type: int32
305     [
306       22
307     ])expected";
308   CheckStream(*array, {2, 10}, ex_2);
309 }
310 
TEST_F(TestPrettyPrint,StructTypeAdvanced)311 TEST_F(TestPrettyPrint, StructTypeAdvanced) {
312   auto simple_1 = field("one", int32());
313   auto simple_2 = field("two", int32());
314   auto simple_struct = struct_({simple_1, simple_2});
315 
316   auto array = ArrayFromJSON(simple_struct, "[[11, 22], null, [null, 33]]");
317 
318   static const char* ex = R"expected(-- is_valid:
319   [
320     true,
321     false,
322     true
323   ]
324 -- child 0 type: int32
325   [
326     11,
327     null,
328     null
329   ]
330 -- child 1 type: int32
331   [
332     22,
333     null,
334     33
335   ])expected";
336   CheckStream(*array, {0, 10}, ex);
337 }
338 
TEST_F(TestPrettyPrint,BinaryType)339 TEST_F(TestPrettyPrint, BinaryType) {
340   std::vector<bool> is_valid = {true, true, false, true, true, true};
341   std::vector<std::string> values = {"foo", "bar", "", "baz", "", "\xff"};
342   static const char* ex = "[\n  666F6F,\n  626172,\n  null,\n  62617A,\n  ,\n  FF\n]";
343   CheckPrimitive<BinaryType, std::string>({0}, is_valid, values, ex);
344   CheckPrimitive<LargeBinaryType, std::string>({0}, is_valid, values, ex);
345   static const char* ex_in2 =
346       "  [\n    666F6F,\n    626172,\n    null,\n    62617A,\n    ,\n    FF\n  ]";
347   CheckPrimitive<BinaryType, std::string>({2}, is_valid, values, ex_in2);
348   CheckPrimitive<LargeBinaryType, std::string>({2}, is_valid, values, ex_in2);
349 }
350 
TEST_F(TestPrettyPrint,ListType)351 TEST_F(TestPrettyPrint, ListType) {
352   auto list_type = list(int64());
353 
354   static const char* ex = R"expected([
355   [
356     null
357   ],
358   [],
359   null,
360   [
361     4,
362     6,
363     7
364   ],
365   [
366     2,
367     3
368   ]
369 ])expected";
370   static const char* ex_2 = R"expected(  [
371     [
372       null
373     ],
374     [],
375     null,
376     [
377       4,
378       6,
379       7
380     ],
381     [
382       2,
383       3
384     ]
385   ])expected";
386   static const char* ex_3 = R"expected([
387   [
388     null
389   ],
390   ...
391   [
392     2,
393     3
394   ]
395 ])expected";
396 
397   auto array = ArrayFromJSON(list_type, "[[null], [], null, [4, 6, 7], [2, 3]]");
398   CheckArray(*array, {0, 10}, ex);
399   CheckArray(*array, {2, 10}, ex_2);
400   CheckStream(*array, {0, 1}, ex_3);
401 
402   list_type = large_list(int64());
403   array = ArrayFromJSON(list_type, "[[null], [], null, [4, 6, 7], [2, 3]]");
404   CheckArray(*array, {0, 10}, ex);
405   CheckArray(*array, {2, 10}, ex_2);
406   CheckStream(*array, {0, 1}, ex_3);
407 }
408 
TEST_F(TestPrettyPrint,MapType)409 TEST_F(TestPrettyPrint, MapType) {
410   auto map_type = map(utf8(), int64());
411   auto array = ArrayFromJSON(map_type, R"([
412     [["joe", 0], ["mark", null]],
413     null,
414     [["cap", 8]],
415     []
416   ])");
417 
418   static const char* ex = R"expected([
419   keys:
420   [
421     "joe",
422     "mark"
423   ]
424   values:
425   [
426     0,
427     null
428   ],
429   null,
430   keys:
431   [
432     "cap"
433   ]
434   values:
435   [
436     8
437   ],
438   keys:
439   []
440   values:
441   []
442 ])expected";
443   CheckArray(*array, {0, 10}, ex);
444 }
445 
TEST_F(TestPrettyPrint,FixedSizeListType)446 TEST_F(TestPrettyPrint, FixedSizeListType) {
447   auto list_type = fixed_size_list(int32(), 3);
448   auto array = ArrayFromJSON(list_type,
449                              "[[null, 0, 1], [2, 3, null], null, [4, 6, 7], [8, 9, 5]]");
450 
451   CheckArray(*array, {0, 10}, R"expected([
452   [
453     null,
454     0,
455     1
456   ],
457   [
458     2,
459     3,
460     null
461   ],
462   null,
463   [
464     4,
465     6,
466     7
467   ],
468   [
469     8,
470     9,
471     5
472   ]
473 ])expected");
474   CheckStream(*array, {0, 1}, R"expected([
475   [
476     null,
477     ...
478     1
479   ],
480   ...
481   [
482     8,
483     ...
484     5
485   ]
486 ])expected");
487 }
488 
TEST_F(TestPrettyPrint,FixedSizeBinaryType)489 TEST_F(TestPrettyPrint, FixedSizeBinaryType) {
490   std::vector<bool> is_valid = {true, true, false, true, false};
491 
492   auto type = fixed_size_binary(3);
493   auto array = ArrayFromJSON(type, "[\"foo\", \"bar\", null, \"baz\"]");
494 
495   static const char* ex = "[\n  666F6F,\n  626172,\n  null,\n  62617A\n]";
496   CheckArray(*array, {0, 10}, ex);
497   static const char* ex_2 = "  [\n    666F6F,\n    ...\n    62617A\n  ]";
498   CheckArray(*array, {2, 1}, ex_2);
499 }
500 
TEST_F(TestPrettyPrint,Decimal128Type)501 TEST_F(TestPrettyPrint, Decimal128Type) {
502   int32_t p = 19;
503   int32_t s = 4;
504 
505   auto type = decimal(p, s);
506   auto array = ArrayFromJSON(type, "[\"123.4567\", \"456.7891\", null]");
507 
508   static const char* ex = "[\n  123.4567,\n  456.7891,\n  null\n]";
509   CheckArray(*array, {0}, ex);
510 }
511 
TEST_F(TestPrettyPrint,DictionaryType)512 TEST_F(TestPrettyPrint, DictionaryType) {
513   std::vector<bool> is_valid = {true, true, false, true, true, true};
514 
515   std::shared_ptr<Array> dict;
516   std::vector<std::string> dict_values = {"foo", "bar", "baz"};
517   ArrayFromVector<StringType, std::string>(dict_values, &dict);
518   std::shared_ptr<DataType> dict_type = dictionary(int16(), utf8());
519 
520   std::shared_ptr<Array> indices;
521   std::vector<int16_t> indices_values = {1, 2, -1, 0, 2, 0};
522   ArrayFromVector<Int16Type, int16_t>(is_valid, indices_values, &indices);
523   auto arr = std::make_shared<DictionaryArray>(dict_type, indices, dict);
524 
525   static const char* expected = R"expected(
526 -- dictionary:
527   [
528     "foo",
529     "bar",
530     "baz"
531   ]
532 -- indices:
533   [
534     1,
535     2,
536     null,
537     0,
538     2,
539     0
540   ])expected";
541 
542   CheckArray(*arr, {0}, expected);
543 }
544 
TEST_F(TestPrettyPrint,ChunkedArrayPrimitiveType)545 TEST_F(TestPrettyPrint, ChunkedArrayPrimitiveType) {
546   auto array = ArrayFromJSON(int32(), "[0, 1, null, 3, null]");
547   ChunkedArray chunked_array(array);
548 
549   static const char* expected = R"expected([
550   [
551     0,
552     1,
553     null,
554     3,
555     null
556   ]
557 ])expected";
558   CheckStream(chunked_array, {0}, expected);
559 
560   ChunkedArray chunked_array_2({array, array});
561 
562   static const char* expected_2 = R"expected([
563   [
564     0,
565     1,
566     null,
567     3,
568     null
569   ],
570   [
571     0,
572     1,
573     null,
574     3,
575     null
576   ]
577 ])expected";
578 
579   CheckStream(chunked_array_2, {0}, expected_2);
580 }
581 
TEST_F(TestPrettyPrint,TablePrimitive)582 TEST_F(TestPrettyPrint, TablePrimitive) {
583   std::shared_ptr<Field> int_field = field("column", int32());
584   auto array = ArrayFromJSON(int_field->type(), "[0, 1, null, 3, null]");
585   auto column = std::make_shared<ChunkedArray>(ArrayVector({array}));
586   std::shared_ptr<Schema> table_schema = schema({int_field});
587   std::shared_ptr<Table> table = Table::Make(table_schema, {column});
588 
589   static const char* expected = R"expected(column: int32
590 ----
591 column:
592   [
593     [
594       0,
595       1,
596       null,
597       3,
598       null
599     ]
600   ]
601 )expected";
602   CheckStream(*table, {0}, expected);
603 }
604 
TEST_F(TestPrettyPrint,SchemaWithDictionary)605 TEST_F(TestPrettyPrint, SchemaWithDictionary) {
606   std::vector<bool> is_valid = {true, true, false, true, true, true};
607 
608   std::shared_ptr<Array> dict;
609   std::vector<std::string> dict_values = {"foo", "bar", "baz"};
610   ArrayFromVector<StringType, std::string>(dict_values, &dict);
611 
612   auto simple = field("one", int32());
613   auto simple_dict = field("two", dictionary(int16(), utf8()));
614   auto list_of_dict = field("three", list(simple_dict));
615   auto struct_with_dict = field("four", struct_({simple, simple_dict}));
616 
617   auto sch = schema({simple, simple_dict, list_of_dict, struct_with_dict});
618 
619   static const char* expected = R"expected(one: int32
620 two: dictionary<values=string, indices=int16, ordered=0>
621 three: list<two: dictionary<values=string, indices=int16, ordered=0>>
622   child 0, two: dictionary<values=string, indices=int16, ordered=0>
623 four: struct<one: int32, two: dictionary<values=string, indices=int16, ordered=0>>
624   child 0, one: int32
625   child 1, two: dictionary<values=string, indices=int16, ordered=0>)expected";
626 
627   PrettyPrintOptions options;
628   Check(*sch, options, expected);
629 }
630 
TEST_F(TestPrettyPrint,SchemaWithNotNull)631 TEST_F(TestPrettyPrint, SchemaWithNotNull) {
632   auto simple = field("one", int32());
633   auto non_null = field("two", int32(), false);
634   auto list_simple = field("three", list(int32()));
635   auto list_non_null = field("four", list(int32()), false);
636   auto list_non_null2 = field("five", list(field("item", int32(), false)));
637 
638   auto sch = schema({simple, non_null, list_simple, list_non_null, list_non_null2});
639 
640   static const char* expected = R"expected(one: int32
641 two: int32 not null
642 three: list<item: int32>
643   child 0, item: int32
644 four: list<item: int32> not null
645   child 0, item: int32
646 five: list<item: int32 not null>
647   child 0, item: int32 not null)expected";
648 
649   PrettyPrintOptions options;
650   Check(*sch, options, expected);
651 }
652 
TEST_F(TestPrettyPrint,SchemaWithMetadata)653 TEST_F(TestPrettyPrint, SchemaWithMetadata) {
654   // ARROW-7063
655   auto metadata1 = key_value_metadata({"foo1"}, {"bar1"});
656   auto metadata2 = key_value_metadata({"foo2"}, {"bar2"});
657   auto metadata3 = key_value_metadata(
658       {"foo3", "lorem"},
659       {"bar3",
660        R"(Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla accumsan vel
661           turpis et mollis. Aliquam tincidunt arcu id tortor blandit blandit. Donec
662           eget leo quis lectus scelerisque varius. Class aptent taciti sociosqu ad
663           litora torquent per conubia nostra, per inceptos himenaeos. Praesent
664           faucibus, diam eu volutpat iaculis, tellus est porta ligula, a efficitur
665           turpis nulla facilisis quam. Aliquam vitae lorem erat. Proin a dolor ac libero
666           dignissim mollis vitae eu mauris. Quisque posuere tellus vitae massa
667           pellentesque sagittis. Aenean feugiat, diam ac dignissim fermentum, lorem
668           sapien commodo massa, vel volutpat orci nisi eu justo. Nulla non blandit
669           sapien. Quisque pretium vestibulum urna eu vehicula.)"});
670   auto my_schema = schema(
671       {field("one", int32(), true, metadata1), field("two", utf8(), false, metadata2)},
672       metadata3);
673 
674   PrettyPrintOptions options;
675   static const char* expected = R"(one: int32
676   -- field metadata --
677   foo1: 'bar1'
678 two: string not null
679   -- field metadata --
680   foo2: 'bar2'
681 -- schema metadata --
682 foo3: 'bar3'
683 lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac' + 737)";
684   Check(*my_schema, options, expected);
685 
686   static const char* expected_verbose = R"(one: int32
687   -- field metadata --
688   foo1: 'bar1'
689 two: string not null
690   -- field metadata --
691   foo2: 'bar2'
692 -- schema metadata --
693 foo3: 'bar3'
694 lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla accumsan vel
695           turpis et mollis. Aliquam tincidunt arcu id tortor blandit blandit. Donec
696           eget leo quis lectus scelerisque varius. Class aptent taciti sociosqu ad
697           litora torquent per conubia nostra, per inceptos himenaeos. Praesent
698           faucibus, diam eu volutpat iaculis, tellus est porta ligula, a efficitur
699           turpis nulla facilisis quam. Aliquam vitae lorem erat. Proin a dolor ac libero
700           dignissim mollis vitae eu mauris. Quisque posuere tellus vitae massa
701           pellentesque sagittis. Aenean feugiat, diam ac dignissim fermentum, lorem
702           sapien commodo massa, vel volutpat orci nisi eu justo. Nulla non blandit
703           sapien. Quisque pretium vestibulum urna eu vehicula.')";
704   options.truncate_metadata = false;
705   Check(*my_schema, options, expected_verbose);
706 
707   // Metadata that exactly fits
708   auto metadata4 =
709       key_value_metadata({"key"}, {("valuexxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
710                                     "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")});
711   my_schema = schema({field("f0", int32())}, metadata4);
712   static const char* expected_fits = R"(f0: int32
713 -- schema metadata --
714 key: 'valuexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')";
715   options.truncate_metadata = false;
716   Check(*my_schema, options, expected_fits);
717 
718   // A large key
719   auto metadata5 = key_value_metadata({"0123456789012345678901234567890123456789"},
720                                       {("valuexxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
721                                         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")});
722   my_schema = schema({field("f0", int32())}, metadata5);
723   static const char* expected_big_key = R"(f0: int32
724 -- schema metadata --
725 0123456789012345678901234567890123456789: 'valuexxxxxxxxxxxxxxxxxxxxxxxxx' + 40)";
726   options.truncate_metadata = true;
727   Check(*my_schema, options, expected_big_key);
728 }
729 
TEST_F(TestPrettyPrint,SchemaIndentation)730 TEST_F(TestPrettyPrint, SchemaIndentation) {
731   // ARROW-6159
732   auto simple = field("one", int32());
733   auto non_null = field("two", int32(), false);
734   auto sch = schema({simple, non_null});
735 
736   static const char* expected = R"expected(    one: int32
737     two: int32 not null)expected";
738 
739   PrettyPrintOptions options(/*indent=*/4);
740   Check(*sch, options, expected);
741 }
742 
743 }  // namespace arrow
744