1 // Copyright (c) Lawrence Livermore National Security, LLC and other Conduit
2 // Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
3 // other details. No copyright assignment is required to contribute to Conduit.
4
5 //-----------------------------------------------------------------------------
6 ///
7 /// file: t_relay_zfp.cpp
8 ///
9 //-----------------------------------------------------------------------------
10
11 #include "conduit_relay.hpp"
12 #include "conduit_relay_zfp.hpp"
13 #include "gtest/gtest.h"
14 #include <cstring>
15
16 using namespace conduit;
17 using namespace conduit::relay;
18
19 //-----------------------------------------------------------------------------
TEST(conduit_relay_zfp,wrap_zfparray_and_verify_header)20 TEST(conduit_relay_zfp, wrap_zfparray_and_verify_header)
21 {
22 // initialize empty result Node
23 Node result;
24 EXPECT_FALSE(result.has_child(io::ZFP_HEADER_FIELD_NAME));
25
26 // create compressed-array
27 uint nx = 9;
28 uint ny = 12;
29 double rate = 8.0;
30 zfp::array2f arr(nx, ny, rate);
31
32 // write zfparray to Node
33 EXPECT_EQ(0, io::wrap_zfparray(&arr, result));
34
35 // verify header entry was set
36 EXPECT_TRUE(result.has_child(io::ZFP_HEADER_FIELD_NAME));
37 Node n_header = result[io::ZFP_HEADER_FIELD_NAME];
38
39 // assert header dtype
40 EXPECT_TRUE(n_header.dtype().is_uint8());
41 uint8_array header_as_arr = n_header.as_uint8_array();
42
43 // assert header length
44 zfp::array::header header = arr.get_header();
45 EXPECT_EQ(sizeof(header), header_as_arr.number_of_elements());
46
47 // assert header contents
48 EXPECT_TRUE(0 == std::memcmp(header.buffer, n_header.data_ptr(), sizeof(header)));
49 }
50
51 //-----------------------------------------------------------------------------
TEST(conduit_relay_zfp,wrap_zfparray_and_verify_compressed_data)52 TEST(conduit_relay_zfp, wrap_zfparray_and_verify_compressed_data)
53 {
54 // initialize empty result Node
55 Node result;
56 EXPECT_FALSE(result.has_child(io::ZFP_COMPRESSED_DATA_FIELD_NAME));
57
58 // create compressed-array
59 uint nx = 9;
60 uint ny = 12;
61 uint ntotal = nx * ny;
62 float * vals = new float[ntotal];
63 uint i;
64 for (i = 0; i < ntotal; i++) {
65 vals[i] = i*i;
66 }
67
68 double rate = 8.0;
69 zfp::array2f arr(nx, ny, rate, vals);
70
71 // write zfparray to Node
72 EXPECT_EQ(0, io::wrap_zfparray(&arr, result));
73
74 // verify compressed data entry was set
75 EXPECT_TRUE(result.has_child(io::ZFP_COMPRESSED_DATA_FIELD_NAME));
76 Node n_data = result[io::ZFP_COMPRESSED_DATA_FIELD_NAME];
77
78 EXPECT_TRUE(n_data.dtype().is_unsigned_integer());
79 size_t compressed_data_num_words = arr.compressed_size() * CHAR_BIT / stream_word_bits;
80
81 // compressed-data entry written with same uint type, having width `stream_word_bits`
82 switch(stream_word_bits) {
83 case 64:
84 EXPECT_TRUE(n_data.dtype().is_uint64());
85 {
86 uint64_array data_as_arr = n_data.as_uint64_array();
87 EXPECT_EQ(compressed_data_num_words, data_as_arr.number_of_elements());
88 }
89 break;
90
91 case 32:
92 EXPECT_TRUE(n_data.dtype().is_uint32());
93 {
94 uint32_array data_as_arr = n_data.as_uint32_array();
95 EXPECT_EQ(compressed_data_num_words, data_as_arr.number_of_elements());
96 }
97 break;
98
99 case 16:
100 EXPECT_TRUE(n_data.dtype().is_uint16());
101 {
102 uint16_array data_as_arr = n_data.as_uint16_array();
103 EXPECT_EQ(compressed_data_num_words, data_as_arr.number_of_elements());
104 }
105 break;
106
107 case 8:
108 EXPECT_TRUE(n_data.dtype().is_uint8());
109 {
110 uint8_array data_as_arr = n_data.as_uint8_array();
111 EXPECT_EQ(compressed_data_num_words, data_as_arr.number_of_elements());
112 }
113 break;
114
115 default:
116 FAIL() << "ZFP was compiled with an unrecognizable word type";
117 break;
118 }
119
120 delete [] vals;
121
122 EXPECT_TRUE(0 == std::memcmp(arr.compressed_data(), n_data.data_ptr(), arr.compressed_size()));
123 }
124
125 //-----------------------------------------------------------------------------
TEST(conduit_relay_zfp,wrap_zfparray_with_header_exception)126 TEST(conduit_relay_zfp, wrap_zfparray_with_header_exception)
127 {
128 // create compressed-array that does not support short header
129 uint nx = 9;
130 uint ny = 12;
131 uint nz = 5;
132 double rate = 64.0;
133 zfp::array3d arr(nx, ny, nz, rate);
134
135 // write zfparray to Node, but expect failure
136 Node result;
137 EXPECT_EQ(1, io::wrap_zfparray(&arr, result));
138 }
139
140 //-----------------------------------------------------------------------------
TEST(conduit_relay_zfp,unwrap_zfparray)141 TEST(conduit_relay_zfp, unwrap_zfparray)
142 {
143 // create compressed-array
144 uint nx = 9;
145 uint ny = 12;
146
147 float vals[nx * ny];
148 uint i, j;
149 for (j = 0; j < ny; j++) {
150 for (i = 0; i < nx; i++) {
151 vals[nx*j + i] = i * 10. + j*j;
152 }
153 }
154
155 double rate = 32.0;
156 zfp::array2f original_arr(nx, ny, rate, vals);
157
158 // write zfparray to Node
159 Node result;
160 EXPECT_EQ(0, io::wrap_zfparray(&original_arr, result));
161
162 // fetch zfparray object from Node
163 zfp::array* fetched_arr = io::unwrap_zfparray(result);
164
165 // verify against original_arr
166 ASSERT_TRUE(fetched_arr != 0);
167
168 zfp::array2f* casted_arr = dynamic_cast<zfp::array2f*>(fetched_arr);
169 ASSERT_TRUE(casted_arr != 0);
170
171 EXPECT_EQ(nx, casted_arr->size_x());
172 EXPECT_EQ(ny, casted_arr->size_y());
173 EXPECT_EQ(rate, casted_arr->rate());
174
175 // verify compressed data
176 EXPECT_EQ(original_arr.compressed_size(), casted_arr->compressed_size());
177 EXPECT_TRUE(0 == std::memcmp(original_arr.compressed_data(), casted_arr->compressed_data(), original_arr.compressed_size()));
178
179 delete fetched_arr;
180 }
181
182 //-----------------------------------------------------------------------------
TEST(conduit_relay_zfp,unwrap_zfparray_with_exception)183 TEST(conduit_relay_zfp, unwrap_zfparray_with_exception)
184 {
185 // create compressed-array
186 uint nx = 9;
187 uint ny = 12;
188
189 double rate = 32.0;
190 zfp::array2f original_arr(nx, ny, rate);
191
192 // write zfparray to Node
193 Node result;
194 EXPECT_EQ(0, io::wrap_zfparray(&original_arr, result));
195
196 // corrupt the Node's data
197 size_t n = 10;
198 float * vals = new float[n];
199 for (size_t i = 0; i < n; i++) {
200 vals[i] = 0;
201 }
202 result[io::ZFP_HEADER_FIELD_NAME].set(vals, sizeof(vals));
203
204 // fetch zfparray object from Node
205 zfp::array* fetched_arr = io::unwrap_zfparray(result);
206
207 // verify no instance returned
208 ASSERT_TRUE(fetched_arr == 0);
209
210 delete [] vals;
211 }
212
213 //-----------------------------------------------------------------------------
TEST(conduit_relay_zfp,unwrap_zfparray_with_compressed_data_dtype_mismatched_with_compiled_zfp_word_size)214 TEST(conduit_relay_zfp, unwrap_zfparray_with_compressed_data_dtype_mismatched_with_compiled_zfp_word_size)
215 {
216 // create compressed-array
217 uint nx = 9;
218 uint ny = 12;
219 uint nz = 15;
220
221 double rate = 16.0;
222 zfp::array3f arr(nx, ny, nz, rate);
223
224 // write zfparray to Node
225 Node result;
226 EXPECT_EQ(0, relay::io::wrap_zfparray(&arr, result));
227
228 // remove compressed-data node
229 EXPECT_TRUE(result.has_child(io::ZFP_COMPRESSED_DATA_FIELD_NAME));
230 result.remove(io::ZFP_COMPRESSED_DATA_FIELD_NAME);
231
232 // re-add compressed-data node as the wrong type
233 switch(stream_word_bits) {
234 case 64:
235 case 32:
236 case 16:
237 {
238 conduit::uint8 data = 3;
239 result[io::ZFP_COMPRESSED_DATA_FIELD_NAME] = data;
240 }
241 break;
242
243 case 8:
244 {
245 conduit::uint64 data = 3;
246 result[io::ZFP_COMPRESSED_DATA_FIELD_NAME] = data;
247 }
248 break;
249
250 default:
251 FAIL() << "ZFP was compiled with an unrecognizable word type";
252 }
253
254 // fetch zfparray object from Node
255 zfp::array* fetched_arr = io::unwrap_zfparray(result);
256
257 // verify no instance returned
258 ASSERT_TRUE(fetched_arr == 0);
259 }
260
261