1 // Copyright 2019 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_string/format.h"
16
17 #include <cstdarg>
18
19 #include "pw_span/span.h"
20 #include "pw_unit_test/framework.h"
21
22 namespace pw::string {
23 namespace {
24
TEST(Format,ValidFormatString_Succeeds)25 TEST(Format, ValidFormatString_Succeeds) {
26 char buffer[32];
27 auto result = Format(buffer, "-_-");
28
29 EXPECT_EQ(OkStatus(), result.status());
30 EXPECT_EQ(3u, result.size());
31 EXPECT_STREQ("-_-", buffer);
32 }
33
TEST(Format,ValidFormatStringAndArguments_Succeeds)34 TEST(Format, ValidFormatStringAndArguments_Succeeds) {
35 char buffer[32];
36 auto result = Format(buffer, "%d4%s", 123, "5");
37
38 EXPECT_EQ(OkStatus(), result.status());
39 EXPECT_EQ(5u, result.size());
40 EXPECT_STREQ("12345", buffer);
41 }
42
TEST(Format,EmptyBuffer_ReturnsResourceExhausted)43 TEST(Format, EmptyBuffer_ReturnsResourceExhausted) {
44 auto result = Format(span<char>(), "?");
45
46 EXPECT_EQ(Status::ResourceExhausted(), result.status());
47 EXPECT_EQ(0u, result.size());
48 }
49
TEST(Format,FormatLargerThanBuffer_ReturnsResourceExhausted)50 TEST(Format, FormatLargerThanBuffer_ReturnsResourceExhausted) {
51 char buffer[5];
52 auto result = Format(buffer, "2big!");
53
54 EXPECT_EQ(Status::ResourceExhausted(), result.status());
55 EXPECT_EQ(4u, result.size());
56 EXPECT_STREQ("2big", buffer);
57 }
58
TEST(Format,ArgumentLargerThanBuffer_ReturnsResourceExhausted)59 TEST(Format, ArgumentLargerThanBuffer_ReturnsResourceExhausted) {
60 char buffer[5];
61 auto result = Format(buffer, "%s", "2big!");
62
63 EXPECT_EQ(Status::ResourceExhausted(), result.status());
64 EXPECT_EQ(4u, result.size());
65 EXPECT_STREQ("2big", buffer);
66 }
67
68 PW_PRINTF_FORMAT(2, 3)
CallFormatWithVaList(span<char> buffer,const char * fmt,...)69 StatusWithSize CallFormatWithVaList(span<char> buffer, const char* fmt, ...) {
70 va_list args;
71 va_start(args, fmt);
72
73 StatusWithSize result = FormatVaList(buffer, fmt, args);
74
75 va_end(args);
76 return result;
77 }
78
TEST(Format,CallFormatWithVaList_CallsCorrectFormatOverload)79 TEST(Format, CallFormatWithVaList_CallsCorrectFormatOverload) {
80 char buffer[8];
81 auto result = CallFormatWithVaList(buffer, "Yo%s", "?!");
82
83 EXPECT_EQ(OkStatus(), result.status());
84 EXPECT_EQ(4u, result.size());
85 EXPECT_STREQ("Yo?!", buffer);
86 }
87
TEST(FormatString,Append)88 TEST(FormatString, Append) {
89 InlineString<6> string;
90 EXPECT_EQ(OkStatus(), Format(string, "-_-"));
91 EXPECT_EQ("-_-", string);
92
93 EXPECT_EQ(OkStatus(), Format(string, "%d", 123));
94 EXPECT_EQ("-_-123", string);
95
96 EXPECT_EQ(Status::ResourceExhausted(), Format(string, "%d", 1));
97 EXPECT_EQ("-_-123", string);
98 }
99
TEST(FormatString,EmptyString)100 TEST(FormatString, EmptyString) {
101 InlineString<0> string;
102 EXPECT_EQ(Status::ResourceExhausted(), Format(string, "-_-"));
103 EXPECT_EQ("", string);
104 }
105
TEST(FormatString,Truncates)106 TEST(FormatString, Truncates) {
107 InlineString<5> string;
108 EXPECT_EQ(Status::ResourceExhausted(), Format(string, "1%s", "23456"));
109 EXPECT_EQ("12345", string);
110 }
111
TEST(FormatString,Overwrite)112 TEST(FormatString, Overwrite) {
113 InlineString<6> string("???");
114 EXPECT_EQ(OkStatus(), FormatOverwrite(string, "-_-"));
115 EXPECT_EQ("-_-", string);
116 }
117
118 template <Status (&kFunction)(InlineString<>&, const char*, va_list)>
119 PW_PRINTF_FORMAT(2, 3)
CallInlineString(InlineString<> & string,const char * fmt,...)120 Status CallInlineString(InlineString<>& string, const char* fmt, ...) {
121 va_list args;
122 va_start(args, fmt);
123
124 Status result = kFunction(string, fmt, args);
125
126 va_end(args);
127 return result;
128 }
129
TEST(FormatString,CallFormatWithVaList_CallsCorrectFormatOverload)130 TEST(FormatString, CallFormatWithVaList_CallsCorrectFormatOverload) {
131 InlineString<8> string;
132 Status result = CallInlineString<FormatVaList>(string, "Yo%s %d", "?!", 5);
133
134 EXPECT_EQ(OkStatus(), result);
135 EXPECT_EQ(6u, string.size());
136 EXPECT_EQ("Yo?! 5", string);
137 }
138
TEST(FormatString,OverwriteVaList)139 TEST(FormatString, OverwriteVaList) {
140 InlineString<8> string("blah");
141 Status result = CallInlineString<FormatOverwriteVaList>(string, "why%c", '?');
142
143 EXPECT_EQ(OkStatus(), result);
144 EXPECT_EQ(4u, string.size());
145 EXPECT_EQ("why?", string);
146 }
147
148 } // namespace
149 } // namespace pw::string
150