string_test.cpp revision 13476deec46d7ba101c1f76b8ddcaab9d0b96b84
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 <math.h>
21#include <string.h>
22
23#define KB 1024
24#define SMALL 1*KB
25#define LARGE 64*KB
26
27static int signum(int i) {
28  if (i < 0) {
29    return -1;
30  } else if (i > 0) {
31    return 1;
32  }
33  return 0;
34}
35
36TEST(string, strerror) {
37  // Valid.
38  ASSERT_STREQ("Success", strerror(0));
39  ASSERT_STREQ("Operation not permitted", strerror(1));
40
41  // Invalid.
42  ASSERT_STREQ("Unknown error -1", strerror(-1));
43  ASSERT_STREQ("Unknown error 1234", strerror(1234));
44}
45
46#if __BIONIC__ // glibc's strerror isn't thread safe, only its strsignal.
47
48static void* ConcurrentStrErrorFn(void*) {
49  bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
50  return reinterpret_cast<void*>(equal);
51}
52
53TEST(string, strerror_concurrent) {
54  const char* strerror1001 = strerror(1001);
55  ASSERT_STREQ("Unknown error 1001", strerror1001);
56
57  pthread_t t;
58  ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrErrorFn, NULL));
59  void* result;
60  ASSERT_EQ(0, pthread_join(t, &result));
61  ASSERT_TRUE(static_cast<bool>(result));
62
63  ASSERT_STREQ("Unknown error 1001", strerror1001);
64}
65
66#endif
67
68#if __BIONIC__ // glibc's strerror_r doesn't even have the same signature as the POSIX one.
69TEST(string, strerror_r) {
70  char buf[256];
71
72  // Valid.
73  ASSERT_EQ(0, strerror_r(0, buf, sizeof(buf)));
74  ASSERT_STREQ("Success", buf);
75  ASSERT_EQ(0, strerror_r(1, buf, sizeof(buf)));
76  ASSERT_STREQ("Operation not permitted", buf);
77
78  // Invalid.
79  ASSERT_EQ(0, strerror_r(-1, buf, sizeof(buf)));
80  ASSERT_STREQ("Unknown error -1", buf);
81  ASSERT_EQ(0, strerror_r(1234, buf, sizeof(buf)));
82  ASSERT_STREQ("Unknown error 1234", buf);
83
84  // Buffer too small.
85  ASSERT_EQ(-1, strerror_r(0, buf, 2));
86  ASSERT_EQ(ERANGE, errno);
87}
88#endif
89
90TEST(string, strsignal) {
91  // A regular signal.
92  ASSERT_STREQ("Hangup", strsignal(1));
93
94  // A real-time signal.
95#ifdef __GLIBC__ // glibc reserves real-time signals for internal use, and doesn't count those.
96  ASSERT_STREQ("Real-time signal 14", strsignal(48));
97#else
98  ASSERT_STREQ("Real-time signal 16", strsignal(48));
99#endif
100
101  // Errors.
102  ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
103  ASSERT_STREQ("Unknown signal 0", strsignal(0)); // Still too small.
104  ASSERT_STREQ("Unknown signal 1234", strsignal(1234)); // Too large.
105}
106
107static void* ConcurrentStrSignalFn(void*) {
108  bool equal = (strcmp("Unknown signal 2002", strsignal(2002)) == 0);
109  return reinterpret_cast<void*>(equal);
110}
111
112TEST(string, strsignal_concurrent) {
113  const char* strsignal1001 = strsignal(1001);
114  ASSERT_STREQ("Unknown signal 1001", strsignal1001);
115
116  pthread_t t;
117  ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrSignalFn, NULL));
118  void* result;
119  ASSERT_EQ(0, pthread_join(t, &result));
120  ASSERT_TRUE(static_cast<bool>(result));
121
122  ASSERT_STREQ("Unknown signal 1001", strsignal1001);
123}
124
125// TODO: where did these numbers come from?
126#define POS_ITER    10
127#define ITER        500
128
129// For every length we want to test, vary and change alignment
130// of allocated memory, fill it with some values, calculate
131// expected result and then run function and compare what we got.
132// These tests contributed by Intel Corporation.
133// TODO: make these tests more intention-revealing and less random.
134struct StringTestState {
135  StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN) {
136    int max_alignment = 64;
137
138    // TODO: fix the tests to not sometimes use twice their specified "MAX_LEN".
139    glob_ptr = reinterpret_cast<char*>(valloc(2 * MAX_LEN + max_alignment));
140    glob_ptr1 = reinterpret_cast<char*>(valloc(2 * MAX_LEN + max_alignment));
141    glob_ptr2 = reinterpret_cast<char*>(valloc(2 * MAX_LEN + max_alignment));
142
143    InitLenArray();
144
145    srandom(1234);
146  }
147
148  ~StringTestState() {
149    free(glob_ptr);
150    free(glob_ptr1);
151    free(glob_ptr2);
152  }
153
154  void NewIteration() {
155    int alignments[] = { 24, 32, 16, 48, 1, 2, 3, 0, 5, 11 };
156    int usable_alignments = 10;
157    int align1 = alignments[random() % (usable_alignments - 1)];
158    int align2 = alignments[random() % (usable_alignments - 1)];
159
160    ptr = glob_ptr + align1;
161    ptr1 = glob_ptr1 + align1;
162    ptr2 = glob_ptr2 + align2;
163  }
164
165  const size_t MAX_LEN;
166  char *ptr, *ptr1, *ptr2;
167  size_t n;
168  int len[ITER + 1];
169
170 private:
171  char *glob_ptr, *glob_ptr1, *glob_ptr2;
172
173  // Calculate input lengths and fill state.len with them.
174  // Test small lengths with more density than big ones. Manually push
175  // smallest (0) and biggest (MAX_LEN) lengths. Avoid repeats.
176  // Return number of lengths to test.
177  void InitLenArray() {
178    n = 0;
179    len[n++] = 0;
180    for (size_t i = 1; i < ITER; ++i) {
181      int l = (int) exp(log((double) MAX_LEN) * i / ITER);
182      if (l != len[n - 1]) {
183        len[n++] = l;
184      }
185    }
186    len[n++] = MAX_LEN;
187  }
188};
189
190TEST(string, strcat) {
191  StringTestState state(SMALL);
192  for (size_t i = 1; i < state.n; i++) {
193    for (size_t j = 0; j < POS_ITER; j++) {
194      state.NewIteration();
195
196      memset(state.ptr2, '\2', state.MAX_LEN);
197      state.ptr2[state.MAX_LEN - 1] = '\0';
198      memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
199
200      memset(state.ptr1, random() & 255, state.len[i]);
201      state.ptr1[random() % state.len[i]] = '\0';
202      state.ptr1[state.len[i] - 1] = '\0';
203
204      strcpy(state.ptr + state.MAX_LEN - 1, state.ptr1);
205
206      EXPECT_TRUE(strcat(state.ptr2, state.ptr1) == state.ptr2);
207      EXPECT_TRUE(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN) == 0);
208    }
209  }
210}
211
212// one byte target with "\0" source
213TEST(string, strcpy2) {
214  char buf[1];
215  char* orig = strdup("");
216  strcpy(buf, orig);
217  ASSERT_EQ('\0', buf[0]);
218  free(orig);
219}
220
221// multibyte target where we under fill target
222TEST(string, strcpy3) {
223  char buf[10];
224  char* orig = strdup("12345");
225  memset(buf, 'A', sizeof(buf));
226  strcpy(buf, orig);
227  ASSERT_EQ('1',  buf[0]);
228  ASSERT_EQ('2',  buf[1]);
229  ASSERT_EQ('3',  buf[2]);
230  ASSERT_EQ('4',  buf[3]);
231  ASSERT_EQ('5',  buf[4]);
232  ASSERT_EQ('\0', buf[5]);
233  ASSERT_EQ('A',  buf[6]);
234  ASSERT_EQ('A',  buf[7]);
235  ASSERT_EQ('A',  buf[8]);
236  ASSERT_EQ('A',  buf[9]);
237  free(orig);
238}
239
240// multibyte target where we fill target exactly
241TEST(string, strcpy4) {
242  char buf[10];
243  char* orig = strdup("123456789");
244  memset(buf, 'A', sizeof(buf));
245  strcpy(buf, orig);
246  ASSERT_EQ('1',  buf[0]);
247  ASSERT_EQ('2',  buf[1]);
248  ASSERT_EQ('3',  buf[2]);
249  ASSERT_EQ('4',  buf[3]);
250  ASSERT_EQ('5',  buf[4]);
251  ASSERT_EQ('6',  buf[5]);
252  ASSERT_EQ('7',  buf[6]);
253  ASSERT_EQ('8',  buf[7]);
254  ASSERT_EQ('9',  buf[8]);
255  ASSERT_EQ('\0', buf[9]);
256  free(orig);
257}
258
259TEST(string, strcat2) {
260  char buf[10];
261  memset(buf, 'A', sizeof(buf));
262  buf[0] = 'a';
263  buf[1] = '\0';
264  char* res = strcat(buf, "01234");
265  ASSERT_EQ(buf, res);
266  ASSERT_EQ('a',  buf[0]);
267  ASSERT_EQ('0',  buf[1]);
268  ASSERT_EQ('1',  buf[2]);
269  ASSERT_EQ('2',  buf[3]);
270  ASSERT_EQ('3',  buf[4]);
271  ASSERT_EQ('4',  buf[5]);
272  ASSERT_EQ('\0', buf[6]);
273  ASSERT_EQ('A',  buf[7]);
274  ASSERT_EQ('A',  buf[8]);
275  ASSERT_EQ('A',  buf[9]);
276}
277
278TEST(string, strcat3) {
279  char buf[10];
280  memset(buf, 'A', sizeof(buf));
281  buf[0] = 'a';
282  buf[1] = '\0';
283  char* res = strcat(buf, "01234567");
284  ASSERT_EQ(buf, res);
285  ASSERT_EQ('a',  buf[0]);
286  ASSERT_EQ('0',  buf[1]);
287  ASSERT_EQ('1',  buf[2]);
288  ASSERT_EQ('2',  buf[3]);
289  ASSERT_EQ('3',  buf[4]);
290  ASSERT_EQ('4',  buf[5]);
291  ASSERT_EQ('5', buf[6]);
292  ASSERT_EQ('6',  buf[7]);
293  ASSERT_EQ('7',  buf[8]);
294  ASSERT_EQ('\0',  buf[9]);
295}
296
297TEST(string, strncat2) {
298  char buf[10];
299  memset(buf, 'A', sizeof(buf));
300  buf[0] = 'a';
301  buf[1] = '\0';
302  char* res = strncat(buf, "01234", sizeof(buf) - strlen(buf) - 1);
303  ASSERT_EQ(buf, res);
304  ASSERT_EQ('a',  buf[0]);
305  ASSERT_EQ('0',  buf[1]);
306  ASSERT_EQ('1',  buf[2]);
307  ASSERT_EQ('2',  buf[3]);
308  ASSERT_EQ('3',  buf[4]);
309  ASSERT_EQ('4',  buf[5]);
310  ASSERT_EQ('\0', buf[6]);
311  ASSERT_EQ('A',  buf[7]);
312  ASSERT_EQ('A',  buf[8]);
313  ASSERT_EQ('A',  buf[9]);
314}
315
316TEST(string, strncat3) {
317  char buf[10];
318  memset(buf, 'A', sizeof(buf));
319  buf[0] = 'a';
320  buf[1] = '\0';
321  char* res = strncat(buf, "0123456789", 5);
322  ASSERT_EQ(buf, res);
323  ASSERT_EQ('a',  buf[0]);
324  ASSERT_EQ('0',  buf[1]);
325  ASSERT_EQ('1',  buf[2]);
326  ASSERT_EQ('2',  buf[3]);
327  ASSERT_EQ('3',  buf[4]);
328  ASSERT_EQ('4',  buf[5]);
329  ASSERT_EQ('\0', buf[6]);
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_EQ('a',  buf[0]);
343  ASSERT_EQ('0',  buf[1]);
344  ASSERT_EQ('1',  buf[2]);
345  ASSERT_EQ('2',  buf[3]);
346  ASSERT_EQ('3',  buf[4]);
347  ASSERT_EQ('4',  buf[5]);
348  ASSERT_EQ('5', buf[6]);
349  ASSERT_EQ('6',  buf[7]);
350  ASSERT_EQ('7',  buf[8]);
351  ASSERT_EQ('\0',  buf[9]);
352}
353
354TEST(string, strncat5) {
355  char buf[10];
356  memset(buf, 'A', sizeof(buf));
357  buf[0] = 'a';
358  buf[1] = '\0';
359  char* res = strncat(buf, "01234567", 9);
360  ASSERT_EQ(buf, res);
361  ASSERT_EQ('a',  buf[0]);
362  ASSERT_EQ('0',  buf[1]);
363  ASSERT_EQ('1',  buf[2]);
364  ASSERT_EQ('2',  buf[3]);
365  ASSERT_EQ('3',  buf[4]);
366  ASSERT_EQ('4',  buf[5]);
367  ASSERT_EQ('5', buf[6]);
368  ASSERT_EQ('6',  buf[7]);
369  ASSERT_EQ('7',  buf[8]);
370  ASSERT_EQ('\0',  buf[9]);
371}
372
373TEST(string, strchr_with_0) {
374  char buf[10];
375  const char* s = "01234";
376  memcpy(buf, s, strlen(s) + 1);
377  EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
378}
379
380TEST(string, strchr) {
381  int seek_char = random() & 255;
382
383  StringTestState 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 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, strcpy) {
451  StringTestState 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(strcpy(state.ptr2, state.ptr1) == state.ptr2);
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
476
477#if __BIONIC__
478TEST(string, strlcat) {
479  StringTestState state(SMALL);
480  for (size_t i = 0; i < state.n; i++) {
481    for (size_t j = 0; j < POS_ITER; j++) {
482      state.NewIteration();
483
484      memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]);
485      state.ptr2[state.MAX_LEN - 1] = '\0';
486      memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
487
488      int pos = random() % state.MAX_LEN;
489      memset(state.ptr1, '\3', pos);
490      state.ptr1[pos] = '\0';
491      if (pos < state.len[i]) {
492        memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, pos + 1);
493      } else {
494        memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, state.len[i]);
495        state.ptr[state.MAX_LEN + state.len[i] - 1] = '\0';
496      }
497
498      strlcat(state.ptr2, state.ptr1, state.MAX_LEN + state.len[i]);
499
500      ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
501    }
502  }
503}
504#endif
505
506#if __BIONIC__
507TEST(string, strlcpy) {
508  StringTestState state(SMALL);
509  for (size_t j = 0; j < POS_ITER; j++) {
510    state.NewIteration();
511
512    int rand = random() & 255;
513    if (rand < 1) {
514      rand = 1;
515    }
516    memset(state.ptr1, rand, state.MAX_LEN);
517
518    size_t pos = random() % state.MAX_LEN;
519    if (pos < state.MAX_LEN) {
520      state.ptr1[pos] = '\0';
521    }
522    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
523
524    memset(state.ptr2, random() & 255, state.MAX_LEN);
525    memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN);
526
527    if (pos > state.MAX_LEN - 1) {
528      memcpy(state.ptr + state.MAX_LEN, state.ptr1, state.MAX_LEN);
529      state.ptr[2 * state.MAX_LEN - 1] = '\0';
530    } else {
531      memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
532    }
533
534    ASSERT_EQ(strlcpy(state.ptr2, state.ptr1, state.MAX_LEN), strlen(state.ptr1));
535    ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
536                 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
537  }
538}
539#endif
540
541TEST(string, strncat) {
542  StringTestState state(SMALL);
543  for (size_t i = 1; i < state.n; i++) {
544    for (size_t j = 0; j < POS_ITER; j++) {
545      state.NewIteration();
546
547      memset(state.ptr2, '\2', state.MAX_LEN);
548      state.ptr2[state.MAX_LEN - 1] = '\0';
549      memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
550
551      memset(state.ptr1, random() & 255, state.len[i]);
552      state.ptr1[random() % state.len[i]] = '\0';
553      state.ptr1[state.len[i] - 1] = '\0';
554
555      size_t pos = strlen(state.ptr1);
556
557      size_t actual = random() % state.len[i];
558      strncpy(state.ptr + state.MAX_LEN - 1, state.ptr1, std::min(actual, pos));
559      state.ptr[state.MAX_LEN + std::min(actual, pos) - 1] = '\0';
560
561      ASSERT_TRUE(strncat(state.ptr2, state.ptr1, actual) == state.ptr2);
562      ASSERT_EQ(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN), 0);
563    }
564  }
565}
566
567TEST(string, strncmp) {
568  StringTestState state(SMALL);
569  for (size_t i = 1; i < state.n; i++) {
570    for (size_t j = 0; j < POS_ITER; j++) {
571      state.NewIteration();
572
573      memset(state.ptr1, 'v', state.MAX_LEN);
574      memset(state.ptr2, 'n', state.MAX_LEN);
575      state.ptr1[state.len[i] - 1] = '\0';
576      state.ptr2[state.len[i] - 1] = '\0';
577
578      int pos = 1 + (random() % (state.MAX_LEN - 1));
579      int actual;
580      int expected;
581      if (pos >= state.len[i] - 1) {
582        memcpy(state.ptr1, state.ptr2, state.len[i]);
583        expected = 0;
584        actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
585      } else {
586        memcpy(state.ptr1, state.ptr2, pos);
587        if (state.ptr1[pos] > state.ptr2[pos]) {
588          expected = 1;
589        } else if (state.ptr1[pos] == state.ptr2[pos]) {
590          state.ptr1[pos + 1] = '\0';
591          state.ptr2[pos + 1] = '\0';
592          expected = 0;
593        } else {
594          expected = -1;
595        }
596        actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
597      }
598
599      ASSERT_EQ(expected, signum(actual));
600    }
601  }
602}
603
604TEST(string, strncpy) {
605  StringTestState state(SMALL);
606  for (size_t j = 0; j < ITER; j++) {
607    state.NewIteration();
608
609    memset(state.ptr1, random() & 255, state.MAX_LEN);
610    state.ptr1[random () % state.MAX_LEN] = '\0';
611    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
612
613    memset(state.ptr2, '\1', state.MAX_LEN);
614
615    size_t pos;
616    if (memchr(state.ptr1, 0, state.MAX_LEN)) {
617      pos = strlen(state.ptr1);
618    } else {
619      pos = state.MAX_LEN - 1;
620    }
621
622    memset(state.ptr + state.MAX_LEN, '\0', state.MAX_LEN);
623    memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
624
625    ASSERT_TRUE(strncpy(state.ptr2, state.ptr1, state.MAX_LEN) == state.ptr2);
626    ASSERT_FALSE(memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0 ||
627                 memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0);
628  }
629}
630
631TEST(string, strrchr) {
632  int seek_char = random() & 255;
633  StringTestState state(SMALL);
634  for (size_t i = 1; i < state.n; i++) {
635    for (size_t j = 0; j < POS_ITER; j++) {
636      state.NewIteration();
637
638      if (~seek_char > 0) {
639        memset(state.ptr1, ~seek_char, state.len[i]);
640      } else {
641        memset(state.ptr1, '\1', state.len[i]);
642      }
643      state.ptr1[state.len[i] - 1] = '\0';
644
645      int pos = random() % state.MAX_LEN;
646      char* expected;
647      if (pos >= state.len[i] - 1) {
648        if (seek_char == 0) {
649          expected = state.ptr1 + state.len[i] - 1;
650        } else {
651          expected = NULL;
652        }
653      } else {
654        state.ptr1[pos] = seek_char;
655        expected = state.ptr1 + pos;
656      }
657
658      ASSERT_TRUE(strrchr(state.ptr1, seek_char) == expected);
659    }
660  }
661}
662
663TEST(string, memchr) {
664  int seek_char = random() & 255;
665  StringTestState state(SMALL);
666  for (size_t i = 0; i < state.n; i++) {
667    for (size_t j = 0; j < POS_ITER; j++) {
668      state.NewIteration();
669
670      memset(state.ptr1, ~seek_char, state.len[i]);
671
672      int pos = random() % state.MAX_LEN;
673      char* expected;
674      if (pos >= state.len[i]) {
675        expected = NULL;
676      } else {
677        state.ptr1[pos] = seek_char;
678        expected = state.ptr1 + pos;
679      }
680
681      ASSERT_TRUE(memchr(state.ptr1, seek_char, state.len[i]) == expected);
682    }
683  }
684}
685
686TEST(string, memrchr) {
687  int seek_char = random() & 255;
688  StringTestState state(SMALL);
689  for (size_t i = 0; i < state.n; i++) {
690    for (size_t j = 0; j < POS_ITER; j++) {
691      state.NewIteration();
692
693      memset(state.ptr1, ~seek_char, state.len[i]);
694
695      int pos = random() % state.MAX_LEN;
696      char* expected;
697      if (pos >= state.len[i]) {
698        expected = NULL;
699      } else {
700        state.ptr1[pos] = seek_char;
701        expected = state.ptr1 + pos;
702      }
703
704      ASSERT_TRUE(memrchr(state.ptr1, seek_char, state.len[i]) == expected);
705    }
706  }
707}
708
709TEST(string, memcmp) {
710  StringTestState state(SMALL);
711  for (size_t i = 0; i < state.n; i++) {
712    for (size_t j = 0; j < POS_ITER; j++) {
713      state.NewIteration();
714
715      int c1 = random() & 0xff;
716      int c2 = random() & 0xff;
717      memset(state.ptr1, c1, state.MAX_LEN);
718      memset(state.ptr2, c1, state.MAX_LEN);
719
720      int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
721      state.ptr2[pos] = c2;
722
723      int expected = (static_cast<int>(c1) - static_cast<int>(c2));
724      int actual = memcmp(state.ptr1, state.ptr2, state.MAX_LEN);
725
726      ASSERT_EQ(signum(expected), signum(actual));
727    }
728  }
729}
730
731TEST(string, memcpy) {
732  StringTestState state(LARGE);
733  int rand = random() & 255;
734  for (size_t i = 0; i < state.n - 1; i++) {
735    for (size_t j = 0; j < POS_ITER; j++) {
736      state.NewIteration();
737
738      size_t pos = random() % (state.MAX_LEN - state.len[i]);
739
740      memset(state.ptr1, rand, state.len[i]);
741      memset(state.ptr1 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
742
743      memset(state.ptr2, rand, state.len[i]);
744      memset(state.ptr2 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
745      memset(state.ptr2 + pos, '\0', state.len[i]);
746
747      ASSERT_FALSE(memcpy(state.ptr2 + pos, state.ptr1 + pos, state.len[i]) != state.ptr2 + pos);
748      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
749    }
750  }
751}
752
753TEST(string, memset) {
754  StringTestState state(LARGE);
755  char ch = random () & 255;
756  for (size_t i = 0; i < state.n - 1; i++) {
757    for (size_t j = 0; j < POS_ITER; j++) {
758      state.NewIteration();
759
760      memset(state.ptr1, ~ch, state.MAX_LEN);
761      memcpy(state.ptr2, state.ptr1, state.MAX_LEN);
762
763      size_t pos = random () % (state.MAX_LEN - state.len[i]);
764      for (size_t k = pos; k < pos + state.len[i]; k++) {
765        state.ptr1[k] = ch;
766      }
767
768      ASSERT_TRUE(memset(state.ptr2 + pos, ch, state.len[i]) == state.ptr2 + pos);
769
770      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
771    }
772  }
773}
774
775TEST(string, memmove) {
776  StringTestState state(LARGE);
777  for (size_t i = 0; i < state.n - 1; i++) {
778    for (size_t j = 0; j < POS_ITER; j++) {
779      state.NewIteration();
780
781      memset(state.ptr1, random() & 255, 2 * state.MAX_LEN);
782
783      size_t pos = random() % (state.MAX_LEN - state.len[i]);
784
785      memset(state.ptr1, random() & 255, state.len[i]);
786      memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
787      memcpy(state.ptr, state.ptr1, state.len[i]);
788      memcpy(state.ptr1 + pos, state.ptr, state.len[i]);
789
790      ASSERT_TRUE(memmove(state.ptr2 + pos, state.ptr2, state.len[i]) == state.ptr2 + pos);
791      ASSERT_EQ(0, memcmp(state.ptr2, state.ptr1, 2 * state.MAX_LEN));
792    }
793  }
794}
795
796TEST(string, bcopy) {
797  StringTestState state(LARGE);
798  for (size_t i = 0; i < state.n; i++) {
799    for (size_t j = 0; j < POS_ITER; j++) {
800      state.NewIteration();
801
802      memset(state.ptr1, random() & 255, state.MAX_LEN);
803      memset(state.ptr1 + state.MAX_LEN, random() & 255, state.MAX_LEN);
804      memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
805
806      size_t start = random() % (2 * state.MAX_LEN - state.len[i]);
807      memcpy(state.ptr2 + start, state.ptr1, state.len[i]);
808
809      bcopy(state.ptr1, state.ptr1 + start, state.len[i]);
810      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, 2 * state.MAX_LEN));
811    }
812  }
813}
814
815TEST(string, bzero) {
816  StringTestState state(LARGE);
817  for (size_t j = 0; j < ITER; j++) {
818    state.NewIteration();
819
820    memset(state.ptr1, random() & 255, state.MAX_LEN);
821
822    size_t start = random() % state.MAX_LEN;
823    size_t end = start + random() % (state.MAX_LEN - start);
824
825    memcpy(state.ptr2, state.ptr1, start);
826    memset(state.ptr2 + start, '\0', end - start);
827    memcpy(state.ptr2 + end, state.ptr1 + end, state.MAX_LEN - end);
828
829    bzero(state.ptr1 + start, end - start);
830
831    ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
832  }
833}
834