aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/std/format/string.cc
blob: e421028a873e58d81fc389867c2211ab0dcebff3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// { dg-options "-std=gnu++20" }
// { dg-do run { target c++20 } }

#include <format>
#include <testsuite_hooks.h>

template<typename... Args>
bool
is_format_string_for(const char* str, Args&&... args)
{
  try {
    (void) std::vformat(str, std::make_format_args(args...));
    return true;
  } catch (const std::format_error&) {
    return false;
  }
}

void
test_no_args()
{
  VERIFY( is_format_string_for("") );
  VERIFY( is_format_string_for("chars") );
  VERIFY( is_format_string_for(" The Great Escape {{}} ") );

  VERIFY( ! is_format_string_for("{") );
  VERIFY( ! is_format_string_for("}") );
  VERIFY( ! is_format_string_for("}{") );
  VERIFY( ! is_format_string_for("{{}") );
  VERIFY( ! is_format_string_for("{{{") );
  VERIFY( ! is_format_string_for("{{{{{") );
}

void
test_indexing()
{
  VERIFY( is_format_string_for("{} to {}", "a", "b") );   // automatic indexing
  VERIFY( is_format_string_for("{1} to {0}", "a", "b") ); // manual indexing
  VERIFY( ! is_format_string_for("{0} to {}", "a", "b") );  // mixed indexing
  VERIFY( ! is_format_string_for("{} to {1}", "a", "b") );  // mixed indexing

  VERIFY( is_format_string_for("{} {} {}", 1, 2, 3) );
  VERIFY( is_format_string_for("{} {} {}", 1, 2, 3, 4) );
  VERIFY( is_format_string_for("{0} {1} {2}", 1, 2, 3, 4) );
  VERIFY( is_format_string_for("{1} {2} {3}", 1, 2, 3, 4) );
  VERIFY( is_format_string_for("{3} {3} {3}", 1, 2, 3, 4) );

  VERIFY( ! is_format_string_for("{2}", 1, 2) );

  VERIFY( ! is_format_string_for("{0} {}", 1) );
  VERIFY( ! is_format_string_for("{} {0}", 1) );
}

#if __cpp_lib_format_ranges
constexpr bool escaped_strings_supported = true;
#else
constexpr bool escaped_strings_supported = false;
#endif

void
test_format_spec()
{
  VERIFY( is_format_string_for("{:}", 1) );
  VERIFY( is_format_string_for("{0:}", 1) );
  VERIFY( is_format_string_for("{2:}", 1, 2, 3) );
  VERIFY( is_format_string_for("{0:s} {0:}", "str") );
  VERIFY( is_format_string_for("{0:} {0:c}", 'c') );
  VERIFY( is_format_string_for("{0:p} {0:}", nullptr) );
  VERIFY( is_format_string_for("{:d} {:+d}", true, true) );
  VERIFY( is_format_string_for("{:0<-#03Ld}", 1) );
  VERIFY( is_format_string_for("{1:0<-#03.4Lf}", 1, 2.3) );
  VERIFY( is_format_string_for("{1:3.3f}", 1, 2.3) );
  VERIFY( is_format_string_for("{:#d}", 'c') );
  VERIFY( is_format_string_for("{:#d}", true) );
  VERIFY( is_format_string_for("{0:s} {0:?}", "str") == escaped_strings_supported );
  VERIFY( is_format_string_for("{0:} {0:?}", 'c') == escaped_strings_supported );

  // Invalid sign options.
  VERIFY( ! is_format_string_for("{:+}", "str") );
  VERIFY( ! is_format_string_for("{:+s}", "str") );
  VERIFY( ! is_format_string_for("{:+}", 'c') );
  VERIFY( ! is_format_string_for("{:+c}", 'c') );
  VERIFY( ! is_format_string_for("{:+p}", nullptr) );
  VERIFY( ! is_format_string_for("{:+}", true) );
  VERIFY( ! is_format_string_for("{:+s}", true) );
  VERIFY( ! is_format_string_for("{:+?}", "str") );
  VERIFY( ! is_format_string_for("{:+?}", 'c') );

  // Invalid alternate forms.
  VERIFY( ! is_format_string_for("{:#}", "str") );
  VERIFY( ! is_format_string_for("{:#s}", "str") );
  VERIFY( ! is_format_string_for("{:#}", 'c') );
  VERIFY( ! is_format_string_for("{:#c}", 'c') );
  VERIFY( ! is_format_string_for("{:#}", true) );
  VERIFY( ! is_format_string_for("{:#s}", true) );
  VERIFY( ! is_format_string_for("{:#}", nullptr) );
  VERIFY( ! is_format_string_for("{:#p}", nullptr) );
  VERIFY( ! is_format_string_for("{:#?}", "str") );
  VERIFY( ! is_format_string_for("{:#?}", 'c') );

  // Precision only valid for string and floating-point types.
  VERIFY( ! is_format_string_for("{:.3d}", 1) );
  VERIFY( ! is_format_string_for("{:3.3d}", 1) );
  VERIFY( is_format_string_for("{:3.3s}", "str") );
  VERIFY( ! is_format_string_for("{:3.3s}", 'c') );
  VERIFY( ! is_format_string_for("{:3.3p}", nullptr) );

  // Invalid presentation types for integers.
  VERIFY( ! is_format_string_for("{:f}", 1) );
  VERIFY( ! is_format_string_for("{:s}", 1) );
  VERIFY( ! is_format_string_for("{:g}", 1) );
  VERIFY( ! is_format_string_for("{:E}", 1) );
  VERIFY( ! is_format_string_for("{:D}", 1) );

  // Invalid presentation types for floating-point types.
  VERIFY( ! is_format_string_for("{:d}", 1.2) );
  VERIFY( ! is_format_string_for("{:b}", 1.2) );
  VERIFY( ! is_format_string_for("{:x}", 1.2) );
  VERIFY( ! is_format_string_for("{:s}", 1.2) );

  // Invalid presentation types for strings.
  VERIFY( ! is_format_string_for("{:S}", "str") );
  VERIFY( ! is_format_string_for("{:d}", "str") );
}

int main()
{
  test_no_args();
  test_indexing();
  test_format_spec();
}