mirror of
https://fuchsia.googlesource.com/third_party/pigweed.googlesource.com/pigweed/pigweed
synced 2024-09-20 13:51:05 +00:00
f89f1379d4
Moves and renames the existing pw::string::Length to pw::string::internal::ClampedLength. Instead two new helpers are added: 1) pw::string::NullTerminatedLength(...) which returns the length IFF the string is null terminated. 2) pw::string::ClampedCString(...) which returns a string_view of the clamped string. This is considered safer compared to strnlen_s and the existing internal::ClampedLength implementation, since sting_view does not require null termination. Change-Id: Ie6486df13b205332633f3970109ca97f578e6993 Requires: pigweed-internal:12460 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/43463 Reviewed-by: Ewout van Bekkum <ewout@google.com> Reviewed-by: Wyatt Hepler <hepler@google.com> Reviewed-by: Keir Mierle <keir@google.com> Pigweed-Auto-Submit: Ewout van Bekkum <ewout@google.com> Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
146 lines
4.3 KiB
C++
146 lines
4.3 KiB
C++
// Copyright 2021 The Pigweed Authors
|
|
//
|
|
// 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
|
|
//
|
|
// https://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 "pw_string/util.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace pw::string {
|
|
namespace {
|
|
|
|
using namespace std::literals::string_view_literals;
|
|
|
|
TEST(ClampedLength, Nullptr_Returns0) {
|
|
EXPECT_EQ(0u, internal::ClampedLength(nullptr, 100));
|
|
}
|
|
|
|
TEST(ClampedLength, EmptyString_Returns0) {
|
|
EXPECT_EQ(0u, internal::ClampedLength("", 0));
|
|
EXPECT_EQ(0u, internal::ClampedLength("", 100));
|
|
}
|
|
|
|
TEST(ClampedLength, MaxLongerThanString_ReturnsStrlen) {
|
|
EXPECT_EQ(5u, internal::ClampedLength("12345", 100));
|
|
}
|
|
|
|
TEST(ClampedLength, StringMaxLongerThanMax_ReturnsMax) {
|
|
EXPECT_EQ(0u, internal::ClampedLength("12345", 0));
|
|
EXPECT_EQ(4u, internal::ClampedLength("12345", 4));
|
|
}
|
|
|
|
TEST(ClampedLength, LengthEqualsMax) {
|
|
EXPECT_EQ(5u, internal::ClampedLength("12345", 5));
|
|
}
|
|
|
|
TEST(ClampedCString, NullPtr_ReturnsEmpty) {
|
|
EXPECT_TRUE(ClampedCString(nullptr, 100).empty());
|
|
}
|
|
|
|
TEST(ClampedCString, EmptyString_Returns0) {
|
|
EXPECT_TRUE(ClampedCString("", 0).empty());
|
|
EXPECT_TRUE(ClampedCString("", 100).empty());
|
|
}
|
|
|
|
TEST(ClampedCString, MaxLongerThanString_ReturnsStr) {
|
|
static constexpr char kInput[] = "12345";
|
|
const std::string_view result = ClampedCString(kInput, 100);
|
|
EXPECT_EQ(result.size(), strlen(kInput));
|
|
EXPECT_EQ(result.data(), &kInput[0]);
|
|
}
|
|
|
|
TEST(ClampedCString, StringMaxLongerThanMax_ClampsView) {
|
|
static constexpr char kInput[] = "12345";
|
|
|
|
EXPECT_TRUE(ClampedCString(kInput, 0).empty());
|
|
|
|
const std::string_view result = ClampedCString(kInput, 4);
|
|
EXPECT_EQ(result.size(), 4u);
|
|
EXPECT_EQ(result.data(), &kInput[0]);
|
|
}
|
|
|
|
TEST(ClampedCString, FullStringView) {
|
|
static constexpr char kInput[] = "12345";
|
|
const std::string_view result = ClampedCString(kInput);
|
|
EXPECT_EQ(result.size(), strlen(kInput));
|
|
EXPECT_EQ(result.data(), &kInput[0]);
|
|
}
|
|
|
|
TEST(NullTerminatedLength, EmptyString_RequiresNullTerminator) {
|
|
EXPECT_TRUE(NullTerminatedLength("", 0).status().IsOutOfRange());
|
|
|
|
ASSERT_TRUE(NullTerminatedLength("", 100).status().ok());
|
|
EXPECT_EQ(0u, NullTerminatedLength("", 100).value());
|
|
}
|
|
|
|
TEST(NullTerminatedLength, MaxLongerThanString_ReturnsStrlen) {
|
|
ASSERT_TRUE(NullTerminatedLength("12345", 100).status().ok());
|
|
EXPECT_EQ(5u, NullTerminatedLength("12345", 100).value());
|
|
}
|
|
|
|
TEST(NullTerminatedLength, StringMaxLongerThanMax_Fails) {
|
|
EXPECT_TRUE(NullTerminatedLength("12345", 0).status().IsOutOfRange());
|
|
EXPECT_TRUE(NullTerminatedLength("12345", 4).status().IsOutOfRange());
|
|
}
|
|
|
|
TEST(NullTerminatedLength, LengthEqualsMax) {
|
|
static constexpr char kInput[] = "12345";
|
|
ASSERT_TRUE(NullTerminatedLength(kInput).ok());
|
|
EXPECT_EQ(5u, NullTerminatedLength(kInput).value());
|
|
}
|
|
|
|
class TestWithBuffer : public ::testing::Test {
|
|
protected:
|
|
static constexpr char kStartingString[] = "!@#$%^&*()!@#$%^&*()";
|
|
|
|
TestWithBuffer() { std::memcpy(buffer_, kStartingString, sizeof(buffer_)); }
|
|
|
|
char buffer_[sizeof(kStartingString)];
|
|
};
|
|
|
|
class CopyTest : public TestWithBuffer {};
|
|
|
|
TEST_F(CopyTest, EmptyStringView_WritesNullTerminator) {
|
|
EXPECT_EQ(0u, Copy("", buffer_).size());
|
|
EXPECT_EQ('\0', buffer_[0]);
|
|
}
|
|
|
|
TEST_F(CopyTest, EmptyBuffer_WritesNothing) {
|
|
auto result = Copy("Hello", std::span(buffer_, 0));
|
|
EXPECT_EQ(0u, result.size());
|
|
EXPECT_FALSE(result.ok());
|
|
EXPECT_STREQ(kStartingString, buffer_);
|
|
}
|
|
|
|
TEST_F(CopyTest, TooSmall_Truncates) {
|
|
auto result = Copy("Hi!", std::span(buffer_, 3));
|
|
EXPECT_EQ(2u, result.size());
|
|
EXPECT_FALSE(result.ok());
|
|
EXPECT_STREQ("Hi", buffer_);
|
|
}
|
|
|
|
TEST_F(CopyTest, ExactFit) {
|
|
auto result = Copy("Hi!", std::span(buffer_, 4));
|
|
EXPECT_EQ(3u, result.size());
|
|
EXPECT_TRUE(result.ok());
|
|
EXPECT_STREQ("Hi!", buffer_);
|
|
}
|
|
|
|
TEST_F(CopyTest, NullTerminatorsInString) {
|
|
ASSERT_EQ(4u, Copy("\0!\0\0"sv, std::span(buffer_, 5)).size());
|
|
EXPECT_EQ("\0!\0\0"sv, std::string_view(buffer_, 4));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace pw::string
|