Skip to content

Commit 5ace630

Browse files
yyzhong-grestyled-commits
andauthoredNov 8, 2024
Add a helper function to allow ErrorStr not using static char array (project-chip#36391)
* Add a helper function to allow ErrorStr does not rely on static char array * Use dedicated storage for ErrorStr and add unit tests * Restyled by whitespace * Restyled by clang-format * remove size() --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 585a74c commit 5ace630

File tree

4 files changed

+113
-48
lines changed

4 files changed

+113
-48
lines changed
 

‎src/lib/core/ErrorStr.cpp

+27-16
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace chip {
2929
/**
3030
* Static buffer to store the formatted error string.
3131
*/
32-
static char sErrorStr[CHIP_CONFIG_ERROR_STR_SIZE];
32+
static ErrorStrStorage sErrorStr;
3333

3434
/**
3535
* Linked-list of error formatter functions.
@@ -38,7 +38,7 @@ static ErrorFormatter * sErrorFormatterList = nullptr;
3838

3939
/**
4040
* This routine returns a human-readable NULL-terminated C string
41-
* describing the provided error.
41+
* describing the provided error. This uses the global static storage.
4242
*
4343
* @param[in] err The error for format and describe.
4444
* @param[in] withSourceLocation Whether or not to include the source
@@ -50,8 +50,26 @@ static ErrorFormatter * sErrorFormatterList = nullptr;
5050
*/
5151
DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation)
5252
{
53-
char * formattedError = sErrorStr;
54-
uint16_t formattedSpace = sizeof(sErrorStr);
53+
return ErrorStr(err, withSourceLocation, sErrorStr);
54+
}
55+
56+
/**
57+
* This routine writess a human-readable NULL-terminated C string into the buf
58+
* which describes the provided error.
59+
*
60+
* @param[in] err The error for format and describe.
61+
* @param[in] withSourceLocation Whether or not to include the source
62+
* @param[in] storage ErrorStrStorage to write into
63+
* location in the output string. Only used if CHIP_CONFIG_ERROR_SOURCE &&
64+
* !CHIP_CONFIG_SHORT_ERROR_STR. Defaults to true.
65+
*
66+
* @return A pointer to a NULL-terminated C string describing the
67+
* provided error.
68+
*/
69+
DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation, ErrorStrStorage & storage)
70+
{
71+
char * formattedError = storage.buff;
72+
uint16_t formattedSpace = storage.kBufferSize;
5573

5674
#if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
5775

@@ -65,34 +83,27 @@ DLL_EXPORT const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation)
6583
formattedError += n;
6684
formattedSpace = static_cast<uint16_t>(formattedSpace - n);
6785
}
68-
if (err == CHIP_NO_ERROR)
69-
{
70-
(void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING);
71-
return sErrorStr;
72-
}
73-
74-
#else // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
86+
#endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
7587

7688
if (err == CHIP_NO_ERROR)
7789
{
78-
return CHIP_NO_ERROR_STRING;
90+
(void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING);
91+
return storage.buff;
7992
}
8093

81-
#endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR
82-
8394
// Search the registered error formatter for one that will format the given
8495
// error code.
8596
for (const ErrorFormatter * errFormatter = sErrorFormatterList; errFormatter != nullptr; errFormatter = errFormatter->Next)
8697
{
8798
if (errFormatter->FormatError(formattedError, formattedSpace, err))
8899
{
89-
return sErrorStr;
100+
return storage.buff;
90101
}
91102
}
92103

93104
// Use a default formatting if no formatter found.
94105
FormatError(formattedError, formattedSpace, nullptr, err, nullptr);
95-
return sErrorStr;
106+
return storage.buff;
96107
}
97108

98109
/**

‎src/lib/core/ErrorStr.h

+7
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@ struct ErrorFormatter
4848
ErrorFormatter * Next;
4949
};
5050

51+
struct ErrorStrStorage
52+
{
53+
char buff[CHIP_CONFIG_ERROR_STR_SIZE];
54+
constexpr static uint16_t kBufferSize = sizeof(buff);
55+
};
56+
5157
extern const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation = true);
58+
extern const char * ErrorStr(CHIP_ERROR err, bool withSourceLocation, ErrorStrStorage & storage);
5259
extern void RegisterErrorFormatter(ErrorFormatter * errFormatter);
5360
extern void DeregisterErrorFormatter(ErrorFormatter * errFormatter);
5461
extern void FormatError(char * buf, uint16_t bufSize, const char * subsys, CHIP_ERROR err, const char * desc);

‎src/lib/core/tests/TestCHIPErrorStr.cpp

+72-32
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,31 @@ static const CHIP_ERROR kTestElements[] =
170170
};
171171
// clang-format on
172172

173+
void CheckCoreErrorStrHelper(const char * errStr, CHIP_ERROR err)
174+
{
175+
char expectedText[9];
176+
177+
// Assert that the error string contains the error number in hex.
178+
snprintf(expectedText, sizeof(expectedText), "%08" PRIX32, static_cast<uint32_t>(err.AsInteger()));
179+
EXPECT_TRUE((strstr(errStr, expectedText) != nullptr));
180+
181+
#if !CHIP_CONFIG_SHORT_ERROR_STR
182+
// Assert that the error string contains a description, which is signaled
183+
// by a presence of a colon proceeding the description.
184+
EXPECT_TRUE((strchr(errStr, ':') != nullptr));
185+
#endif // !CHIP_CONFIG_SHORT_ERROR_STR
186+
187+
#if CHIP_CONFIG_ERROR_SOURCE
188+
// GetFile() should be relative to ${chip_root}
189+
char const * const file = err.GetFile();
190+
ASSERT_NE(file, nullptr);
191+
EXPECT_EQ(strstr(file, "src/lib/core/"), file);
192+
193+
// File should be included in the error.
194+
EXPECT_NE(strstr(errStr, file), nullptr);
195+
#endif // CHIP_CONFIG_ERROR_SOURCE
196+
}
197+
173198
TEST(TestCHIPErrorStr, CheckCoreErrorStr)
174199
{
175200
// Register the layer error formatter
@@ -179,29 +204,46 @@ TEST(TestCHIPErrorStr, CheckCoreErrorStr)
179204
// For each defined error...
180205
for (const auto & err : kTestElements)
181206
{
182-
const char * errStr = ErrorStr(err);
183-
char expectedText[9];
207+
// ErrorStr with static char array.
208+
CheckCoreErrorStrHelper(ErrorStr(err, /*withSourceLocation=*/true), err);
209+
}
210+
}
211+
212+
TEST(TestCHIPErrorStr, CheckCoreErrorStrStorage)
213+
{
214+
// Register the layer error formatter
215+
216+
RegisterCHIPLayerErrorFormatter();
217+
218+
// For each defined error...
219+
for (const auto & err : kTestElements)
220+
{
221+
// ErrorStr with given storage.
222+
ErrorStrStorage storage;
223+
CheckCoreErrorStrHelper(ErrorStr(err, /*withSourceLocation=*/true, storage), err);
224+
}
225+
}
226+
227+
void CheckCoreErrorStrWithoutSourceLocationHelper(const char * errStr, CHIP_ERROR err)
228+
{
229+
char expectedText[9];
184230

185-
// Assert that the error string contains the error number in hex.
186-
snprintf(expectedText, sizeof(expectedText), "%08" PRIX32, static_cast<uint32_t>(err.AsInteger()));
187-
EXPECT_TRUE((strstr(errStr, expectedText) != nullptr));
231+
// Assert that the error string contains the error number in hex.
232+
snprintf(expectedText, sizeof(expectedText), "%08" PRIX32, static_cast<uint32_t>(err.AsInteger()));
233+
EXPECT_TRUE((strstr(errStr, expectedText) != nullptr));
188234

189235
#if !CHIP_CONFIG_SHORT_ERROR_STR
190-
// Assert that the error string contains a description, which is signaled
191-
// by a presence of a colon proceeding the description.
192-
EXPECT_TRUE((strchr(errStr, ':') != nullptr));
236+
// Assert that the error string contains a description, which is signaled
237+
// by a presence of a colon proceeding the description.
238+
EXPECT_TRUE((strchr(errStr, ':') != nullptr));
193239
#endif // !CHIP_CONFIG_SHORT_ERROR_STR
194240

195241
#if CHIP_CONFIG_ERROR_SOURCE
196-
// GetFile() should be relative to ${chip_root}
197-
char const * const file = err.GetFile();
198-
ASSERT_NE(file, nullptr);
199-
EXPECT_EQ(strstr(file, "src/lib/core/"), file);
200-
201-
// File should be included in the error.
202-
EXPECT_NE(strstr(errStr, file), nullptr);
242+
char const * const file = err.GetFile();
243+
ASSERT_NE(file, nullptr);
244+
// File should not be included in the error.
245+
EXPECT_EQ(strstr(errStr, file), nullptr);
203246
#endif // CHIP_CONFIG_ERROR_SOURCE
204-
}
205247
}
206248

207249
TEST(TestCHIPErrorStr, CheckCoreErrorStrWithoutSourceLocation)
@@ -213,24 +255,22 @@ TEST(TestCHIPErrorStr, CheckCoreErrorStrWithoutSourceLocation)
213255
// For each defined error...
214256
for (const auto & err : kTestElements)
215257
{
216-
const char * errStr = ErrorStr(err, /*withSourceLocation=*/false);
217-
char expectedText[9];
258+
// ErrorStr with static char array.
259+
CheckCoreErrorStrWithoutSourceLocationHelper(ErrorStr(err, /*withSourceLocation=*/false), err);
260+
}
261+
}
218262

219-
// Assert that the error string contains the error number in hex.
220-
snprintf(expectedText, sizeof(expectedText), "%08" PRIX32, static_cast<uint32_t>(err.AsInteger()));
221-
EXPECT_TRUE((strstr(errStr, expectedText) != nullptr));
263+
TEST(TestCHIPErrorStr, CheckCoreErrorStrStorageWithoutSourceLocation)
264+
{
265+
// Register the layer error formatter
222266

223-
#if !CHIP_CONFIG_SHORT_ERROR_STR
224-
// Assert that the error string contains a description, which is signaled
225-
// by a presence of a colon proceeding the description.
226-
EXPECT_TRUE((strchr(errStr, ':') != nullptr));
227-
#endif // !CHIP_CONFIG_SHORT_ERROR_STR
267+
RegisterCHIPLayerErrorFormatter();
228268

229-
#if CHIP_CONFIG_ERROR_SOURCE
230-
char const * const file = err.GetFile();
231-
ASSERT_NE(file, nullptr);
232-
// File should not be included in the error.
233-
EXPECT_EQ(strstr(errStr, file), nullptr);
234-
#endif // CHIP_CONFIG_ERROR_SOURCE
269+
// For each defined error...
270+
for (const auto & err : kTestElements)
271+
{
272+
// ErrorStr with given storage.
273+
ErrorStrStorage storage;
274+
CheckCoreErrorStrWithoutSourceLocationHelper(ErrorStr(err, /*withSourceLocation=*/false, storage), err);
235275
}
236276
}

‎src/lib/support/tests/TestErrorStr.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ TEST(TestErrorStr, CheckNoError)
121121
EXPECT_STREQ(CHECK_AND_SKIP_SOURCE(ErrorStr(CHIP_NO_ERROR)), CHIP_NO_ERROR_STRING);
122122
}
123123

124+
TEST(TestErrorStr, CheckErrorWithProvidedStorage)
125+
{
126+
ErrorStrStorage storage;
127+
EXPECT_STREQ(CHECK_AND_SKIP_SOURCE(ErrorStr(CHIP_NO_ERROR, true, storage)), CHIP_NO_ERROR_STRING);
128+
EXPECT_STREQ(CHECK_AND_SKIP_SOURCE(ErrorStr(CHIP_ERROR_INTERNAL, true, storage)), "Error 0x000000AC");
129+
}
130+
124131
TEST(TestErrorStr, CheckFormatErr)
125132
{
126133
#if CHIP_CONFIG_SHORT_ERROR_STR

0 commit comments

Comments
 (0)