summaryrefslogtreecommitdiffstats
path: root/tests/string_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/string_test.cpp')
-rw-r--r--tests/string_test.cpp359
1 files changed, 236 insertions, 123 deletions
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index f1ac9dd..1d63c76 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -14,15 +14,22 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
+#define _GNU_SOURCE 1
+
+#include <string.h>
#include <errno.h>
+#include <gtest/gtest.h>
#include <malloc.h>
#include <math.h>
-#include <string.h>
#include "buffer_tests.h"
+#if defined(__BIONIC__)
+#define STRLCPY_SUPPORTED
+#define STRLCAT_SUPPORTED
+#endif
+
#define KB 1024
#define SMALL 1*KB
#define MEDIUM 4*KB
@@ -68,32 +75,38 @@ TEST(string, strerror_concurrent) {
ASSERT_STREQ("Unknown error 1001", strerror1001);
#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
+ GTEST_LOG_(INFO) << "Skipping test, requires a thread safe strerror.";
#endif // __BIONIC__
}
-TEST(string, strerror_r) {
-#if defined(__BIONIC__) // glibc's strerror_r doesn't even have the same signature as the POSIX one.
+TEST(string, gnu_strerror_r) {
char buf[256];
+ // Note that glibc doesn't necessarily write into the buffer.
+
// Valid.
- ASSERT_EQ(0, strerror_r(0, buf, sizeof(buf)));
+ ASSERT_STREQ("Success", strerror_r(0, buf, sizeof(buf)));
+#if defined(__BIONIC__)
ASSERT_STREQ("Success", buf);
- ASSERT_EQ(0, strerror_r(1, buf, sizeof(buf)));
+#endif
+ ASSERT_STREQ("Operation not permitted", strerror_r(1, buf, sizeof(buf)));
+#if defined(__BIONIC__)
ASSERT_STREQ("Operation not permitted", buf);
+#endif
// Invalid.
- ASSERT_EQ(0, strerror_r(-1, buf, sizeof(buf)));
+ ASSERT_STREQ("Unknown error -1", strerror_r(-1, buf, sizeof(buf)));
ASSERT_STREQ("Unknown error -1", buf);
- ASSERT_EQ(0, strerror_r(1234, buf, sizeof(buf)));
+ ASSERT_STREQ("Unknown error 1234", strerror_r(1234, buf, sizeof(buf)));
ASSERT_STREQ("Unknown error 1234", buf);
// Buffer too small.
- ASSERT_EQ(-1, strerror_r(0, buf, 2));
- ASSERT_EQ(ERANGE, errno);
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+ errno = 0;
+ memset(buf, 0, sizeof(buf));
+ ASSERT_EQ(buf, strerror_r(4567, buf, 2));
+ ASSERT_STREQ("U", buf);
+ // The GNU strerror_r doesn't set errno (the POSIX one sets it to ERANGE).
+ ASSERT_EQ(0, errno);
}
TEST(string, strsignal) {
@@ -129,8 +142,7 @@ TEST(string, strsignal_concurrent) {
ASSERT_STREQ("Unknown signal 1001", strsignal1001);
}
-// TODO: where did these numbers come from?
-#define POS_ITER 10
+// TODO: where did this number come from?
#define ITER 500
// For every length we want to test, vary and change alignment
@@ -139,8 +151,9 @@ TEST(string, strsignal_concurrent) {
// These tests contributed by Intel Corporation.
// TODO: make these tests more intention-revealing and less random.
template<class Character>
-struct StringTestState {
- StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN) {
+class StringTestState {
+ public:
+ StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN), align1_index_(0), align2_index_(0) {
int max_alignment = 64;
// TODO: fix the tests to not sometimes use twice their specified "MAX_LEN".
@@ -159,15 +172,30 @@ struct StringTestState {
free(glob_ptr2);
}
- void NewIteration() {
- int alignments[] = { 24, 32, 16, 48, 1, 2, 3, 0, 5, 11 };
- int usable_alignments = 10;
- int align1 = alignments[random() % (usable_alignments - 1)];
- int align2 = alignments[random() % (usable_alignments - 1)];
+ void BeginIterations() {
+ align1_index_ = 0;
+ align2_index_ = 0;
+
+ ResetPointers();
+ }
+
+ bool HasNextIteration() {
+ return (align1_index_ != (alignments_size - 1) || align2_index_ != (alignments_size - 1));
+ }
+
+ void NextIteration() {
+ if (align1_index_ == (alignments_size - 1) && align2_index_ == (alignments_size - 1)) {
+ return;
+ }
+
+ if (align1_index_ == (alignments_size - 1)) {
+ align1_index_ = 0;
+ align2_index_++;
+ } else {
+ align1_index_++;
+ }
- ptr = glob_ptr + align1;
- ptr1 = glob_ptr1 + align1;
- ptr2 = glob_ptr2 + align2;
+ ResetPointers();
}
const size_t MAX_LEN;
@@ -176,7 +204,10 @@ struct StringTestState {
size_t len[ITER + 1];
private:
+ static size_t alignments[];
+ static size_t alignments_size;
Character *glob_ptr, *glob_ptr1, *glob_ptr2;
+ size_t align1_index_, align2_index_;
// Calculate input lengths and fill state.len with them.
// Test small lengths with more density than big ones. Manually push
@@ -193,19 +224,33 @@ struct StringTestState {
}
len[n++] = MAX_LEN;
}
+
+ void ResetPointers() {
+ if (align1_index_ == alignments_size || align2_index_ == alignments_size) {
+ ptr = ptr1 = ptr2 = nullptr;
+ } else {
+ ptr = glob_ptr + alignments[align1_index_];
+ ptr1 = glob_ptr1 + alignments[align1_index_];
+ ptr2 = glob_ptr2 + alignments[align2_index_];
+ }
+ }
};
+template<class Character>
+size_t StringTestState<Character>::alignments[] = { 24, 32, 16, 48, 0, 1, 2, 3, 4, 5, 6, 7, 11 };
+
+template<class Character>
+size_t StringTestState<Character>::alignments_size = sizeof(alignments)/sizeof(size_t);
+
TEST(string, strcat) {
StringTestState<char> state(SMALL);
for (size_t i = 1; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr2, '\2', state.MAX_LEN);
state.ptr2[state.MAX_LEN - 1] = '\0';
memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
- memset(state.ptr1, random() & 255, state.len[i]);
+ memset(state.ptr1, 'L', state.len[i]);
state.ptr1[random() % state.len[i]] = '\0';
state.ptr1[state.len[i] - 1] = '\0';
@@ -378,13 +423,11 @@ TEST(string, strchr_multiple) {
}
TEST(string, strchr) {
- int seek_char = random() & 255;
+ int seek_char = 'R';
StringTestState<char> state(SMALL);
for (size_t i = 1; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
if (~seek_char > 0) {
memset(state.ptr1, ~seek_char, state.len[i]);
} else {
@@ -413,9 +456,7 @@ TEST(string, strchr) {
TEST(string, strcmp) {
StringTestState<char> state(SMALL);
for (size_t i = 1; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr1, 'v', state.MAX_LEN);
memset(state.ptr2, 'n', state.MAX_LEN);
state.ptr1[state.len[i] - 1] = '\0';
@@ -449,9 +490,7 @@ TEST(string, strcmp) {
TEST(string, stpcpy) {
StringTestState<char> state(SMALL);
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
size_t pos = random() % state.MAX_LEN;
memset(state.ptr1, '\2', pos);
@@ -475,9 +514,7 @@ TEST(string, stpcpy) {
TEST(string, strcpy) {
StringTestState<char> state(SMALL);
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
size_t pos = random() % state.MAX_LEN;
memset(state.ptr1, '\2', pos);
@@ -500,12 +537,10 @@ TEST(string, strcpy) {
}
TEST(string, strlcat) {
-#if defined(__BIONIC__)
+#if defined(STRLCAT_SUPPORTED)
StringTestState<char> state(SMALL);
for (size_t i = 0; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]);
state.ptr2[state.MAX_LEN - 1] = '\0';
memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
@@ -525,21 +560,16 @@ TEST(string, strlcat) {
ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
}
}
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+#else
+ GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
}
TEST(string, strlcpy) {
-#if defined(__BIONIC__)
+#if defined(STRLCPY_SUPPORTED)
StringTestState<char> state(SMALL);
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
- int rand = random() & 255;
- if (rand < 1) {
- rand = 1;
- }
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
+ int rand = 'O';
memset(state.ptr1, rand, state.MAX_LEN);
size_t pos = random() % state.MAX_LEN;
@@ -548,7 +578,7 @@ TEST(string, strlcpy) {
}
memcpy(state.ptr, state.ptr1, state.MAX_LEN);
- memset(state.ptr2, random() & 255, state.MAX_LEN);
+ memset(state.ptr2, 'I', state.MAX_LEN);
memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN);
if (pos > state.MAX_LEN - 1) {
@@ -562,22 +592,20 @@ TEST(string, strlcpy) {
ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
(memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
}
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+#else
+ GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
}
TEST(string, strncat) {
StringTestState<char> state(SMALL);
for (size_t i = 1; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr2, '\2', state.MAX_LEN);
state.ptr2[state.MAX_LEN - 1] = '\0';
memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
- memset(state.ptr1, random() & 255, state.len[i]);
+ memset(state.ptr1, 'I', state.len[i]);
state.ptr1[random() % state.len[i]] = '\0';
state.ptr1[state.len[i] - 1] = '\0';
@@ -596,9 +624,7 @@ TEST(string, strncat) {
TEST(string, strncmp) {
StringTestState<char> state(SMALL);
for (size_t i = 1; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr1, 'v', state.MAX_LEN);
memset(state.ptr2, 'n', state.MAX_LEN);
state.ptr1[state.len[i] - 1] = '\0';
@@ -632,12 +658,8 @@ TEST(string, strncmp) {
TEST(string, stpncpy) {
StringTestState<char> state(SMALL);
- for (size_t j = 0; j < ITER; j++) {
- state.NewIteration();
-
- // Choose a random value to fill the string, except \0 (string terminator),
- // or \1 (guarantees it's different from anything in ptr2).
- memset(state.ptr1, (random() % 254) + 2, state.MAX_LEN);
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
+ memset(state.ptr1, 'J', state.MAX_LEN);
// Choose a random size for our src buffer.
size_t ptr1_len = random() % state.MAX_LEN;
state.ptr1[ptr1_len] = '\0';
@@ -671,12 +693,10 @@ TEST(string, stpncpy) {
TEST(string, strncpy) {
StringTestState<char> state(SMALL);
- for (size_t j = 0; j < ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
// Choose a random value to fill the string, except \0 (string terminator),
// or \1 (guarantees it's different from anything in ptr2).
- memset(state.ptr1, (random() % 254) + 2, state.MAX_LEN);
+ memset(state.ptr1, 'K', state.MAX_LEN);
// Choose a random size for our src buffer.
size_t ptr1_len = random() % state.MAX_LEN;
state.ptr1[ptr1_len] = '\0';
@@ -709,12 +729,10 @@ TEST(string, strncpy) {
}
TEST(string, strrchr) {
- int seek_char = random() & 255;
+ int seek_char = 'M';
StringTestState<char> state(SMALL);
for (size_t i = 1; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
if (~seek_char > 0) {
memset(state.ptr1, ~seek_char, state.len[i]);
} else {
@@ -741,12 +759,10 @@ TEST(string, strrchr) {
}
TEST(string, memchr) {
- int seek_char = random() & 255;
+ int seek_char = 'N';
StringTestState<char> state(SMALL);
for (size_t i = 0; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr1, ~seek_char, state.len[i]);
size_t pos = random() % state.MAX_LEN;
@@ -772,12 +788,10 @@ TEST(string, memchr_zero) {
}
TEST(string, memrchr) {
- int seek_char = random() & 255;
+ int seek_char = 'P';
StringTestState<char> state(SMALL);
for (size_t i = 0; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr1, ~seek_char, state.len[i]);
size_t pos = random() % state.MAX_LEN;
@@ -797,11 +811,9 @@ TEST(string, memrchr) {
TEST(string, memcmp) {
StringTestState<char> state(SMALL);
for (size_t i = 0; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
- int c1 = random() & 0xff;
- int c2 = random() & 0xff;
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
+ int c1 = 'A';
+ int c2 = 'N';
memset(state.ptr1, c1, state.MAX_LEN);
memset(state.ptr2, c1, state.MAX_LEN);
@@ -820,9 +832,7 @@ TEST(string, wmemcmp) {
StringTestState<wchar_t> state(SMALL);
for (size_t i = 0; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
long long mask = ((long long) 1 << 8 * sizeof(wchar_t)) - 1;
int c1 = rand() & mask;
int c2 = rand() & mask;
@@ -842,11 +852,9 @@ TEST(string, wmemcmp) {
TEST(string, memcpy) {
StringTestState<char> state(LARGE);
- int rand = random() & 255;
+ int rand = 4;
for (size_t i = 0; i < state.n - 1; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
size_t pos = random() % (state.MAX_LEN - state.len[i]);
memset(state.ptr1, rand, state.len[i]);
@@ -864,11 +872,9 @@ TEST(string, memcpy) {
TEST(string, memset) {
StringTestState<char> state(LARGE);
- char ch = random () & 255;
+ char ch = 'P';
for (size_t i = 0; i < state.n - 1; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
memset(state.ptr1, ~ch, state.MAX_LEN);
memcpy(state.ptr2, state.ptr1, state.MAX_LEN);
@@ -887,14 +893,12 @@ TEST(string, memset) {
TEST(string, memmove) {
StringTestState<char> state(LARGE);
for (size_t i = 0; i < state.n - 1; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
- memset(state.ptr1, random() & 255, 2 * state.MAX_LEN);
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
+ memset(state.ptr1, 'Q', 2 * state.MAX_LEN);
size_t pos = random() % (state.MAX_LEN - state.len[i]);
- memset(state.ptr1, random() & 255, state.len[i]);
+ memset(state.ptr1, 'R', state.len[i]);
memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
memcpy(state.ptr, state.ptr1, state.len[i]);
memcpy(state.ptr1 + pos, state.ptr, state.len[i]);
@@ -920,8 +924,8 @@ TEST(string, memmove_cache_size) {
for (int i = 0; i < 5; i++) {
char* ptr2 = glob_ptr2 + alignments[i];
- memset(ptr1, random() & 255, 2 * len);
- memset(ptr1, random() & 255, len);
+ memset(ptr1, 'S', 2 * len);
+ memset(ptr1, 'T', len);
memcpy(ptr2, ptr1, 2 * len);
memcpy(ptr, ptr1, len);
memcpy(ptr1 + pos, ptr, len);
@@ -987,11 +991,9 @@ TEST(string, memmove_check) {
TEST(string, bcopy) {
StringTestState<char> state(LARGE);
for (size_t i = 0; i < state.n; i++) {
- for (size_t j = 0; j < POS_ITER; j++) {
- state.NewIteration();
-
- memset(state.ptr1, random() & 255, state.MAX_LEN);
- memset(state.ptr1 + state.MAX_LEN, random() & 255, state.MAX_LEN);
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
+ memset(state.ptr1, '4', state.MAX_LEN);
+ memset(state.ptr1 + state.MAX_LEN, 'a', state.MAX_LEN);
memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
size_t start = random() % (2 * state.MAX_LEN - state.len[i]);
@@ -1005,10 +1007,8 @@ TEST(string, bcopy) {
TEST(string, bzero) {
StringTestState<char> state(LARGE);
- for (size_t j = 0; j < ITER; j++) {
- state.NewIteration();
-
- memset(state.ptr1, random() & 255, state.MAX_LEN);
+ for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
+ memset(state.ptr1, 'R', state.MAX_LEN);
size_t start = random() % state.MAX_LEN;
size_t end = start + random() % (state.MAX_LEN - start);
@@ -1105,6 +1105,36 @@ TEST(string, strcpy_overread) {
RunSrcDstBufferOverreadTest(DoStrcpyTest);
}
+#if defined(STRLCPY_SUPPORTED)
+static void DoStrlcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
+ if (len >= 1) {
+ memset(src, (32 + (len % 96)), len - 1);
+ src[len-1] = '\0';
+ memset(dst, 0, len);
+ ASSERT_EQ(len-1, strlcpy(reinterpret_cast<char*>(dst),
+ reinterpret_cast<char*>(src), len));
+ ASSERT_TRUE(memcmp(src, dst, len) == 0);
+ }
+}
+#endif
+
+TEST(string, strlcpy_align) {
+#if defined(STRLCPY_SUPPORTED)
+ RunSrcDstBufferAlignTest(LARGE, DoStrlcpyTest);
+#else
+ GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
+}
+
+TEST(string, strlcpy_overread) {
+#if defined(STRLCPY_SUPPORTED)
+ RunSrcDstBufferOverreadTest(DoStrlcpyTest);
+#else
+ GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
+#endif
+}
+
+
static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
if (len >= 1) {
memset(src, (32 + (len % 96)), len - 1);
@@ -1177,6 +1207,55 @@ TEST(string, strcat_overread) {
RunSrcDstBufferOverreadTest(DoStrcatTest);
}
+#if defined(STRLCAT_SUPPORTED)
+static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
+ if (len >= 1) {
+ int value = 32 + (len % 96);
+ memset(src, value, len - 1);
+ src[len-1] = '\0';
+
+ if (len >= STRCAT_DST_LEN) {
+ // Create a small buffer for doing quick compares in each loop.
+ uint8_t cmp_buf[STRCAT_DST_LEN];
+ // Make sure dst string contains a different value then the src string.
+ int value2 = 32 + (value + 2) % 96;
+ memset(cmp_buf, value2, sizeof(cmp_buf));
+
+ for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
+ memset(dst, value2, i-1);
+ memset(dst+i-1, 0, len-i);
+ src[len-i] = '\0';
+ ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
+ reinterpret_cast<char*>(src), len));
+ ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
+ ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
+ }
+ } else {
+ dst[0] = '\0';
+ ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
+ reinterpret_cast<char*>(src), len));
+ ASSERT_TRUE(memcmp(src, dst, len) == 0);
+ }
+ }
+}
+#endif
+
+TEST(string, strlcat_align) {
+#if defined(STRLCAT_SUPPORTED)
+ RunSrcDstBufferAlignTest(MEDIUM, DoStrlcatTest, LargeSetIncrement);
+#else
+ GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
+}
+
+TEST(string, strlcat_overread) {
+#if defined(STRLCAT_SUPPORTED)
+ RunSrcDstBufferOverreadTest(DoStrlcatTest);
+#else
+ GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
+#endif
+}
+
static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
if (len >= 1) {
memset(buf1, (32 + (len % 96)), len - 1);
@@ -1287,3 +1366,37 @@ TEST(string, strchr_align) {
TEST(string, strchr_overread) {
RunSingleBufferOverreadTest(DoStrchrTest);
}
+
+static void TestBasename(const char* in, const char* expected_out) {
+ errno = 0;
+ const char* out = basename(in);
+ ASSERT_STREQ(expected_out, out) << in;
+ ASSERT_EQ(0, errno) << in;
+}
+
+TEST(string, __gnu_basename) {
+ TestBasename("", "");
+ TestBasename("/usr/lib", "lib");
+ TestBasename("/usr/", "");
+ TestBasename("usr", "usr");
+ TestBasename("/", "");
+ TestBasename(".", ".");
+ TestBasename("..", "..");
+ TestBasename("///", "");
+ TestBasename("//usr//lib//", "");
+}
+
+TEST(string, strnlen_147048) {
+ // https://code.google.com/p/android/issues/detail?id=147048
+ char stack_src[64] = {0};
+ EXPECT_EQ(0U, strnlen(stack_src, 1024*1024*1024));
+ char* heap_src = new char[1];
+ *heap_src = '\0';
+ EXPECT_EQ(0U, strnlen(heap_src, 1024*1024*1024));
+ delete[] heap_src;
+}
+
+TEST(string, mempcpy) {
+ char dst[6];
+ ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
+}