1 /*
2 Copyright (C) 2021 The Blosc Developers <blosc@blosc.org>
3 https://blosc.org
4 License: BSD 3-Clause (see LICENSE.txt)
5 */
6
7 #include "test_common.h"
8 #include "cutest.h"
9
10 #define CHUNKSIZE (5 * 1000) // > NCHUNKS for the bench purposes
11 #define NCHUNKS 10
12
13
14 typedef struct {
15 int32_t open;
16 int32_t close;
17 int32_t tell;
18 int32_t seek;
19 int32_t write;
20 int32_t read;
21 int32_t truncate;
22 } test_udio_params;
23
24
25 typedef struct {
26 blosc2_stdio_file *bfile;
27 test_udio_params *params;
28 } test_file;
29
30
test_open(const char * urlpath,const char * mode,void * params)31 void* test_open(const char *urlpath, const char *mode, void *params) {
32 test_file *my = malloc(sizeof(test_file));
33 my->params = params;
34 my->params->open++;
35
36 my->bfile = blosc2_stdio_open(urlpath, mode, NULL);
37 return my;
38 }
39
test_close(void * stream)40 int test_close(void *stream) {
41 test_file *my = (test_file *) stream;
42 my->params->close++;
43 int err = blosc2_stdio_close(my->bfile);
44 free(my);
45 return err;
46 }
47
test_tell(void * stream)48 int64_t test_tell(void *stream) {
49 test_file *my = (test_file *) stream;
50 my->params->tell++;
51 return blosc2_stdio_tell(my->bfile);
52 }
53
test_seek(void * stream,int64_t offset,int whence)54 int test_seek(void *stream, int64_t offset, int whence) {
55 test_file *my = (test_file *) stream;
56 my->params->seek++;
57 return blosc2_stdio_seek(my->bfile, offset, whence);
58 }
59
test_write(const void * ptr,int64_t size,int64_t nitems,void * stream)60 int64_t test_write(const void *ptr, int64_t size, int64_t nitems, void *stream) {
61 test_file *my = (test_file *) stream;
62 my->params->write++;
63 return blosc2_stdio_write(ptr, size, nitems, my->bfile);
64 }
65
test_read(void * ptr,int64_t size,int64_t nitems,void * stream)66 int64_t test_read(void *ptr, int64_t size, int64_t nitems, void *stream) {
67 test_file *my = (test_file *) stream;
68 my->params->read++;
69 return blosc2_stdio_read(ptr, size, nitems, my->bfile);
70 }
71
test_truncate(void * stream,int64_t size)72 int64_t test_truncate(void *stream, int64_t size) {
73 test_file *my = (test_file *) stream;
74 my->params->truncate++;
75 return blosc2_stdio_truncate(my->bfile, size);
76 }
77
78
79 typedef struct {
80 bool contiguous;
81 char *urlpath;
82 }test_udio_backend;
83
CUTEST_TEST_DATA(udio)84 CUTEST_TEST_DATA(udio) {
85 blosc2_cparams cparams;
86 };
87
CUTEST_TEST_SETUP(udio)88 CUTEST_TEST_SETUP(udio) {
89 blosc_init();
90
91 blosc2_io_cb io_cb;
92
93 io_cb.id = 244;
94 io_cb.open = (blosc2_open_cb) test_open;
95 io_cb.close = (blosc2_close_cb) test_close;
96 io_cb.read = (blosc2_read_cb) test_read;
97 io_cb.tell = (blosc2_tell_cb) test_tell;
98 io_cb.seek = (blosc2_seek_cb) test_seek;
99 io_cb.write = (blosc2_write_cb) test_write;
100 io_cb.truncate = (blosc2_truncate_cb) test_truncate;
101
102 blosc2_register_io_cb(&io_cb);
103
104 data->cparams = BLOSC2_CPARAMS_DEFAULTS;
105 data->cparams.typesize = sizeof(int32_t);
106 data->cparams.compcode = BLOSC_BLOSCLZ;
107 data->cparams.clevel = 4;
108 data->cparams.nthreads = 2;
109
110 CUTEST_PARAMETRIZE(backend, test_udio_backend, CUTEST_DATA(
111 {true, "test_udio.b2frame"}, // disk - cframe
112 {false, "test_udio_s.b2frame"}, // disk - sframe
113 ));
114 }
115
116
CUTEST_TEST_TEST(udio)117 CUTEST_TEST_TEST(udio) {
118 CUTEST_GET_PARAMETER(backend, test_udio_backend);
119
120 /* Free resources */
121 blosc2_remove_urlpath(backend.urlpath);
122
123 int32_t nbytes = CHUNKSIZE * sizeof(int32_t);
124 int32_t *data_buffer = malloc(nbytes);
125 int32_t *rec_buffer = malloc(nbytes);
126
127 /* Create a super-chunk container */
128 blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
129 cparams.typesize = sizeof(int32_t);
130 cparams.compcode = BLOSC_BLOSCLZ;
131 cparams.clevel = 9;
132 cparams.nthreads = 2;
133
134 test_udio_params io_params = {0};
135 blosc2_io io = {.id = 244, .params = &io_params};
136 blosc2_storage storage = {.cparams=&cparams, .contiguous=backend.contiguous, .urlpath = backend.urlpath, .io=&io};
137
138 blosc2_schunk *schunk = blosc2_schunk_new(&storage);
139
140 for (int i = 0; i < NCHUNKS; ++i) {
141 int32_t cbytes = blosc2_schunk_append_buffer(schunk, data_buffer, nbytes);
142 CUTEST_ASSERT("Error during compression", cbytes >= 0);
143 }
144
145 blosc2_schunk *schunk2 = blosc2_schunk_open_udio(backend.urlpath, &io);
146
147 for (int i = 0; i < NCHUNKS; ++i) {
148 int32_t dbytes = blosc2_schunk_decompress_chunk(schunk2, i, rec_buffer, nbytes);
149 CUTEST_ASSERT("Error during decompression", dbytes >= 0);
150 for (int j = 0; j < CHUNKSIZE; ++j) {
151 CUTEST_ASSERT("Data are not equal", data_buffer[j] == rec_buffer[j]);
152 }
153 }
154
155 // Check io params
156 CUTEST_ASSERT("Open must be positive", io_params.open > 0);
157 CUTEST_ASSERT("Close must be positive", io_params.close > 0);
158 CUTEST_ASSERT("Seek must be positive", io_params.seek > 0);
159 CUTEST_ASSERT("Write must be positive", io_params.write > 0);
160 CUTEST_ASSERT("Read must be positive", io_params.read > 0);
161 CUTEST_ASSERT("Truncate must be positive", io_params.truncate > 0);
162
163 blosc2_schunk_free(schunk);
164 blosc2_schunk_free(schunk2);
165 free(data_buffer);
166 free(rec_buffer);
167
168 return 0;
169 }
170
CUTEST_TEST_TEARDOWN(udio)171 CUTEST_TEST_TEARDOWN(udio) {
172 blosc_destroy();
173 }
174
175
main()176 int main() {
177 CUTEST_TEST_RUN(udio)
178 }
179