test_sars_load.c (12451B)
1 /* Copyright (C) 2022, 2023 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redismshbute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is dismshbuted in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #define _POSIX_C_SOURCE 200112L /* nextarfter */ 17 18 #include "sars.h" 19 #include <rsys/hash.h> 20 #include <rsys/mem_allocator.h> 21 #include <math.h> 22 #include <string.h> 23 24 /******************************************************************************* 25 * Helper functions 26 ******************************************************************************/ 27 static void 28 check_sars_load 29 (const struct sars* sars, 30 const size_t nbands, 31 const size_t nnodes) 32 { 33 struct sars_band band = SARS_BAND_NULL; 34 size_t iband; 35 36 CHK(sars); 37 CHK(nbands); 38 CHK(nnodes); 39 40 CHK(sars_get_bands_count(sars) == nbands); 41 CHK(sars_get_nodes_count(sars) == nnodes); 42 43 CHK(sars_get_band(NULL, 0, &band) == RES_BAD_ARG); 44 CHK(sars_get_band(sars, nbands, &band) == RES_BAD_ARG); 45 CHK(sars_get_band(sars, nbands, NULL) == RES_BAD_ARG); 46 CHK(sars_get_band(sars, 0, &band) == RES_OK); 47 48 FOR_EACH(iband, 0, nbands) { 49 const double low = (double)(iband+1); 50 const double upp = (double)(iband+2); 51 size_t inode; 52 53 CHK(sars_get_band(sars, iband, &band) == RES_OK); 54 CHK(band.lower == low); 55 CHK(band.upper == upp); 56 CHK(band.id == iband); 57 58 FOR_EACH(inode, 0, nnodes) { 59 const float ks = (float)(iband*2000 + inode); 60 const float ka = (float)(iband*1000 + inode); 61 CHK(sars_band_get_ks(&band, inode) == ks); 62 CHK(sars_band_get_ka(&band, inode) == ka); 63 } 64 } 65 } 66 67 static void 68 write_sars 69 (FILE* fp, 70 const uint64_t pagesize, 71 const uint64_t nbands, 72 const uint64_t nnodes) 73 { 74 uint64_t iband; 75 const char byte = 0; 76 77 /* Write the header */ 78 CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); 79 CHK(fwrite(&nbands, sizeof(nbands), 1, fp) == 1); 80 CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); 81 82 FOR_EACH(iband, 0, nbands) { 83 const double low = (double)(iband+1); 84 const double upp = (double)(iband+2); 85 86 /* Write band description */ 87 CHK(fwrite(&low, sizeof(low), 1, fp) == 1); 88 CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); 89 } 90 91 /* Write per band ks and ka */ 92 FOR_EACH(iband, 0, nbands) { 93 uint64_t inode; 94 95 /* Padding */ 96 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET)==0); 97 98 FOR_EACH(inode, 0, nnodes) { 99 const float ka = (float)(iband*1000 + inode); 100 const float ks = (float)(iband*2000 + inode); 101 CHK(fwrite(&ka, sizeof(ka), 1, fp) == 1); 102 CHK(fwrite(&ks, sizeof(ks), 1, fp) == 1); 103 } 104 } 105 106 /* Padding. Write one char to position the EOF indicator */ 107 CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); 108 CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); 109 } 110 111 static void 112 test_load(struct sars* sars) 113 { 114 hash256_T hash0; 115 hash256_T hash1; 116 hash256_T band_hash0; 117 hash256_T band_hash1; 118 struct sars_load_args args = SARS_LOAD_ARGS_NULL; 119 struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL; 120 121 FILE* fp = NULL; 122 const char* filename = "test_file.sars"; 123 const uint64_t pagesize = 16384; 124 const uint64_t nbands = 11; 125 const uint64_t nnodes = 1000; 126 127 CHK(fp = fopen(filename, "w+")); 128 write_sars(fp, pagesize, nbands, nnodes); 129 rewind(fp); 130 131 stream_args.stream =fp; 132 stream_args.name = filename; 133 CHK(sars_load_stream(NULL, &stream_args) == RES_BAD_ARG); 134 CHK(sars_load_stream(sars, NULL) == RES_BAD_ARG); 135 stream_args.stream = NULL; 136 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 137 stream_args.stream = fp; 138 CHK(sars_load_stream(sars, &stream_args) == RES_OK); 139 140 CHK(!strcmp(sars_get_name(sars), filename)); 141 142 CHK(sars_compute_hash(NULL, hash0) == RES_BAD_ARG); 143 CHK(sars_compute_hash(sars, NULL) == RES_BAD_ARG); 144 CHK(sars_compute_hash(sars, hash0) == RES_OK); 145 146 CHK(sars_band_compute_hash(NULL, 0, band_hash0) == RES_BAD_ARG); 147 CHK(sars_band_compute_hash(sars, nbands, band_hash0) == RES_BAD_ARG); 148 CHK(sars_band_compute_hash(sars, 0, NULL) == RES_BAD_ARG); 149 CHK(sars_band_compute_hash(sars, 0, band_hash0) == RES_OK); 150 CHK(!hash256_eq(hash0, band_hash0)); 151 152 CHK(sars_band_compute_hash(sars, 0, band_hash1) == RES_OK); 153 CHK(hash256_eq(band_hash0, band_hash1)); 154 155 check_sars_load(sars, nbands, nnodes); 156 rewind(fp); 157 158 stream_args.name = NULL; 159 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 160 stream_args.name = SARS_LOAD_STREAM_ARGS_NULL.name; 161 stream_args.memory_mapping = 1; 162 CHK(sars_load_stream(sars, &stream_args) == RES_OK); 163 CHK(!strcmp(sars_get_name(sars), SARS_LOAD_STREAM_ARGS_NULL.name)); 164 check_sars_load(sars, nbands, nnodes); 165 166 args.path = "nop"; 167 CHK(sars_load(NULL, &args) == RES_BAD_ARG); 168 CHK(sars_load(sars, NULL) == RES_BAD_ARG); 169 CHK(sars_load(sars, &args) == RES_IO_ERR); 170 args.path = filename; 171 CHK(sars_load(sars, &args) == RES_OK); 172 check_sars_load(sars, nbands, nnodes); 173 174 CHK(sars_compute_hash(sars, hash1) == RES_OK); 175 CHK(hash256_eq(hash0, hash1)); 176 177 rewind(fp); 178 write_sars(fp, pagesize, nbands+1, nnodes); 179 rewind(fp); 180 181 stream_args.stream = fp; 182 stream_args.name = filename; 183 CHK(sars_load_stream(sars, &stream_args) == RES_OK); 184 CHK(sars_compute_hash(sars, hash1) == RES_OK); 185 CHK(!hash256_eq(hash0, hash1)); 186 187 CHK(sars_band_compute_hash(sars, 0, band_hash1) == RES_OK); 188 CHK(hash256_eq(band_hash0, band_hash1)); 189 190 CHK(fclose(fp) == 0); 191 } 192 193 static void 194 test_load_fail(struct sars* sars) 195 { 196 struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL; 197 FILE* fp = NULL; 198 double low; 199 double upp; 200 201 /* The pagesize is less than the operating system page size*/ 202 CHK(fp = tmpfile()); 203 write_sars(fp, 2048, 1, 1); 204 rewind(fp); 205 stream_args.stream = fp; 206 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 207 CHK(fclose(fp) == 0); 208 209 /* The pagesize is not a power of two */ 210 CHK(fp = tmpfile()); 211 write_sars(fp, 4100, 1, 1); 212 rewind(fp); 213 stream_args.stream = fp; 214 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 215 CHK(fclose(fp) == 0); 216 217 /* Wrong #bands */ 218 CHK(fp = tmpfile()); 219 write_sars(fp, 4096, 0, 1); 220 rewind(fp); 221 stream_args.stream = fp; 222 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 223 CHK(fclose(fp) == 0); 224 225 /* Wrong #nodes */ 226 CHK(fp = tmpfile()); 227 write_sars(fp, 4096, 1, 0); 228 rewind(fp); 229 stream_args.stream = fp; 230 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 231 CHK(fclose(fp) == 0); 232 233 /* Wrong band boundaries */ 234 low = 1; 235 upp = 0; 236 CHK(fp = tmpfile()); 237 write_sars(fp, 4096, 1, 1); 238 CHK(fseek(fp, 24, SEEK_SET) == 0); 239 CHK(fwrite(&low, sizeof(low), 1, fp) == 1); 240 CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); 241 rewind(fp); 242 stream_args.stream = fp; 243 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 244 CHK(fclose(fp) == 0); 245 246 /* Unsorted bands */ 247 CHK(fp = tmpfile()); 248 write_sars(fp, 4096, 2, 1); 249 CHK(fseek(fp, 24, SEEK_SET) == 0); 250 low = 1; upp = 2; 251 CHK(fwrite(&low, sizeof(low), 1, fp) == 1); 252 CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); 253 low = 0; upp = 1; 254 CHK(fwrite(&low, sizeof(low), 1, fp) == 1); 255 CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); 256 rewind(fp); 257 stream_args.stream = fp; 258 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 259 CHK(fclose(fp) == 0); 260 261 /* Bands overlap */ 262 CHK(fp = tmpfile()); 263 write_sars(fp, 4096, 2, 1); 264 CHK(fseek(fp, 24, SEEK_SET) == 0); 265 low = 0; upp = 1; 266 CHK(fwrite(&low, sizeof(low), 1, fp) == 1); 267 CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); 268 low = 0.5; upp = 1.5; 269 CHK(fwrite(&low, sizeof(low), 1, fp) == 1); 270 CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); 271 rewind(fp); 272 stream_args.stream = fp; 273 CHK(sars_load_stream(sars, &stream_args) == RES_BAD_ARG); 274 CHK(fclose(fp) == 0); 275 } 276 277 static void 278 test_load_files(struct sars* sars, int argc, char** argv) 279 { 280 int i; 281 CHK(sars); 282 FOR_EACH(i, 1, argc) { 283 hash256_T hash; 284 size_t nnodes; 285 size_t nbands; 286 size_t iband; 287 288 if(!strcmp(argv[i], "-")) { /* Read from stdin */ 289 struct sars_load_stream_args args = SARS_LOAD_STREAM_ARGS_NULL; 290 printf("Load from stdin\n"); 291 args.stream = stdin; 292 args.name = "stdin"; 293 args.memory_mapping = 1; 294 CHK(sars_load_stream(sars, &args) == RES_BAD_ARG); 295 args.memory_mapping = 0; 296 CHK(sars_load_stream(sars, &args) == RES_OK); 297 } else { 298 struct sars_load_args args = SARS_LOAD_ARGS_NULL; 299 printf("Load %s\n", argv[1]); 300 args.path = argv[i]; 301 args.memory_mapping = 1; 302 CHK(sars_load(sars, &args) == RES_OK); 303 } 304 nbands = sars_get_bands_count(sars); 305 nnodes = sars_get_nodes_count(sars); 306 CHK(nbands); 307 CHK(nnodes); 308 309 FOR_EACH(iband, 0, nbands) { 310 struct sars_band band = SARS_BAND_NULL; 311 312 CHK(sars_get_band(sars, iband, &band) == RES_OK); 313 printf("band %lu in [%g, %g[ nm\n", 314 (unsigned long)band.id, 315 band.lower, band.upper); 316 } 317 318 CHK(sars_validate(sars) == RES_OK); 319 CHK(sars_compute_hash(sars, hash) == RES_OK); 320 } 321 } 322 323 static void 324 test_find(struct sars* sars) 325 { 326 struct sars_load_stream_args stream_args = SARS_LOAD_STREAM_ARGS_NULL; 327 size_t ibands[2]; 328 double range[2]; 329 FILE* fp; 330 331 CHK(fp = tmpfile()); 332 write_sars(fp, 4096, 10, 1); 333 rewind(fp); 334 stream_args.stream = fp; 335 CHK(sars_load_stream(sars, &stream_args) == RES_OK); 336 337 range[0] = 0; 338 range[1] = 10; 339 CHK(sars_find_bands(NULL, range, ibands) == RES_BAD_ARG); 340 CHK(sars_find_bands(sars, NULL, ibands) == RES_BAD_ARG); 341 CHK(sars_find_bands(sars, range, NULL) == RES_BAD_ARG); 342 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 343 CHK(ibands[0] == 0 && ibands[1] == 9); 344 345 range[0] = 10; 346 range[1] = 0; 347 CHK(sars_find_bands(sars, range, ibands) == RES_BAD_ARG); 348 349 range[0] = 11; 350 range[1] = 12; 351 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 352 CHK(ibands[0] > ibands[1]); 353 354 range[0] = 11; 355 range[1] = 11; 356 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 357 CHK(ibands[0] > ibands[1]); 358 359 range[0] = 0; 360 range[1] = nextafter(1, 0); 361 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 362 CHK(ibands[0] > ibands[1]); 363 364 range[0] = 0; 365 range[1] = 0; 366 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 367 CHK(ibands[0] > ibands[1]); 368 369 range[0] = nextafter(1, 0); 370 range[1] = nextafter(1, 0); 371 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 372 CHK(ibands[0] > ibands[1]); 373 374 range[0] = 2; 375 range[1] = 2; 376 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 377 CHK(ibands[0] == 1 && ibands[1] == 1); 378 379 range[0] = 0; 380 range[1] = 1; 381 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 382 CHK(ibands[0] == 0 && ibands[1] == 0); 383 384 range[0] = 1; 385 range[1] = nextafterf(2, 1); 386 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 387 CHK(ibands[0] == 0 && ibands[1] == 0); 388 389 range[0] = 2; 390 range[1] = 20; 391 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 392 CHK(ibands[0] == 1 && ibands[1] == 9); 393 394 range[0] = 1.5; 395 range[1] = 2; 396 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 397 CHK(ibands[0] == 0 && ibands[1] == 1); 398 399 range[0] = 3.1; 400 range[1] = nextafter(6, 0); 401 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 402 CHK(ibands[0] == 2 && ibands[1] == 4); 403 404 range[0] = 3.1; 405 range[1] = 7; 406 CHK(sars_find_bands(sars, range, ibands) == RES_OK); 407 CHK(ibands[0] == 2 && ibands[1] == 6); 408 409 CHK(fclose(fp) == 0); 410 } 411 412 /******************************************************************************* 413 * Main function 414 ******************************************************************************/ 415 int 416 main(int argc, char** argv) 417 { 418 struct sars_create_args args = SARS_CREATE_ARGS_DEFAULT; 419 struct sars* sars = NULL; 420 (void)argc, (void)argv; 421 422 args.verbose = 1; 423 CHK(sars_create(&args, &sars) == RES_OK); 424 425 if(argc > 1) { 426 test_load_files(sars, argc, argv); 427 } else { 428 test_load(sars); 429 test_load_fail(sars); 430 test_find(sars); 431 } 432 433 CHK(sars_ref_put(sars) == RES_OK); 434 CHK(mem_allocated_size() == 0); 435 return 0; 436 }