/* * Copyright (C) 2016 The Android Open Source Project * * 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 <shared/nano_string.h> #include <string.h> // brings strlen, strncpy, and memset into scope. #include <stdint.h> #include <gtest/gtest.h> #include <shared/array_length.h> // This "using directive" intentionally makes the symbols 'strlen', 'strncpy', // and 'memset' "ambigious" at this point. This means that every use of these // needs to be fully qualified in our tests below. That's as desired for // clarity and to avoid accidentally invoking the wrong version. // Note that a leading bare "::" is the fully qualified version of the // C library methods. using namespace nanoapp_testing; static constexpr size_t kMemsetBufferLen = 16; static constexpr int kUnsetValue = 0x5F; static constexpr int kNewValue = 0xB8; template<size_t kLenToSet> static void testMemset() { uint8_t expected[kMemsetBufferLen]; uint8_t actual[arrayLength(expected)]; static_assert(kLenToSet <= arrayLength(expected), "Bad test invocation"); ::memset(expected, kUnsetValue, sizeof(expected)); ::memset(actual, kUnsetValue, sizeof(actual)); ::memset(expected, kNewValue, kLenToSet); nanoapp_testing::memset(actual, kNewValue, kLenToSet); EXPECT_EQ(0, memcmp(expected, actual, sizeof(expected))); } TEST(NanoStringsTest, MemsetZeroBytes) { testMemset<0>(); } TEST(NanoStringsTest, MemsetPartialArray) { testMemset<(kMemsetBufferLen / 2) - 1>(); } TEST(NanoStringsTest, MemsetFullArray) { testMemset<kMemsetBufferLen>(); } static constexpr size_t kMemcpyBufferLen = 8; static constexpr uint8_t kMemcpySrc[kMemcpyBufferLen] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; template<size_t kLenToCopy> static void testMemcpy() { uint8_t expected[arrayLength(kMemcpySrc)]; uint8_t actual[arrayLength(expected)]; static_assert(kLenToCopy <= arrayLength(kMemcpySrc), "Bad test invocation"); ::memset(expected, kUnsetValue, sizeof(expected)); ::memset(actual, kUnsetValue, sizeof(actual)); ::memcpy(expected, kMemcpySrc, kLenToCopy); nanoapp_testing::memcpy(actual, kMemcpySrc, kLenToCopy); EXPECT_EQ(0, memcmp(expected, actual, sizeof(expected))); } TEST(NanoStringsTest, MemcpyZeroBytes) { testMemcpy<0>(); } TEST(NanoStringsTest, MemcpyPartialArray) { testMemcpy<(kMemcpyBufferLen / 2) - 1>(); } TEST(NanoStringsTest, MemcpyFullArray) { testMemcpy<kMemcpyBufferLen>(); } TEST(NanoStringsTest, StrlenEmptyString) { const char *str = ""; EXPECT_EQ(::strlen(str), nanoapp_testing::strlen(str)); } TEST(NanoStringsTest, StrlenNormal) { const char *str = "random string\n"; EXPECT_EQ(::strlen(str), nanoapp_testing::strlen(str)); } static constexpr size_t kStrncpyMax = 10; static constexpr char kShortString[] = "short"; static constexpr char kLongString[] = "Kind of long string"; static constexpr char kExactString[] = "0123456789"; static void testStrncpy(const char *str, size_t len) { char expected[kStrncpyMax]; char actual[arrayLength(expected)]; ::memset(expected, kUnsetValue, sizeof(expected)); ::memset(actual, kUnsetValue, sizeof(actual)); ::strncpy(expected, str, len); nanoapp_testing::strncpy(actual, str, len); EXPECT_EQ(0, memcmp(expected, actual, sizeof(expected))); } TEST(NanoStringsTest, Strncpy) { testStrncpy(kShortString, ::strlen(kShortString)); } TEST(NanoStringsTest, StrncpySetsTrailingBytes) { ASSERT_LT(::strlen(kShortString), kStrncpyMax); testStrncpy(kShortString, kStrncpyMax); } TEST(NanoStringsTest, StrncpyMax) { ASSERT_GT(::strlen(kLongString), kStrncpyMax); testStrncpy(kLongString, kStrncpyMax); } TEST(NanoStringsTest, StrncpyNothing) { testStrncpy(kLongString, 0); } TEST(NanoStringsTest, StrncpyExactFit) { ASSERT_EQ(::strlen(kExactString), kStrncpyMax); testStrncpy(kExactString, kStrncpyMax); } static void testHexAscii(uint32_t value, const char *str) { static constexpr size_t kAsciiLen = nanoapp_testing::kUint32ToHexAsciiBufferMinLen; char array[kAsciiLen + 1]; array[kAsciiLen] = kUnsetValue; uint32ToHexAscii(array, sizeof(array), value); EXPECT_EQ(kUnsetValue, array[kAsciiLen]); array[kAsciiLen] = '\0'; EXPECT_STREQ(str, array); } TEST(NanoStringsTest, Uint32ToHexAscii) { testHexAscii(0x1234ABCD, "0x1234ABCD"); } TEST(NanoStringsTest, Uint32ToHexAsciiMin) { testHexAscii(0, "0x00000000"); } TEST(NanoStringsTest, Uint32ToHexAsciiMax) { testHexAscii(0xFFFFFFFF, "0xFFFFFFFF"); }