test_utils.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2003-2012 Tim Kientzle
  3. * Copyright (c) 2012 Andres Mejia
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "test_utils.h"
  27. #include <errno.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <assert.h>
  32. static inline uint64_t
  33. xorshift64(uint64_t *state)
  34. {
  35. uint64_t x = *state;
  36. x ^= x << 13;
  37. x ^= x >> 7;
  38. x ^= x << 17;
  39. *state = x;
  40. return (x);
  41. }
  42. /*
  43. * Fill a buffer with reproducible pseudo-random data using a simple xorshift
  44. * algorithm. Originally, most tests filled buffers with a loop that calls
  45. * rand() once for each byte. However, this initialization can be extremely
  46. * slow when running on emulated platforms such as QEMU where 16M calls to
  47. * rand() take a long time: Before the test_write_format_7zip_large_copy test
  48. * took ~22 seconds, whereas using a xorshift random number generator (that can
  49. * be inlined) reduces it to ~17 seconds on QEMU RISC-V.
  50. */
  51. static void
  52. fill_with_pseudorandom_data_seed(uint64_t seed, void *buffer, size_t size)
  53. {
  54. uint64_t *aligned_buffer;
  55. size_t num_values;
  56. size_t i;
  57. size_t unaligned_suffix;
  58. size_t unaligned_prefix = 0;
  59. /*
  60. * To avoid unaligned stores we only fill the aligned part of the buffer
  61. * with pseudo-random data and fill the unaligned prefix with 0xab and
  62. * the suffix with 0xcd.
  63. */
  64. if ((uintptr_t)buffer % sizeof(uint64_t)) {
  65. unaligned_prefix =
  66. sizeof(uint64_t) - (uintptr_t)buffer % sizeof(uint64_t);
  67. aligned_buffer =
  68. (uint64_t *)((char *)buffer + unaligned_prefix);
  69. memset(buffer, 0xab, unaligned_prefix);
  70. } else {
  71. aligned_buffer = (uint64_t *)buffer;
  72. }
  73. assert((uintptr_t)aligned_buffer % sizeof(uint64_t) == 0);
  74. num_values = (size - unaligned_prefix) / sizeof(uint64_t);
  75. unaligned_suffix =
  76. size - unaligned_prefix - num_values * sizeof(uint64_t);
  77. for (i = 0; i < num_values; i++) {
  78. aligned_buffer[i] = xorshift64(&seed);
  79. }
  80. if (unaligned_suffix) {
  81. memset((char *)buffer + size - unaligned_suffix, 0xcd,
  82. unaligned_suffix);
  83. }
  84. }
  85. void
  86. fill_with_pseudorandom_data(void *buffer, size_t size)
  87. {
  88. uint64_t seed;
  89. const char* seed_str;
  90. /*
  91. * Check if a seed has been specified in the environment, otherwise fall
  92. * back to using rand() as a seed.
  93. */
  94. if ((seed_str = getenv("TEST_RANDOM_SEED")) != NULL) {
  95. errno = 0;
  96. seed = strtoull(seed_str, NULL, 10);
  97. if (errno != 0) {
  98. fprintf(stderr, "strtoull(%s) failed: %s", seed_str,
  99. strerror(errno));
  100. seed = rand();
  101. }
  102. } else {
  103. seed = rand();
  104. }
  105. fill_with_pseudorandom_data_seed(seed, buffer, size);
  106. }