string_test.cpp revision 3a657d01eca1529ba7002cbee44e149988834c9d
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <errno.h>
20#include <malloc.h>
21#include <math.h>
22#include <string.h>
23
24#include "buffer_tests.h"
25
26#define KB 1024
27#define SMALL 1*KB
28#define MEDIUM 4*KB
29#define LARGE 64*KB
30
31static int signum(int i) {
32  if (i < 0) {
33    return -1;
34  } else if (i > 0) {
35    return 1;
36  }
37  return 0;
38}
39
40TEST(string, strerror) {
41  // Valid.
42  ASSERT_STREQ("Success", strerror(0));
43  ASSERT_STREQ("Operation not permitted", strerror(1));
44
45  // Invalid.
46  ASSERT_STREQ("Unknown error -1", strerror(-1));
47  ASSERT_STREQ("Unknown error 1234", strerror(1234));
48}
49
50#if defined(__BIONIC__)
51static void* ConcurrentStrErrorFn(void*) {
52  bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
53  return reinterpret_cast<void*>(equal);
54}
55#endif // __BIONIC__
56
57// glibc's strerror isn't thread safe, only its strsignal.
58TEST(string, strerror_concurrent) {
59#if defined(__BIONIC__)
60  const char* strerror1001 = strerror(1001);
61  ASSERT_STREQ("Unknown error 1001", strerror1001);
62
63  pthread_t t;
64  ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrErrorFn, NULL));
65  void* result;
66  ASSERT_EQ(0, pthread_join(t, &result));
67  ASSERT_TRUE(static_cast<bool>(result));
68
69  ASSERT_STREQ("Unknown error 1001", strerror1001);
70#else // __BIONIC__
71  GTEST_LOG_(INFO) << "This test does nothing.\n";
72#endif // __BIONIC__
73}
74
75TEST(string, strerror_r) {
76#if defined(__BIONIC__) // glibc's strerror_r doesn't even have the same signature as the POSIX one.
77  char buf[256];
78
79  // Valid.
80  ASSERT_EQ(0, strerror_r(0, buf, sizeof(buf)));
81  ASSERT_STREQ("Success", buf);
82  ASSERT_EQ(0, strerror_r(1, buf, sizeof(buf)));
83  ASSERT_STREQ("Operation not permitted", buf);
84
85  // Invalid.
86  ASSERT_EQ(0, strerror_r(-1, buf, sizeof(buf)));
87  ASSERT_STREQ("Unknown error -1", buf);
88  ASSERT_EQ(0, strerror_r(1234, buf, sizeof(buf)));
89  ASSERT_STREQ("Unknown error 1234", buf);
90
91  // Buffer too small.
92  ASSERT_EQ(-1, strerror_r(0, buf, 2));
93  ASSERT_EQ(ERANGE, errno);
94#else // __BIONIC__
95  GTEST_LOG_(INFO) << "This test does nothing.\n";
96#endif // __BIONIC__
97}
98
99TEST(string, strsignal) {
100  // A regular signal.
101  ASSERT_STREQ("Hangup", strsignal(1));
102
103  // A real-time signal.
104  ASSERT_STREQ("Real-time signal 14", strsignal(SIGRTMIN + 14));
105  // One of the signals the C library keeps to itself.
106  ASSERT_STREQ("Unknown signal 32", strsignal(__SIGRTMIN));
107
108  // Errors.
109  ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
110  ASSERT_STREQ("Unknown signal 0", strsignal(0)); // Still too small.
111  ASSERT_STREQ("Unknown signal 1234", strsignal(1234)); // Too large.
112}
113
114static void* ConcurrentStrSignalFn(void*) {
115  bool equal = (strcmp("Unknown signal 2002", strsignal(2002)) == 0);
116  return reinterpret_cast<void*>(equal);
117}
118
119TEST(string, strsignal_concurrent) {
120  const char* strsignal1001 = strsignal(1001);
121  ASSERT_STREQ("Unknown signal 1001", strsignal1001);
122
123  pthread_t t;
124  ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrSignalFn, NULL));
125  void* result;
126  ASSERT_EQ(0, pthread_join(t, &result));
127  ASSERT_TRUE(static_cast<bool>(result));
128
129  ASSERT_STREQ("Unknown signal 1001", strsignal1001);
130}
131
132// TODO: where did these numbers come from?
133#define POS_ITER    10
134#define ITER        500
135
136// For every length we want to test, vary and change alignment
137// of allocated memory, fill it with some values, calculate
138// expected result and then run function and compare what we got.
139// These tests contributed by Intel Corporation.
140// TODO: make these tests more intention-revealing and less random.
141template<class Character>
142struct StringTestState {
143  StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN) {
144    int max_alignment = 64;
145
146    // TODO: fix the tests to not sometimes use twice their specified "MAX_LEN".
147    glob_ptr = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
148    glob_ptr1 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
149    glob_ptr2 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
150
151    InitLenArray();
152
153    srandom(1234);
154  }
155
156  ~StringTestState() {
157    free(glob_ptr);
158    free(glob_ptr1);
159    free(glob_ptr2);
160  }
161
162  void NewIteration() {
163    int alignments[] = { 24, 32, 16, 48, 1, 2, 3, 0, 5, 11 };
164    int usable_alignments = 10;
165    int align1 = alignments[random() % (usable_alignments - 1)];
166    int align2 = alignments[random() % (usable_alignments - 1)];
167
168    ptr = glob_ptr + align1;
169    ptr1 = glob_ptr1 + align1;
170    ptr2 = glob_ptr2 + align2;
171  }
172
173  const size_t MAX_LEN;
174  Character *ptr, *ptr1, *ptr2;
175  size_t n;
176  int len[ITER + 1];
177
178 private:
179  Character *glob_ptr, *glob_ptr1, *glob_ptr2;
180
181  // Calculate input lengths and fill state.len with them.
182  // Test small lengths with more density than big ones. Manually push
183  // smallest (0) and biggest (MAX_LEN) lengths. Avoid repeats.
184  // Return number of lengths to test.
185  void InitLenArray() {
186    n = 0;
187    len[n++] = 0;
188    for (size_t i = 1; i < ITER; ++i) {
189      int l = (int) exp(log((double) MAX_LEN) * i / ITER);
190      if (l != len[n - 1]) {
191        len[n++] = l;
192      }
193    }
194    len[n++] = MAX_LEN;
195  }
196};
197
198TEST(string, strcat) {
199  StringTestState<char> state(SMALL);
200  for (size_t i = 1; i < state.n; i++) {
201    for (size_t j = 0; j < POS_ITER; j++) {
202      state.NewIteration();
203
204      memset(state.ptr2, '\2', state.MAX_LEN);
205      state.ptr2[state.MAX_LEN - 1] = '\0';
206      memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
207
208      memset(state.ptr1, random() & 255, state.len[i]);
209      state.ptr1[random() % state.len[i]] = '\0';
210      state.ptr1[state.len[i] - 1] = '\0';
211
212      strcpy(state.ptr + state.MAX_LEN - 1, state.ptr1);
213
214      EXPECT_TRUE(strcat(state.ptr2, state.ptr1) == state.ptr2);
215      EXPECT_TRUE(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN) == 0);
216    }
217  }
218}
219
220// one byte target with "\0" source
221TEST(string, strcpy2) {
222  char buf[1];
223  char* orig = strdup("");
224  ASSERT_EQ(buf, strcpy(buf, orig));
225  ASSERT_EQ('\0', buf[0]);
226  free(orig);
227}
228
229// multibyte target where we under fill target
230TEST(string, strcpy3) {
231  char buf[10];
232  char* orig = strdup("12345");
233  memset(buf, 'A', sizeof(buf));
234  ASSERT_EQ(buf, strcpy(buf, orig));
235  ASSERT_STREQ("12345", buf);
236  ASSERT_EQ('A',  buf[6]);
237  ASSERT_EQ('A',  buf[7]);
238  ASSERT_EQ('A',  buf[8]);
239  ASSERT_EQ('A',  buf[9]);
240  free(orig);
241}
242
243// multibyte target where we fill target exactly
244TEST(string, strcpy4) {
245  char buf[10];
246  char* orig = strdup("123456789");
247  memset(buf, 'A', sizeof(buf));
248  ASSERT_EQ(buf, strcpy(buf, orig));
249  ASSERT_STREQ("123456789", buf);
250  free(orig);
251}
252
253// one byte target with "\0" source
254TEST(string, stpcpy2) {
255  char buf[1];
256  char* orig = strdup("");
257  ASSERT_EQ(buf, stpcpy(buf, orig));
258  ASSERT_EQ('\0', buf[0]);
259  free(orig);
260}
261
262// multibyte target where we under fill target
263TEST(string, stpcpy3) {
264  char buf[10];
265  char* orig = strdup("12345");
266  memset(buf, 'A', sizeof(buf));
267  ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig));
268  ASSERT_STREQ("12345", buf);
269  ASSERT_EQ('A',  buf[6]);
270  ASSERT_EQ('A',  buf[7]);
271  ASSERT_EQ('A',  buf[8]);
272  ASSERT_EQ('A',  buf[9]);
273  free(orig);
274}
275
276// multibyte target where we fill target exactly
277TEST(string, stpcpy4) {
278  char buf[10];
279  char* orig = strdup("123456789");
280  memset(buf, 'A', sizeof(buf));
281  ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig));
282  ASSERT_STREQ("123456789", buf);
283  free(orig);
284}
285
286TEST(string, strcat2) {
287  char buf[10];
288  memset(buf, 'A', sizeof(buf));
289  buf[0] = 'a';
290  buf[1] = '\0';
291  char* res = strcat(buf, "01234");
292  ASSERT_EQ(buf, res);
293  ASSERT_STREQ("a01234", buf);
294  ASSERT_EQ('A',  buf[7]);
295  ASSERT_EQ('A',  buf[8]);
296  ASSERT_EQ('A',  buf[9]);
297}
298
299TEST(string, strcat3) {
300  char buf[10];
301  memset(buf, 'A', sizeof(buf));
302  buf[0] = 'a';
303  buf[1] = '\0';
304  char* res = strcat(buf, "01234567");
305  ASSERT_EQ(buf, res);
306  ASSERT_STREQ("a01234567", buf);
307}
308
309TEST(string, strncat2) {
310  char buf[10];
311  memset(buf, 'A', sizeof(buf));
312  buf[0] = 'a';
313  buf[1] = '\0';
314  char* res = strncat(buf, "01234", sizeof(buf) - strlen(buf) - 1);
315  ASSERT_EQ(buf, res);
316  ASSERT_STREQ("a01234", buf);
317  ASSERT_EQ('A',  buf[7]);
318  ASSERT_EQ('A',  buf[8]);
319  ASSERT_EQ('A',  buf[9]);
320}
321
322TEST(string, strncat3) {
323  char buf[10];
324  memset(buf, 'A', sizeof(buf));
325  buf[0] = 'a';
326  buf[1] = '\0';
327  char* res = strncat(buf, "0123456789", 5);
328  ASSERT_EQ(buf, res);
329  ASSERT_STREQ("a01234", buf);
330  ASSERT_EQ('A',  buf[7]);
331  ASSERT_EQ('A',  buf[8]);
332  ASSERT_EQ('A',  buf[9]);
333}
334
335TEST(string, strncat4) {
336  char buf[10];
337  memset(buf, 'A', sizeof(buf));
338  buf[0] = 'a';
339  buf[1] = '\0';
340  char* res = strncat(buf, "01234567", 8);
341  ASSERT_EQ(buf, res);
342  ASSERT_STREQ("a01234567", buf);
343}
344
345TEST(string, strncat5) {
346  char buf[10];
347  memset(buf, 'A', sizeof(buf));
348  buf[0] = 'a';
349  buf[1] = '\0';
350  char* res = strncat(buf, "01234567", 9);
351  ASSERT_EQ(buf, res);
352  ASSERT_STREQ("a01234567", buf);
353}
354
355TEST(string, strchr_with_0) {
356  char buf[10];
357  const char* s = "01234";
358  memcpy(buf, s, strlen(s) + 1);
359  EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
360}
361
362TEST(string, strchr_multiple) {
363  char str[128];
364  memset(str, 'a', sizeof(str) - 1);
365  str[sizeof(str)-1] = '\0';
366
367  // Verify that strchr finds the first occurrence of 'a' in a string
368  // filled with 'a' characters. Iterate over the string putting
369  // non 'a' characters at the front of the string during each iteration
370  // and continue to verify that strchr can find the first occurrence
371  // properly. The idea is to cover all possible alignments of the location
372  // of the first occurrence of the 'a' character and which includes
373  // other 'a' characters close by.
374  for (size_t i = 0; i < sizeof(str) - 1; i++) {
375    EXPECT_EQ(&str[i], strchr(str, 'a'));
376    str[i] = 'b';
377  }
378}
379
380TEST(string, strchr) {
381  int seek_char = random() & 255;
382
383  StringTestState<char> state(SMALL);
384  for (size_t i = 1; i < state.n; i++) {
385    for (size_t j = 0; j < POS_ITER; j++) {
386      state.NewIteration();
387
388      if (~seek_char > 0) {
389        memset(state.ptr1, ~seek_char, state.len[i]);
390      } else {
391        memset(state.ptr1, '\1', state.len[i]);
392      }
393      state.ptr1[state.len[i] - 1] = '\0';
394
395      int pos = random() % state.MAX_LEN;
396      char* expected;
397      if (pos >= state.len[i] - 1) {
398        if (seek_char == 0) {
399          expected = state.ptr1 + state.len[i] - 1;
400        } else {
401          expected = NULL;
402        }
403      } else {
404        state.ptr1[pos] = seek_char;
405        expected = state.ptr1 + pos;
406      }
407
408      ASSERT_TRUE(strchr(state.ptr1, seek_char) == expected);
409    }
410  }
411}
412
413TEST(string, strcmp) {
414  StringTestState<char> state(SMALL);
415  for (size_t i = 1; i < state.n; i++) {
416    for (size_t j = 0; j < POS_ITER; j++) {
417      state.NewIteration();
418
419      memset(state.ptr1, 'v', state.MAX_LEN);
420      memset(state.ptr2, 'n', state.MAX_LEN);
421      state.ptr1[state.len[i] - 1] = '\0';
422      state.ptr2[state.len[i] - 1] = '\0';
423
424      int pos = 1 + (random() % (state.MAX_LEN - 1));
425      int actual;
426      int expected;
427      if (pos >= state.len[i] - 1) {
428        memcpy(state.ptr1, state.ptr2, state.len[i]);
429        expected = 0;
430        actual = strcmp(state.ptr1, state.ptr2);
431      } else {
432        memcpy(state.ptr1, state.ptr2, pos);
433        if (state.ptr1[pos] > state.ptr2[pos]) {
434          expected = 1;
435        } else if (state.ptr1[pos] == state.ptr2[pos]) {
436          state.ptr1[pos + 1] = '\0';
437          state.ptr2[pos + 1] = '\0';
438          expected = 0;
439        } else {
440          expected = -1;
441        }
442        actual = strcmp(state.ptr1, state.ptr2);
443      }
444
445      ASSERT_EQ(expected, signum(actual));
446    }
447  }
448}
449
450TEST(string, stpcpy) {
451  StringTestState<char> state(SMALL);
452  for (size_t j = 0; j < POS_ITER; j++) {
453    state.NewIteration();
454
455    size_t pos = random() % state.MAX_LEN;
456
457    memset(state.ptr1, '\2', pos);
458    state.ptr1[pos] = '\0';
459    state.ptr1[state.MAX_LEN - 1] = '\0';
460
461    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
462
463    memset(state.ptr2, '\1', state.MAX_LEN);
464    state.ptr2[state.MAX_LEN - 1] = '\0';
465
466    memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
467    memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
468    state.ptr[2 * state.MAX_LEN - 1] = '\0';
469
470    ASSERT_TRUE(stpcpy(state.ptr2, state.ptr1) == state.ptr2 + strlen(state.ptr1));
471    ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
472                 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
473  }
474}
475
476TEST(string, strcpy) {
477  StringTestState<char> state(SMALL);
478  for (size_t j = 0; j < POS_ITER; j++) {
479    state.NewIteration();
480
481    size_t pos = random() % state.MAX_LEN;
482
483    memset(state.ptr1, '\2', pos);
484    state.ptr1[pos] = '\0';
485    state.ptr1[state.MAX_LEN - 1] = '\0';
486
487    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
488
489    memset(state.ptr2, '\1', state.MAX_LEN);
490    state.ptr2[state.MAX_LEN - 1] = '\0';
491
492    memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
493    memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
494    state.ptr[2 * state.MAX_LEN - 1] = '\0';
495
496    ASSERT_TRUE(strcpy(state.ptr2, state.ptr1) == state.ptr2);
497    ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
498                 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
499  }
500}
501
502TEST(string, strlcat) {
503#if defined(__BIONIC__)
504  StringTestState<char> state(SMALL);
505  for (size_t i = 0; i < state.n; i++) {
506    for (size_t j = 0; j < POS_ITER; j++) {
507      state.NewIteration();
508
509      memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]);
510      state.ptr2[state.MAX_LEN - 1] = '\0';
511      memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
512
513      int pos = random() % state.MAX_LEN;
514      memset(state.ptr1, '\3', pos);
515      state.ptr1[pos] = '\0';
516      if (pos < state.len[i]) {
517        memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, pos + 1);
518      } else {
519        memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, state.len[i]);
520        state.ptr[state.MAX_LEN + state.len[i] - 1] = '\0';
521      }
522
523      strlcat(state.ptr2, state.ptr1, state.MAX_LEN + state.len[i]);
524
525      ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
526    }
527  }
528#else // __BIONIC__
529  GTEST_LOG_(INFO) << "This test does nothing.\n";
530#endif // __BIONIC__
531}
532
533TEST(string, strlcpy) {
534#if defined(__BIONIC__)
535  StringTestState<char> state(SMALL);
536  for (size_t j = 0; j < POS_ITER; j++) {
537    state.NewIteration();
538
539    int rand = random() & 255;
540    if (rand < 1) {
541      rand = 1;
542    }
543    memset(state.ptr1, rand, state.MAX_LEN);
544
545    size_t pos = random() % state.MAX_LEN;
546    if (pos < state.MAX_LEN) {
547      state.ptr1[pos] = '\0';
548    }
549    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
550
551    memset(state.ptr2, random() & 255, state.MAX_LEN);
552    memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN);
553
554    if (pos > state.MAX_LEN - 1) {
555      memcpy(state.ptr + state.MAX_LEN, state.ptr1, state.MAX_LEN);
556      state.ptr[2 * state.MAX_LEN - 1] = '\0';
557    } else {
558      memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
559    }
560
561    ASSERT_EQ(strlcpy(state.ptr2, state.ptr1, state.MAX_LEN), strlen(state.ptr1));
562    ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
563                 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
564  }
565#else // __BIONIC__
566  GTEST_LOG_(INFO) << "This test does nothing.\n";
567#endif // __BIONIC__
568}
569
570TEST(string, strncat) {
571  StringTestState<char> state(SMALL);
572  for (size_t i = 1; i < state.n; i++) {
573    for (size_t j = 0; j < POS_ITER; j++) {
574      state.NewIteration();
575
576      memset(state.ptr2, '\2', state.MAX_LEN);
577      state.ptr2[state.MAX_LEN - 1] = '\0';
578      memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
579
580      memset(state.ptr1, random() & 255, state.len[i]);
581      state.ptr1[random() % state.len[i]] = '\0';
582      state.ptr1[state.len[i] - 1] = '\0';
583
584      size_t pos = strlen(state.ptr1);
585
586      size_t actual = random() % state.len[i];
587      strncpy(state.ptr + state.MAX_LEN - 1, state.ptr1, std::min(actual, pos));
588      state.ptr[state.MAX_LEN + std::min(actual, pos) - 1] = '\0';
589
590      ASSERT_TRUE(strncat(state.ptr2, state.ptr1, actual) == state.ptr2);
591      ASSERT_EQ(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN), 0);
592    }
593  }
594}
595
596TEST(string, strncmp) {
597  StringTestState<char> state(SMALL);
598  for (size_t i = 1; i < state.n; i++) {
599    for (size_t j = 0; j < POS_ITER; j++) {
600      state.NewIteration();
601
602      memset(state.ptr1, 'v', state.MAX_LEN);
603      memset(state.ptr2, 'n', state.MAX_LEN);
604      state.ptr1[state.len[i] - 1] = '\0';
605      state.ptr2[state.len[i] - 1] = '\0';
606
607      int pos = 1 + (random() % (state.MAX_LEN - 1));
608      int actual;
609      int expected;
610      if (pos >= state.len[i] - 1) {
611        memcpy(state.ptr1, state.ptr2, state.len[i]);
612        expected = 0;
613        actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
614      } else {
615        memcpy(state.ptr1, state.ptr2, pos);
616        if (state.ptr1[pos] > state.ptr2[pos]) {
617          expected = 1;
618        } else if (state.ptr1[pos] == state.ptr2[pos]) {
619          state.ptr1[pos + 1] = '\0';
620          state.ptr2[pos + 1] = '\0';
621          expected = 0;
622        } else {
623          expected = -1;
624        }
625        actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
626      }
627
628      ASSERT_EQ(expected, signum(actual));
629    }
630  }
631}
632
633TEST(string, stpncpy) {
634  StringTestState<char> state(SMALL);
635  for (size_t j = 0; j < ITER; j++) {
636    state.NewIteration();
637
638    // Choose a random value to fill the string, except \0 (string terminator),
639    // or \1 (guarantees it's different from anything in ptr2).
640    memset(state.ptr1, (random() % 254) + 2, state.MAX_LEN);
641    // Choose a random size for our src buffer.
642    size_t ptr1_len = random() % state.MAX_LEN;
643    state.ptr1[ptr1_len] = '\0';
644    // Copy ptr1 into ptr, used to verify that ptr1 does not get modified.
645    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
646    // Init ptr2 to a set value.
647    memset(state.ptr2, '\1', state.MAX_LEN);
648
649    // Choose a random amount of data to copy.
650    size_t copy_len = random() % state.MAX_LEN;
651
652    // Set the second half of ptr to the expected pattern in ptr2.
653    memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
654    memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
655    size_t expected_end;
656    if (copy_len > ptr1_len) {
657      memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
658      expected_end = ptr1_len;
659    } else {
660      expected_end = copy_len;
661    }
662
663    ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
664
665    // Verify ptr1 was not modified.
666    ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
667    // Verify ptr2 contains the expected data.
668    ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN));
669  }
670}
671
672TEST(string, strncpy) {
673  StringTestState<char> state(SMALL);
674  for (size_t j = 0; j < ITER; j++) {
675    state.NewIteration();
676
677    // Choose a random value to fill the string, except \0 (string terminator),
678    // or \1 (guarantees it's different from anything in ptr2).
679    memset(state.ptr1, (random() % 254) + 2, state.MAX_LEN);
680    // Choose a random size for our src buffer.
681    size_t ptr1_len = random() % state.MAX_LEN;
682    state.ptr1[ptr1_len] = '\0';
683    // Copy ptr1 into ptr, used to verify that ptr1 does not get modified.
684    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
685    // Init ptr2 to a set value.
686    memset(state.ptr2, '\1', state.MAX_LEN);
687
688    // Choose a random amount of data to copy.
689    size_t copy_len = random() % state.MAX_LEN;
690
691    // Set the second half of ptr to the expected pattern in ptr2.
692    memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
693    memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
694    size_t expected_end;
695    if (copy_len > ptr1_len) {
696      memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
697      expected_end = ptr1_len;
698    } else {
699      expected_end = copy_len;
700    }
701
702    ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
703
704    // Verify ptr1 was not modified.
705    ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
706    // Verify ptr2 contains the expected data.
707    ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN));
708  }
709}
710
711TEST(string, strrchr) {
712  int seek_char = random() & 255;
713  StringTestState<char> state(SMALL);
714  for (size_t i = 1; i < state.n; i++) {
715    for (size_t j = 0; j < POS_ITER; j++) {
716      state.NewIteration();
717
718      if (~seek_char > 0) {
719        memset(state.ptr1, ~seek_char, state.len[i]);
720      } else {
721        memset(state.ptr1, '\1', state.len[i]);
722      }
723      state.ptr1[state.len[i] - 1] = '\0';
724
725      int pos = random() % state.MAX_LEN;
726      char* expected;
727      if (pos >= state.len[i] - 1) {
728        if (seek_char == 0) {
729          expected = state.ptr1 + state.len[i] - 1;
730        } else {
731          expected = NULL;
732        }
733      } else {
734        state.ptr1[pos] = seek_char;
735        expected = state.ptr1 + pos;
736      }
737
738      ASSERT_TRUE(strrchr(state.ptr1, seek_char) == expected);
739    }
740  }
741}
742
743TEST(string, memchr) {
744  int seek_char = random() & 255;
745  StringTestState<char> state(SMALL);
746  for (size_t i = 0; i < state.n; i++) {
747    for (size_t j = 0; j < POS_ITER; j++) {
748      state.NewIteration();
749
750      memset(state.ptr1, ~seek_char, state.len[i]);
751
752      int pos = random() % state.MAX_LEN;
753      char* expected;
754      if (pos >= state.len[i]) {
755        expected = NULL;
756      } else {
757        state.ptr1[pos] = seek_char;
758        expected = state.ptr1 + pos;
759      }
760
761      ASSERT_TRUE(memchr(state.ptr1, seek_char, state.len[i]) == expected);
762    }
763  }
764}
765
766TEST(string, memrchr) {
767  int seek_char = random() & 255;
768  StringTestState<char> state(SMALL);
769  for (size_t i = 0; i < state.n; i++) {
770    for (size_t j = 0; j < POS_ITER; j++) {
771      state.NewIteration();
772
773      memset(state.ptr1, ~seek_char, state.len[i]);
774
775      int pos = random() % state.MAX_LEN;
776      char* expected;
777      if (pos >= state.len[i]) {
778        expected = NULL;
779      } else {
780        state.ptr1[pos] = seek_char;
781        expected = state.ptr1 + pos;
782      }
783
784      ASSERT_TRUE(memrchr(state.ptr1, seek_char, state.len[i]) == expected);
785    }
786  }
787}
788
789TEST(string, memcmp) {
790  StringTestState<char> state(SMALL);
791  for (size_t i = 0; i < state.n; i++) {
792    for (size_t j = 0; j < POS_ITER; j++) {
793      state.NewIteration();
794
795      int c1 = random() & 0xff;
796      int c2 = random() & 0xff;
797      memset(state.ptr1, c1, state.MAX_LEN);
798      memset(state.ptr2, c1, state.MAX_LEN);
799
800      int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
801      state.ptr2[pos] = c2;
802
803      int expected = (static_cast<int>(c1) - static_cast<int>(c2));
804      int actual = memcmp(state.ptr1, state.ptr2, state.MAX_LEN);
805
806      ASSERT_EQ(signum(expected), signum(actual));
807    }
808  }
809}
810
811TEST(string, wmemcmp) {
812  StringTestState<wchar_t> state(SMALL);
813
814  for (size_t i = 0; i < state.n; i++) {
815    for (size_t j = 0; j < POS_ITER; j++) {
816      state.NewIteration();
817
818      long long mask = ((long long) 1 << 8 * sizeof(wchar_t)) - 1;
819      int c1 = rand() & mask;
820      int c2 = rand() & mask;
821      wmemset(state.ptr1, c1, state.MAX_LEN);
822      wmemset(state.ptr2, c1, state.MAX_LEN);
823
824      int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
825      state.ptr2[pos] = c2;
826
827      int expected = (static_cast<int>(c1) - static_cast<int>(c2));
828      int actual = wmemcmp(state.ptr1, state.ptr2, (size_t) state.MAX_LEN);
829
830      ASSERT_EQ(signum(expected), signum(actual));
831    }
832  }
833}
834
835TEST(string, memcpy) {
836  StringTestState<char> state(LARGE);
837  int rand = random() & 255;
838  for (size_t i = 0; i < state.n - 1; i++) {
839    for (size_t j = 0; j < POS_ITER; j++) {
840      state.NewIteration();
841
842      size_t pos = random() % (state.MAX_LEN - state.len[i]);
843
844      memset(state.ptr1, rand, state.len[i]);
845      memset(state.ptr1 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
846
847      memset(state.ptr2, rand, state.len[i]);
848      memset(state.ptr2 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
849      memset(state.ptr2 + pos, '\0', state.len[i]);
850
851      ASSERT_FALSE(memcpy(state.ptr2 + pos, state.ptr1 + pos, state.len[i]) != state.ptr2 + pos);
852      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
853    }
854  }
855}
856
857TEST(string, memset) {
858  StringTestState<char> state(LARGE);
859  char ch = random () & 255;
860  for (size_t i = 0; i < state.n - 1; i++) {
861    for (size_t j = 0; j < POS_ITER; j++) {
862      state.NewIteration();
863
864      memset(state.ptr1, ~ch, state.MAX_LEN);
865      memcpy(state.ptr2, state.ptr1, state.MAX_LEN);
866
867      size_t pos = random () % (state.MAX_LEN - state.len[i]);
868      for (size_t k = pos; k < pos + state.len[i]; k++) {
869        state.ptr1[k] = ch;
870      }
871
872      ASSERT_TRUE(memset(state.ptr2 + pos, ch, state.len[i]) == state.ptr2 + pos);
873
874      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
875    }
876  }
877}
878
879TEST(string, memmove) {
880  StringTestState<char> state(LARGE);
881  for (size_t i = 0; i < state.n - 1; i++) {
882    for (size_t j = 0; j < POS_ITER; j++) {
883      state.NewIteration();
884
885      memset(state.ptr1, random() & 255, 2 * state.MAX_LEN);
886
887      size_t pos = random() % (state.MAX_LEN - state.len[i]);
888
889      memset(state.ptr1, random() & 255, state.len[i]);
890      memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
891      memcpy(state.ptr, state.ptr1, state.len[i]);
892      memcpy(state.ptr1 + pos, state.ptr, state.len[i]);
893
894      ASSERT_TRUE(memmove(state.ptr2 + pos, state.ptr2, state.len[i]) == state.ptr2 + pos);
895      ASSERT_EQ(0, memcmp(state.ptr2, state.ptr1, 2 * state.MAX_LEN));
896    }
897  }
898}
899
900TEST(string, memmove_cache_size) {
901  size_t len = 600000;
902  int max_alignment = 31;
903  int alignments[] = {0, 5, 11, 29, 30};
904  char* ptr = reinterpret_cast<char*>(malloc(sizeof(char) * len));
905  char* ptr1 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len));
906  char* glob_ptr2 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len + max_alignment));
907  size_t pos = 64;
908
909  ASSERT_TRUE(ptr != NULL);
910  ASSERT_TRUE(ptr1 != NULL);
911  ASSERT_TRUE(glob_ptr2 != NULL);
912
913  for (int i = 0; i < 5; i++) {
914    char* ptr2 = glob_ptr2 + alignments[i];
915    memset(ptr1, random() & 255, 2 * len);
916    memset(ptr1, random() & 255, len);
917    memcpy(ptr2, ptr1, 2 * len);
918    memcpy(ptr, ptr1, len);
919    memcpy(ptr1 + pos, ptr, len);
920
921    ASSERT_TRUE(memmove(ptr2 + pos, ptr, len) == ptr2 + pos);
922    ASSERT_EQ(0, memcmp(ptr2, ptr1, 2 * len));
923  }
924  free(ptr);
925  free(ptr1);
926  free(glob_ptr2);
927}
928
929static void verify_memmove(char* src_copy, char* dst, char* src, size_t size) {
930  memset(dst, 0, size);
931  memcpy(src, src_copy, size);
932  ASSERT_EQ(dst, memmove(dst, src, size));
933  ASSERT_EQ(0, memcmp(dst, src_copy, size));
934}
935
936#define MEMMOVE_DATA_SIZE (1024*1024*3)
937
938TEST(string, memmove_check) {
939  char* buffer = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE));
940  ASSERT_TRUE(buffer != NULL);
941
942  char* src_data = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE));
943  ASSERT_TRUE(src_data != NULL);
944  // Initialize to a known pattern to copy into src for each test and
945  // to compare dst against.
946  for (size_t i = 0; i < MEMMOVE_DATA_SIZE; i++) {
947    src_data[i] = (i + 1) % 255;
948  }
949
950  // Check all different dst offsets between 0 and 127 inclusive.
951  char* src = buffer;
952  for (size_t i = 0; i < 127; i++) {
953    char* dst = buffer + 256 + i;
954    // Small copy.
955    verify_memmove(src_data, dst, src, 1024);
956
957    // Medium copy.
958    verify_memmove(src_data, dst, src, 64 * 1024);
959
960    // Medium copy.
961    verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024);
962  }
963
964  // Check all leftover size offsets between 1 and 127 inclusive.
965  char* dst = buffer + 256;
966  src = buffer;
967  for (size_t size = 1; size < 127; size++) {
968    // Small copy.
969    verify_memmove(src_data, dst, src, 1024);
970
971    // Medium copy.
972    verify_memmove(src_data, dst, src, 64 * 1024);
973
974    // Large copy.
975    verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024);
976  }
977}
978
979TEST(string, bcopy) {
980  StringTestState<char> state(LARGE);
981  for (size_t i = 0; i < state.n; i++) {
982    for (size_t j = 0; j < POS_ITER; j++) {
983      state.NewIteration();
984
985      memset(state.ptr1, random() & 255, state.MAX_LEN);
986      memset(state.ptr1 + state.MAX_LEN, random() & 255, state.MAX_LEN);
987      memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
988
989      size_t start = random() % (2 * state.MAX_LEN - state.len[i]);
990      memcpy(state.ptr2 + start, state.ptr1, state.len[i]);
991
992      bcopy(state.ptr1, state.ptr1 + start, state.len[i]);
993      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, 2 * state.MAX_LEN));
994    }
995  }
996}
997
998TEST(string, bzero) {
999  StringTestState<char> state(LARGE);
1000  for (size_t j = 0; j < ITER; j++) {
1001    state.NewIteration();
1002
1003    memset(state.ptr1, random() & 255, state.MAX_LEN);
1004
1005    size_t start = random() % state.MAX_LEN;
1006    size_t end = start + random() % (state.MAX_LEN - start);
1007
1008    memcpy(state.ptr2, state.ptr1, start);
1009    memset(state.ptr2 + start, '\0', end - start);
1010    memcpy(state.ptr2 + end, state.ptr1 + end, state.MAX_LEN - end);
1011
1012    bzero(state.ptr1 + start, end - start);
1013
1014    ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
1015  }
1016}
1017
1018static void DoMemcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1019  memset(src, (len % 255) + 1, len);
1020  memset(dst, 0, len);
1021
1022  ASSERT_EQ(dst, memcpy(dst, src, len));
1023  ASSERT_TRUE(memcmp(src, dst, len) == 0);
1024}
1025
1026TEST(string, memcpy_align) {
1027  RunSrcDstBufferAlignTest(LARGE, DoMemcpyTest);
1028}
1029
1030TEST(string, memcpy_overread) {
1031  RunSrcDstBufferOverreadTest(DoMemcpyTest);
1032}
1033
1034static void DoMemmoveTest(uint8_t* src, uint8_t* dst, size_t len) {
1035  memset(src, (len % 255) + 1, len);
1036  memset(dst, 0, len);
1037
1038  ASSERT_EQ(dst, memmove(dst, src, len));
1039  ASSERT_TRUE(memcmp(src, dst, len) == 0);
1040}
1041
1042TEST(string, memmove_align) {
1043  RunSrcDstBufferAlignTest(LARGE, DoMemmoveTest);
1044}
1045
1046TEST(string, memmove_overread) {
1047  RunSrcDstBufferOverreadTest(DoMemmoveTest);
1048}
1049
1050static void DoMemsetTest(uint8_t* buf, size_t len) {
1051  for (size_t i = 0; i < len; i++) {
1052    buf[i] = 0;
1053  }
1054  int value = (len % 255) + 1;
1055  ASSERT_EQ(buf, memset(buf, value, len));
1056  for (size_t i = 0; i < len; i++) {
1057    ASSERT_EQ(value, buf[i]);
1058  }
1059}
1060
1061TEST(string, memset_align) {
1062  RunSingleBufferAlignTest(LARGE, DoMemsetTest);
1063}
1064
1065static void DoStrlenTest(uint8_t* buf, size_t len) {
1066  if (len >= 1) {
1067    memset(buf, (32 + (len % 96)), len - 1);
1068    buf[len-1] = '\0';
1069    ASSERT_EQ(len-1, strlen(reinterpret_cast<char*>(buf)));
1070  }
1071}
1072
1073TEST(string, strlen_align) {
1074  RunSingleBufferAlignTest(LARGE, DoStrlenTest);
1075}
1076
1077TEST(string, strlen_overread) {
1078  RunSingleBufferOverreadTest(DoStrlenTest);
1079}
1080
1081static void DoStrcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1082  if (len >= 1) {
1083    memset(src, (32 + (len % 96)), len - 1);
1084    src[len-1] = '\0';
1085    memset(dst, 0, len);
1086    ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcpy(reinterpret_cast<char*>(dst),
1087                                                     reinterpret_cast<char*>(src))));
1088    ASSERT_TRUE(memcmp(src, dst, len) == 0);
1089  }
1090}
1091
1092TEST(string, strcpy_align) {
1093  RunSrcDstBufferAlignTest(LARGE, DoStrcpyTest);
1094}
1095
1096TEST(string, strcpy_overread) {
1097  RunSrcDstBufferOverreadTest(DoStrcpyTest);
1098}
1099
1100static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1101  if (len >= 1) {
1102    memset(src, (32 + (len % 96)), len - 1);
1103    src[len-1] = '\0';
1104    memset(dst, 0, len);
1105    ASSERT_EQ(dst+len-1, reinterpret_cast<uint8_t*>(stpcpy(reinterpret_cast<char*>(dst),
1106                                                           reinterpret_cast<char*>(src))));
1107    ASSERT_TRUE(memcmp(src, dst, len) == 0);
1108  }
1109}
1110
1111TEST(string, stpcpy_align) {
1112  RunSrcDstBufferAlignTest(LARGE, DoStpcpyTest);
1113}
1114
1115TEST(string, stpcpy_overread) {
1116  RunSrcDstBufferOverreadTest(DoStpcpyTest);
1117}
1118
1119// Use our own incrementer to cut down on the total number of calls.
1120static size_t LargeSetIncrement(size_t len) {
1121  if (len >= 4096) {
1122    return 4096;
1123  } else if (len >= 1024) {
1124    return 1024;
1125  } else if (len >= 256) {
1126    return 256;
1127  }
1128  return 1;
1129}
1130
1131#define STRCAT_DST_LEN  128
1132
1133static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
1134  if (len >= 1) {
1135    int value = 32 + (len % 96);
1136    memset(src, value, len - 1);
1137    src[len-1] = '\0';
1138
1139    if (len >= STRCAT_DST_LEN) {
1140      // Create a small buffer for doing quick compares in each loop.
1141      uint8_t cmp_buf[STRCAT_DST_LEN];
1142      // Make sure dst string contains a different value then the src string.
1143      int value2 = 32 + (value + 2) % 96;
1144      memset(cmp_buf, value2, sizeof(cmp_buf));
1145
1146      for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
1147        memset(dst, value2, i-1);
1148        memset(dst+i-1, 0, len-i);
1149        src[len-i] = '\0';
1150        ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
1151                                                         reinterpret_cast<char*>(src))));
1152        ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
1153        ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
1154      }
1155    } else {
1156      dst[0] = '\0';
1157      ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
1158                                                       reinterpret_cast<char*>(src))));
1159      ASSERT_TRUE(memcmp(src, dst, len) == 0);
1160    }
1161  }
1162}
1163
1164TEST(string, strcat_align) {
1165  RunSrcDstBufferAlignTest(MEDIUM, DoStrcatTest, LargeSetIncrement);
1166}
1167
1168TEST(string, strcat_overread) {
1169  RunSrcDstBufferOverreadTest(DoStrcatTest);
1170}
1171
1172static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
1173  if (len >= 1) {
1174    memset(buf1, (32 + (len % 96)), len - 1);
1175    buf1[len-1] = '\0';
1176    memset(buf2, (32 + (len % 96)), len - 1);
1177    buf2[len-1] = '\0';
1178    ASSERT_EQ(0, strcmp(reinterpret_cast<char*>(buf1),
1179                        reinterpret_cast<char*>(buf2)));
1180  }
1181}
1182
1183static void DoStrcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) {
1184  // Do string length differences.
1185  int c = (32 + (len1 % 96));
1186  memset(buf1, c, len1 - 1);
1187  buf1[len1-1] = '\0';
1188  memset(buf2, c, len2 - 1);
1189  buf2[len2-1] = '\0';
1190  ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1191                      reinterpret_cast<char*>(buf2)));
1192
1193  // Do single character differences.
1194  size_t len;
1195  if (len1 > len2) {
1196    len = len2;
1197  } else {
1198    len = len1;
1199  }
1200  // Need at least a two character buffer to do this test.
1201  if (len > 1) {
1202    buf1[len-1] = '\0';
1203    buf2[len-1] = '\0';
1204    int diff_c = (c + 1) % 96;
1205
1206    buf1[len-2] = diff_c;
1207    ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1208                        reinterpret_cast<char*>(buf2)));
1209
1210    buf1[len-2] = c;
1211    buf2[len-2] = diff_c;
1212    ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1213                        reinterpret_cast<char*>(buf2)));
1214  }
1215}
1216
1217TEST(string, strcmp_align) {
1218  RunCmpBufferAlignTest(MEDIUM, DoStrcmpTest, DoStrcmpFailTest, LargeSetIncrement);
1219}
1220
1221TEST(string, strcmp_overread) {
1222  RunCmpBufferOverreadTest(DoStrcmpTest, DoStrcmpFailTest);
1223}
1224
1225static void DoMemcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
1226  memset(buf1, len+1, len);
1227  memset(buf2, len+1, len);
1228  ASSERT_EQ(0, memcmp(buf1, buf2, len));
1229}
1230
1231static void DoMemcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) {
1232  size_t len;
1233  if (len1 > len2) {
1234    len = len2;
1235  } else {
1236    len = len1;
1237  }
1238
1239  memset(buf1, len2+1, len);
1240  buf1[len-1] = len2;
1241  memset(buf2, len2+1, len);
1242  ASSERT_NE(0, memcmp(buf1, buf2, len));
1243
1244  buf1[len-1] = len2+1;
1245  buf2[len-1] = len2;
1246  ASSERT_NE(0, memcmp(buf1, buf2, len));
1247}
1248
1249TEST(string, memcmp_align) {
1250  RunCmpBufferAlignTest(MEDIUM, DoMemcmpTest, DoMemcmpFailTest, LargeSetIncrement);
1251}
1252
1253TEST(string, memcmp_overread) {
1254  RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest);
1255}
1256
1257static void DoStrchrTest(uint8_t* buf, size_t len) {
1258  if (len >= 1) {
1259    char value = 32 + (len % 96);
1260    char search_value = 33 + (len % 96);
1261    memset(buf, value, len - 1);
1262    buf[len-1] = '\0';
1263    ASSERT_EQ(NULL, strchr(reinterpret_cast<char*>(buf), search_value));
1264    ASSERT_EQ(reinterpret_cast<char*>(&buf[len-1]), strchr(reinterpret_cast<char*>(buf), '\0'));
1265    if (len >= 2) {
1266      buf[0] = search_value;
1267      ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf), search_value));
1268      buf[0] = value;
1269      buf[len-2] = search_value;
1270      ASSERT_EQ(reinterpret_cast<char*>(&buf[len-2]), strchr(reinterpret_cast<char*>(buf), search_value));
1271    }
1272  }
1273}
1274
1275TEST(string, strchr_align) {
1276  RunSingleBufferAlignTest(MEDIUM, DoStrchrTest);
1277}
1278
1279TEST(string, strchr_overread) {
1280  RunSingleBufferOverreadTest(DoStrchrTest);
1281}
1282