string_test.cpp revision 1aae9bd170883805f2e7975cd3dbd2502b083cc1
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
212TEST(string, strchr) {
213  int seek_char = random() & 255;
214
215  StringTestState state(SMALL);
216  for (size_t i = 1; i < state.n; i++) {
217    for (size_t j = 0; j < POS_ITER; j++) {
218      state.NewIteration();
219
220      if (~seek_char > 0) {
221        memset(state.ptr1, ~seek_char, state.len[i]);
222      } else {
223        memset(state.ptr1, '\1', state.len[i]);
224      }
225      state.ptr1[state.len[i] - 1] = '\0';
226
227      int pos = random() % state.MAX_LEN;
228      char* expected;
229      if (pos >= state.len[i] - 1) {
230        if (seek_char == 0) {
231          expected = state.ptr1 + state.len[i] - 1;
232        } else {
233          expected = NULL;
234        }
235      } else {
236        state.ptr1[pos] = seek_char;
237        expected = state.ptr1 + pos;
238      }
239
240      ASSERT_TRUE(strchr(state.ptr1, seek_char) == expected);
241    }
242  }
243}
244
245TEST(string, strcmp) {
246  StringTestState state(SMALL);
247  for (size_t i = 1; i < state.n; i++) {
248    for (size_t j = 0; j < POS_ITER; j++) {
249      state.NewIteration();
250
251      memset(state.ptr1, 'v', state.MAX_LEN);
252      memset(state.ptr2, 'n', state.MAX_LEN);
253      state.ptr1[state.len[i] - 1] = '\0';
254      state.ptr2[state.len[i] - 1] = '\0';
255
256      int pos = 1 + (random() % (state.MAX_LEN - 1));
257      int actual;
258      int expected;
259      if (pos >= state.len[i] - 1) {
260        memcpy(state.ptr1, state.ptr2, state.len[i]);
261        expected = 0;
262        actual = strcmp(state.ptr1, state.ptr2);
263      } else {
264        memcpy(state.ptr1, state.ptr2, pos);
265        if (state.ptr1[pos] > state.ptr2[pos]) {
266          expected = 1;
267        } else if (state.ptr1[pos] == state.ptr2[pos]) {
268          state.ptr1[pos + 1] = '\0';
269          state.ptr2[pos + 1] = '\0';
270          expected = 0;
271        } else {
272          expected = -1;
273        }
274        actual = strcmp(state.ptr1, state.ptr2);
275      }
276
277      ASSERT_EQ(expected, signum(actual));
278    }
279  }
280}
281
282TEST(string, strcpy) {
283  StringTestState state(SMALL);
284  for (size_t j = 0; j < POS_ITER; j++) {
285    state.NewIteration();
286
287    size_t pos = random() % state.MAX_LEN;
288
289    memset(state.ptr1, '\2', pos);
290    state.ptr1[pos] = '\0';
291    state.ptr1[state.MAX_LEN - 1] = '\0';
292
293    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
294
295    memset(state.ptr2, '\1', state.MAX_LEN);
296    state.ptr2[state.MAX_LEN - 1] = '\0';
297
298    memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
299    memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
300    state.ptr[2 * state.MAX_LEN - 1] = '\0';
301
302    ASSERT_TRUE(strcpy(state.ptr2, state.ptr1) == state.ptr2);
303    ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
304                 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
305  }
306}
307
308
309#if __BIONIC__
310TEST(string, strlcat) {
311  StringTestState state(SMALL);
312  for (size_t i = 0; i < state.n; i++) {
313    for (size_t j = 0; j < POS_ITER; j++) {
314      state.NewIteration();
315
316      memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]);
317      state.ptr2[state.MAX_LEN - 1] = '\0';
318      memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
319
320      int pos = random() % state.MAX_LEN;
321      memset(state.ptr1, '\3', pos);
322      state.ptr1[pos] = '\0';
323      if (pos < state.len[i]) {
324        memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, pos + 1);
325      } else {
326        memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, state.len[i]);
327        state.ptr[state.MAX_LEN + state.len[i] - 1] = '\0';
328      }
329
330      strlcat(state.ptr2, state.ptr1, state.MAX_LEN + state.len[i]);
331
332      ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
333    }
334  }
335}
336#endif
337
338#if __BIONIC__
339TEST(string, strlcpy) {
340  StringTestState state(SMALL);
341  for (size_t j = 0; j < POS_ITER; j++) {
342    state.NewIteration();
343
344    int rand = random() & 255;
345    if (rand < 1) {
346      rand = 1;
347    }
348    memset(state.ptr1, rand, state.MAX_LEN);
349
350    size_t pos = random() % state.MAX_LEN;
351    if (pos < state.MAX_LEN) {
352      state.ptr1[pos] = '\0';
353    }
354    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
355
356    memset(state.ptr2, random() & 255, state.MAX_LEN);
357    memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN);
358
359    if (pos > state.MAX_LEN - 1) {
360      memcpy(state.ptr + state.MAX_LEN, state.ptr1, state.MAX_LEN);
361      state.ptr[2 * state.MAX_LEN - 1] = '\0';
362    } else {
363      memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
364    }
365
366    ASSERT_EQ(strlcpy(state.ptr2, state.ptr1, state.MAX_LEN), strlen(state.ptr1));
367    ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
368                 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
369  }
370}
371#endif
372
373TEST(string, strncat) {
374  StringTestState state(SMALL);
375  for (size_t i = 1; i < state.n; i++) {
376    for (size_t j = 0; j < POS_ITER; j++) {
377      state.NewIteration();
378
379      memset(state.ptr2, '\2', state.MAX_LEN);
380      state.ptr2[state.MAX_LEN - 1] = '\0';
381      memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
382
383      memset(state.ptr1, random() & 255, state.len[i]);
384      state.ptr1[random() % state.len[i]] = '\0';
385      state.ptr1[state.len[i] - 1] = '\0';
386
387      size_t pos = strlen(state.ptr1);
388
389      size_t actual = random() % state.len[i];
390      strncpy(state.ptr + state.MAX_LEN - 1, state.ptr1, std::min(actual, pos));
391      state.ptr[state.MAX_LEN + std::min(actual, pos) - 1] = '\0';
392
393      ASSERT_TRUE(strncat(state.ptr2, state.ptr1, actual) == state.ptr2);
394      ASSERT_EQ(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN), 0);
395    }
396  }
397}
398
399TEST(string, strncmp) {
400  StringTestState state(SMALL);
401  for (size_t i = 1; i < state.n; i++) {
402    for (size_t j = 0; j < POS_ITER; j++) {
403      state.NewIteration();
404
405      memset(state.ptr1, 'v', state.MAX_LEN);
406      memset(state.ptr2, 'n', state.MAX_LEN);
407      state.ptr1[state.len[i] - 1] = '\0';
408      state.ptr2[state.len[i] - 1] = '\0';
409
410      int pos = 1 + (random() % (state.MAX_LEN - 1));
411      int actual;
412      int expected;
413      if (pos >= state.len[i] - 1) {
414        memcpy(state.ptr1, state.ptr2, state.len[i]);
415        expected = 0;
416        actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
417      } else {
418        memcpy(state.ptr1, state.ptr2, pos);
419        if (state.ptr1[pos] > state.ptr2[pos]) {
420          expected = 1;
421        } else if (state.ptr1[pos] == state.ptr2[pos]) {
422          state.ptr1[pos + 1] = '\0';
423          state.ptr2[pos + 1] = '\0';
424          expected = 0;
425        } else {
426          expected = -1;
427        }
428        actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
429      }
430
431      ASSERT_EQ(expected, signum(actual));
432    }
433  }
434}
435
436TEST(string, strncpy) {
437  StringTestState state(SMALL);
438  for (size_t j = 0; j < ITER; j++) {
439    state.NewIteration();
440
441    memset(state.ptr1, random() & 255, state.MAX_LEN);
442    state.ptr1[random () % state.MAX_LEN] = '\0';
443    memcpy(state.ptr, state.ptr1, state.MAX_LEN);
444
445    memset(state.ptr2, '\1', state.MAX_LEN);
446
447    size_t pos;
448    if (memchr(state.ptr1, 0, state.MAX_LEN)) {
449      pos = strlen(state.ptr1);
450    } else {
451      pos = state.MAX_LEN - 1;
452    }
453
454    memset(state.ptr + state.MAX_LEN, '\0', state.MAX_LEN);
455    memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
456
457    ASSERT_TRUE(strncpy(state.ptr2, state.ptr1, state.MAX_LEN) == state.ptr2);
458    ASSERT_FALSE(memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0 ||
459                 memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0);
460  }
461}
462
463TEST(string, strrchr) {
464  int seek_char = random() & 255;
465  StringTestState state(SMALL);
466  for (size_t i = 1; i < state.n; i++) {
467    for (size_t j = 0; j < POS_ITER; j++) {
468      state.NewIteration();
469
470      if (~seek_char > 0) {
471        memset(state.ptr1, ~seek_char, state.len[i]);
472      } else {
473        memset(state.ptr1, '\1', state.len[i]);
474      }
475      state.ptr1[state.len[i] - 1] = '\0';
476
477      int pos = random() % state.MAX_LEN;
478      char* expected;
479      if (pos >= state.len[i] - 1) {
480        if (seek_char == 0) {
481          expected = state.ptr1 + state.len[i] - 1;
482        } else {
483          expected = NULL;
484        }
485      } else {
486        state.ptr1[pos] = seek_char;
487        expected = state.ptr1 + pos;
488      }
489
490      ASSERT_TRUE(strrchr(state.ptr1, seek_char) == expected);
491    }
492  }
493}
494
495TEST(string, memchr) {
496  int seek_char = random() & 255;
497  StringTestState state(SMALL);
498  for (size_t i = 0; i < state.n; i++) {
499    for (size_t j = 0; j < POS_ITER; j++) {
500      state.NewIteration();
501
502      memset(state.ptr1, ~seek_char, state.len[i]);
503
504      int pos = random() % state.MAX_LEN;
505      char* expected;
506      if (pos >= state.len[i]) {
507        expected = NULL;
508      } else {
509        state.ptr1[pos] = seek_char;
510        expected = state.ptr1 + pos;
511      }
512
513      ASSERT_TRUE(memchr(state.ptr1, seek_char, state.len[i]) == expected);
514    }
515  }
516}
517
518TEST(string, memrchr) {
519  int seek_char = random() & 255;
520  StringTestState state(SMALL);
521  for (size_t i = 0; i < state.n; i++) {
522    for (size_t j = 0; j < POS_ITER; j++) {
523      state.NewIteration();
524
525      memset(state.ptr1, ~seek_char, state.len[i]);
526
527      int pos = random() % state.MAX_LEN;
528      char* expected;
529      if (pos >= state.len[i]) {
530        expected = NULL;
531      } else {
532        state.ptr1[pos] = seek_char;
533        expected = state.ptr1 + pos;
534      }
535
536      ASSERT_TRUE(memrchr(state.ptr1, seek_char, state.len[i]) == expected);
537    }
538  }
539}
540
541TEST(string, memcmp) {
542  StringTestState state(SMALL);
543  for (size_t i = 0; i < state.n; i++) {
544    for (size_t j = 0; j < POS_ITER; j++) {
545      state.NewIteration();
546
547      int c1 = random() & 0xff;
548      int c2 = random() & 0xff;
549      memset(state.ptr1, c1, state.MAX_LEN);
550      memset(state.ptr2, c1, state.MAX_LEN);
551
552      int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
553      state.ptr2[pos] = c2;
554
555      int expected = (static_cast<int>(c1) - static_cast<int>(c2));
556      int actual = memcmp(state.ptr1, state.ptr2, state.MAX_LEN);
557
558      ASSERT_EQ(signum(expected), signum(actual));
559    }
560  }
561}
562
563TEST(string, memcpy) {
564  StringTestState state(LARGE);
565  int rand = random() & 255;
566  for (size_t i = 0; i < state.n - 1; i++) {
567    for (size_t j = 0; j < POS_ITER; j++) {
568      state.NewIteration();
569
570      size_t pos = random() % (state.MAX_LEN - state.len[i]);
571
572      memset(state.ptr1, rand, state.len[i]);
573      memset(state.ptr1 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
574
575      memset(state.ptr2, rand, state.len[i]);
576      memset(state.ptr2 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
577      memset(state.ptr2 + pos, '\0', state.len[i]);
578
579      ASSERT_FALSE(memcpy(state.ptr2 + pos, state.ptr1 + pos, state.len[i]) != state.ptr2 + pos);
580      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
581    }
582  }
583}
584
585TEST(string, memset) {
586  StringTestState state(LARGE);
587  char ch = random () & 255;
588  for (size_t i = 0; i < state.n - 1; i++) {
589    for (size_t j = 0; j < POS_ITER; j++) {
590      state.NewIteration();
591
592      memset(state.ptr1, ~ch, state.MAX_LEN);
593      memcpy(state.ptr2, state.ptr1, state.MAX_LEN);
594
595      size_t pos = random () % (state.MAX_LEN - state.len[i]);
596      for (size_t k = pos; k < pos + state.len[i]; k++) {
597        state.ptr1[k] = ch;
598      }
599
600      ASSERT_TRUE(memset(state.ptr2 + pos, ch, state.len[i]) == state.ptr2 + pos);
601
602      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
603    }
604  }
605}
606
607TEST(string, memmove) {
608  StringTestState state(LARGE);
609  for (size_t i = 0; i < state.n - 1; i++) {
610    for (size_t j = 0; j < POS_ITER; j++) {
611      state.NewIteration();
612
613      memset(state.ptr1, random() & 255, 2 * state.MAX_LEN);
614
615      size_t pos = random() % (state.MAX_LEN - state.len[i]);
616
617      memset(state.ptr1, random() & 255, state.len[i]);
618      memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
619      memcpy(state.ptr, state.ptr1, state.len[i]);
620      memcpy(state.ptr1 + pos, state.ptr, state.len[i]);
621
622      ASSERT_TRUE(memmove(state.ptr2 + pos, state.ptr2, state.len[i]) == state.ptr2 + pos);
623      ASSERT_EQ(0, memcmp(state.ptr2, state.ptr1, 2 * state.MAX_LEN));
624    }
625  }
626}
627
628TEST(string, bcopy) {
629  StringTestState state(LARGE);
630  for (size_t i = 0; i < state.n; i++) {
631    for (size_t j = 0; j < POS_ITER; j++) {
632      state.NewIteration();
633
634      memset(state.ptr1, random() & 255, state.MAX_LEN);
635      memset(state.ptr1 + state.MAX_LEN, random() & 255, state.MAX_LEN);
636      memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
637
638      size_t start = random() % (2 * state.MAX_LEN - state.len[i]);
639      memcpy(state.ptr2 + start, state.ptr1, state.len[i]);
640
641      bcopy(state.ptr1, state.ptr1 + start, state.len[i]);
642      ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, 2 * state.MAX_LEN));
643    }
644  }
645}
646
647TEST(string, bzero) {
648  StringTestState state(LARGE);
649  for (size_t j = 0; j < ITER; j++) {
650    state.NewIteration();
651
652    memset(state.ptr1, random() & 255, state.MAX_LEN);
653
654    size_t start = random() % state.MAX_LEN;
655    size_t end = start + random() % (state.MAX_LEN - start);
656
657    memcpy(state.ptr2, state.ptr1, start);
658    memset(state.ptr2 + start, '\0', end - start);
659    memcpy(state.ptr2 + end, state.ptr1 + end, state.MAX_LEN - end);
660
661    bzero(state.ptr1 + start, end - start);
662
663    ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
664  }
665}
666