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