star-aerosol

Describe the radiative properties of aerosols
git clone git://git.meso-star.fr/star-aerosol.git
Log | Files | Refs | README | LICENSE

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 }