1 /*********************************************************************
2   Blosc - Blocked Shuffling and Compression Library
3 
4   Unit tests for basic features in Blosc.
5 
6   Creation date: 2010-06-07
7   Author: The Blosc Developers <blosc@blosc.org>
8 
9   See LICENSE.txt for details about copyright and rights to use.
10 **********************************************************************/
11 
12 #ifndef BLOSC_TEST_COMMON_H
13 #define BLOSC_TEST_COMMON_H
14 
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <stdbool.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <math.h>
23 #include "blosc2.h"
24 #if defined(_WIN32) && !defined(__MINGW32__)
25   #include <time.h>
26   #include "win32/stdint-windows.h"
27 #else
28   #include <stdint.h>
29   #include <sys/time.h>
30 #endif
31 
32 #if defined(_WIN32)
33   /* MSVC does not have setenv */
34   #define setenv(name, value, overwrite) do {_putenv_s(name, value);} while(0)
35 #endif
36 
37 
38 /* This is MinUnit in action (http://www.jera.com/techinfo/jtns/jtn002.html) */
39 #define mu_assert(message, test) do { if (!(test)) return message; } while (0)
40 #define mu_run_test(test) do \
41     { char *message = test(); tests_run++;                          \
42       if (message) { printf("%c", 'F'); return message;}            \
43       else printf("%c", '.'); } while (0)
44 
45 extern int tests_run;
46 
47 #define KB  1024
48 #define MB  (1024*KB)
49 #define GB  (1024*MB)
50 
51 /*
52   Memory functions.
53 */
54 
55 #define UNUSED(x) ((void)(x))
56 
57 /** Allocates a block of memory with the specified size and alignment.
58     The allocated memory is 'cleaned' before returning to avoid
59     accidental re-use of data within or between tests.
60  */
blosc_test_malloc(const size_t alignment,const size_t size)61 inline static void* blosc_test_malloc(const size_t alignment, const size_t size) {
62   const int32_t clean_value = 0x99;
63   void* block = NULL;
64   int32_t res = 0;
65 
66 #if defined(_ISOC11_SOURCE) || ((defined(__DragonFly__) || defined(__FreeBSD__)) && __STDC_VERSION__ >= 201112L)
67   /* C11 aligned allocation. 'size' must be a multiple of the alignment. */
68   block = aligned_alloc(alignment, size);
69 #elif defined(_WIN32)
70   /* A (void *) cast needed for avoiding a warning with MINGW :-/ */
71   block = (void *)_aligned_malloc(size, alignment);
72 #elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__DragonFly__)
73   /* Platform does have an implementation of posix_memalign */
74   res = posix_memalign(&block, alignment, size);
75 #elif defined(__APPLE__)
76   /* Mac OS X guarantees 16-byte alignment in small allocs */
77   UNUSED(alignment);
78   block = malloc(size);
79 #else
80   #error Cannot determine how to allocate aligned memory on the target platform.
81 #endif
82 
83   if (block == NULL || res != 0) {
84     fprintf(stderr, "Error allocating memory!");
85     return NULL;
86   }
87 
88   /* Clean the allocated memory before returning. */
89   memset(block, clean_value, size);
90 
91   return block;
92 }
93 
94 /** Frees memory allocated by blosc_test_malloc. */
blosc_test_free(void * ptr)95 inline static void blosc_test_free(void* ptr) {
96 #if defined(_WIN32)
97   _aligned_free(ptr);
98 #else
99   free(ptr);
100 #endif  /* _WIN32 */
101 }
102 
103 /** Fills a buffer with contiguous values. */
blosc_test_fill_seq(void * const ptr,const size_t size)104 inline static void blosc_test_fill_seq(void* const ptr, const size_t size) {
105   size_t k;
106   uint8_t* const byte_ptr = (uint8_t*)ptr;
107   for (k = 0; k < size; k++) {
108     byte_ptr[k] = (uint8_t)k;
109   }
110 }
111 
112 /** Fills a buffer with random values. */
blosc_test_fill_random(void * const ptr,const size_t size)113 inline static void blosc_test_fill_random(void* const ptr, const size_t size) {
114   size_t k;
115   uint8_t* const byte_ptr = (uint8_t*)ptr;
116   for (k = 0; k < size; k++) {
117     byte_ptr[k] = (uint8_t)rand();
118   }
119 }
120 
121 /*
122   Argument parsing.
123 */
124 
125 /** Parse a `int32_t` value from a string, checking for overflow. */
blosc_test_parse_uint32_t(const char * const str,uint32_t * value)126 inline static bool blosc_test_parse_uint32_t(const char* const str, uint32_t* value) {
127   char* str_end;
128   long signed_value = strtol(str, &str_end, 10);
129   if (signed_value < 0 || *str_end) {
130     return false;
131   }
132   else {
133     *value = (uint32_t)signed_value;
134     return true;
135   }
136 }
137 
138 /*
139   Error message functions.
140 */
141 
142 /** Print an error message when a test program has been invoked
143     with an invalid number of arguments. */
blosc_test_print_bad_argcount_msg(const int32_t num_expected_args,const int32_t num_actual_args)144 inline static void blosc_test_print_bad_argcount_msg(
145     const int32_t num_expected_args, const int32_t num_actual_args) {
146   fprintf(stderr, "Invalid number of arguments specified.\nExpected %d arguments but was given %d.",
147           num_expected_args, num_actual_args);
148 }
149 
150 /** Print an error message when a test program has been invoked
151     with an invalid argument value. */
blosc_test_print_bad_arg_msg(const int32_t arg_index)152 inline static void blosc_test_print_bad_arg_msg(const int32_t arg_index) {
153   fprintf(stderr, "Invalid value specified for argument at index %d.\n", arg_index);
154 }
155 
156 /* dummy callback backend for testing purposes */
157 /* serial "threads" backend */
dummy_threads_callback(void * callback_data,void (* dojob)(void *),int numjobs,size_t jobdata_elsize,void * jobdata)158 static void dummy_threads_callback(void *callback_data, void (*dojob)(void *), int numjobs, size_t jobdata_elsize, void *jobdata)
159 {
160   int i;
161   (void) callback_data; /* unused */
162   for (i = 0; i < numjobs; ++i)
163     dojob(((char *) jobdata) + ((unsigned) i)*jobdata_elsize);
164 }
165 
166 /* install the callback if environment variable BLOSC_TEST_CALLBACK="yes" */
install_blosc_callback_test(void)167 inline static void install_blosc_callback_test(void)
168 {
169   char *callback_env;
170   callback_env = getenv("BLOSC_TEST_CALLBACK");
171   if (callback_env && !strcmp(callback_env, "yes"))
172     blosc_set_threads_callback(dummy_threads_callback, NULL);
173 }
174 
175 #endif  /* !defined(BLOSC_TEST_COMMON_H) */
176