| /* |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <pw_unit_test/framework.h> |
| |
| #include <lib/core/CHIPCore.h> |
| #include <lib/core/ErrorStr.h> |
| #include <lib/core/StringBuilderAdapters.h> |
| |
| using namespace chip; |
| |
| #if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR |
| |
| const char * CheckAndSkipSource(const char * s, const char * file, unsigned int line) |
| { |
| size_t fileLength = strlen(file); |
| EXPECT_EQ(strncmp(s, file, fileLength), 0); |
| EXPECT_EQ(s[fileLength], ':'); |
| char * end; |
| EXPECT_EQ(strtoul(&s[fileLength + 1], &end, 10), line); |
| EXPECT_EQ(strncmp(end, ": ", 2), 0); |
| return end + 2; |
| } |
| |
| #define CHECK_AND_SKIP_SOURCE(s) CheckAndSkipSource((s), __FILE__, __LINE__) |
| |
| #else // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR |
| |
| #define CHECK_AND_SKIP_SOURCE(s) (s) |
| |
| #endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR |
| |
| static int falseFormatCalled = 0; |
| static bool falseFormat(char * buf, uint16_t bufSize, CHIP_ERROR err) |
| { |
| falseFormatCalled += 1; |
| return false; // means keep going |
| } |
| static int falseFormat2Called = 0; |
| static bool falseFormat2(char * buf, uint16_t bufSize, CHIP_ERROR err) |
| { |
| falseFormat2Called += 1; |
| return false; // means keep going |
| } |
| static int trueFormatCalled = 0; |
| static bool trueFormat(char * buf, uint16_t bufSize, CHIP_ERROR err) |
| { |
| trueFormatCalled += 1; |
| return true; // means I handled it |
| } |
| |
| TEST(TestErrorStr, CheckRegisterDeregisterErrorFormatter) |
| { |
| static ErrorFormatter falseFormatter = { falseFormat, nullptr }; |
| static ErrorFormatter falseFormatter2 = { falseFormat2, nullptr }; |
| static ErrorFormatter trueFormatter = { trueFormat, nullptr }; |
| |
| // simple case |
| RegisterErrorFormatter(&falseFormatter); |
| ErrorStr(CHIP_ERROR_INTERNAL); |
| EXPECT_EQ(falseFormatCalled, 1); |
| // reset |
| falseFormatCalled = 0; |
| |
| // re-registration should be ignored |
| RegisterErrorFormatter(&falseFormatter); |
| ErrorStr(CHIP_ERROR_INTERNAL); |
| EXPECT_EQ(falseFormatCalled, 1); |
| // reset |
| falseFormatCalled = 0; |
| |
| // registration of a new handler, nobody handling anything |
| RegisterErrorFormatter(&falseFormatter2); |
| ErrorStr(CHIP_ERROR_INTERNAL); |
| EXPECT_EQ(falseFormatCalled, 1); |
| EXPECT_EQ(falseFormat2Called, 1); |
| // reset |
| falseFormatCalled = 0; |
| falseFormat2Called = 0; |
| |
| // registration of a true handler, gets first crack |
| RegisterErrorFormatter(&trueFormatter); |
| ErrorStr(CHIP_ERROR_INTERNAL); |
| EXPECT_EQ(trueFormatCalled, 1); |
| EXPECT_EQ(falseFormatCalled, 0); |
| EXPECT_EQ(falseFormat2Called, 0); |
| // reset |
| trueFormatCalled = 0; |
| |
| // deregister true |
| DeregisterErrorFormatter(&trueFormatter); |
| ErrorStr(CHIP_ERROR_INTERNAL); |
| EXPECT_EQ(trueFormatCalled, 0); |
| EXPECT_EQ(falseFormatCalled, 1); |
| EXPECT_EQ(falseFormat2Called, 1); |
| |
| // verify this doesn't crash |
| DeregisterErrorFormatter(&trueFormatter); |
| } |
| |
| TEST(TestErrorStr, CheckNoError) |
| { |
| EXPECT_STREQ(CHECK_AND_SKIP_SOURCE(ErrorStr(CHIP_NO_ERROR)), CHIP_NO_ERROR_STRING); |
| } |
| |
| TEST(TestErrorStr, CheckFormatErr) |
| { |
| #if CHIP_CONFIG_SHORT_ERROR_STR |
| |
| // TODO tests for this config |
| |
| #else // CHIP_CONFIG_SHORT_ERROR_STR |
| static const size_t kBufSize = 1024; |
| static char buf[kBufSize]; |
| static const char subsys[] = "subsys"; |
| static const char desc[] = "desc"; |
| |
| strcpy(buf, "hi"); |
| // shouldn't touch the buffer |
| FormatError(buf, 0, subsys, CHIP_ERROR_INTERNAL, desc); |
| EXPECT_STREQ(buf, "hi"); |
| |
| // guarantees null termination, doesn't touch past 1st byte |
| strcpy(buf, "hi"); |
| FormatError(buf, 1, subsys, CHIP_ERROR_INTERNAL, desc); |
| EXPECT_STREQ(buf, ""); |
| EXPECT_EQ(buf[1], 'i'); |
| |
| // whole shebang |
| FormatError(buf, kBufSize, subsys, CHIP_CORE_ERROR(1), desc); |
| EXPECT_STREQ(buf, "subsys Error 0x00000001: desc"); |
| |
| // skip desc |
| FormatError(buf, kBufSize, subsys, CHIP_CORE_ERROR(1), nullptr); |
| EXPECT_STREQ(buf, "subsys Error 0x00000001"); |
| |
| // skip subsys |
| FormatError(buf, kBufSize, nullptr, CHIP_CORE_ERROR(1), desc); |
| EXPECT_STREQ(buf, "Error 0x00000001: desc"); |
| |
| // skip both |
| FormatError(buf, kBufSize, nullptr, CHIP_CORE_ERROR(1), nullptr); |
| EXPECT_STREQ(buf, "Error 0x00000001"); |
| #endif |
| } |