star-aerosol

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

commit f13f253294797237adefee4f5225e6676b80a31b
parent 39f50bea89b2bbd023408f7d56d1630714bcf547
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 15 Jun 2022 10:31:58 +0200

Test the loading functions

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Asrc/test_sars_load.c | 278+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 279 insertions(+), 1 deletion(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -82,7 +82,7 @@ if(NOT NO_TEST) endfunction() new_test(test_sars) - #new_test(test_sars_load) + new_test(test_sars_load) endif() ################################################################################ diff --git a/src/test_sars_load.c b/src/test_sars_load.c @@ -0,0 +1,278 @@ +/* Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redismshbute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is dismshbuted in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "sars.h" + +#include <rsys/mem_allocator.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +check_sars_load + (const struct sars* sars, + const size_t nbands, + const size_t nnodes) +{ + struct sars_band band = SARS_BAND_NULL; + size_t iband; + + CHK(sars); + CHK(nbands); + CHK(nnodes); + + CHK(sars_get_bands_count(sars) == nbands); + CHK(sars_get_nodes_count(sars) == nnodes); + + CHK(sars_get_band(NULL, 0, &band) == RES_BAD_ARG); + CHK(sars_get_band(sars, nbands, &band) == RES_BAD_ARG); + CHK(sars_get_band(sars, nbands, NULL) == RES_BAD_ARG); + CHK(sars_get_band(sars, 0, &band) == RES_OK); + + FOR_EACH(iband, 0, nbands) { + const double low = (double)iband; + const double upp = (double)(iband+1); + size_t inode; + + CHK(sars_get_band(sars, iband, &band) == RES_OK); + CHK(band.lower == low); + CHK(band.upper == upp); + CHK(band.id == iband); + + FOR_EACH(inode, 0, nnodes) { + const float ks = (float)(iband*2000 + inode); + const float ka = (float)(iband*1000 + inode); + CHK(band.ks_list[inode] == ks); + CHK(band.ka_list[inode] == ka); + } + } +} + +static void +write_sars + (FILE* fp, + const uint64_t pagesize, + const uint64_t nbands, + const uint64_t nnodes) +{ + uint64_t iband; + const char byte = 0; + + /* Write the header */ + CHK(fwrite(&pagesize, sizeof(pagesize), 1, fp) == 1); + CHK(fwrite(&nbands, sizeof(nbands), 1, fp) == 1); + CHK(fwrite(&nnodes, sizeof(nnodes), 1, fp) == 1); + + FOR_EACH(iband, 0, nbands) { + const double low = (double)iband; + const double upp = (double)(iband+1); + + /* Write band description */ + CHK(fwrite(&low, sizeof(low), 1, fp) == 1); + CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); + } + + /* Write per band ks and ka */ + FOR_EACH(iband, 0, nbands) { + uint64_t inode; + + /* Padding */ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET)==0); + + FOR_EACH(inode, 0, nnodes) { + const float ks = (float)(iband*2000 + inode); + CHK(fwrite(&ks, sizeof(ks), 1, fp) == 1); + } + + /* Padding */ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize), SEEK_SET)==0); + + FOR_EACH(inode, 0, nnodes) { + const float ka = (float)(iband*1000 + inode); + CHK(fwrite(&ka, sizeof(ka), 1, fp) == 1); + } + } + + /* Padding. Write one char to position the EOF indicator */ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); + CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); +} + +static void +test_load(struct sars* sars) +{ + FILE* fp = NULL; + const char* filename = "test_file.sars"; + const uint64_t pagesize = 16384; + const uint64_t nbands = 11; + const uint64_t nnodes = 1000; + + CHK(fp = fopen(filename, "w+")); + write_sars(fp, pagesize, nbands, nnodes); + rewind(fp); + + CHK(sars_load_stream(NULL, fp, filename) == RES_BAD_ARG); + CHK(sars_load_stream(sars, NULL, filename) == RES_BAD_ARG); + CHK(sars_load_stream(sars, fp, NULL) == RES_OK); + check_sars_load(sars, nbands, nnodes); + + rewind(fp); + CHK(sars_load_stream(sars, fp, filename) == RES_OK); + + CHK(sars_load(NULL, filename) == RES_BAD_ARG); + CHK(sars_load(sars, NULL) == RES_BAD_ARG); + CHK(sars_load(sars, "nop") == RES_IO_ERR); + CHK(sars_load(sars, filename) == RES_OK); + check_sars_load(sars, nbands, nnodes); + + CHK(fclose(fp) == 0); +} + +static void +test_load_fail(struct sars* sars) +{ + FILE* fp = NULL; + double low; + double upp; + + /* The pagesize is less than the operating system page size*/ + CHK(fp = tmpfile()); + write_sars(fp, 2048, 1, 1); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); + + /* The pagesize is not a power of two */ + CHK(fp = tmpfile()); + write_sars(fp, 4100, 1, 1); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); + + /* Wrong #bands */ + CHK(fp = tmpfile()); + write_sars(fp, 4096, 0, 1); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); + + /* Wrong #nodes */ + CHK(fp = tmpfile()); + write_sars(fp, 4096, 1, 0); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); + + /* Wrong band boundaries */ + low = 1; + upp = 0; + CHK(fp = tmpfile()); + write_sars(fp, 4096, 1, 1); + CHK(fseek(fp, 24, SEEK_SET) == 0); + CHK(fwrite(&low, sizeof(low), 1, fp) == 1); + CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); + + /* Unsorted bands */ + CHK(fp = tmpfile()); + write_sars(fp, 4096, 2, 1); + CHK(fseek(fp, 24, SEEK_SET) == 0); + low = 1; upp = 2; + CHK(fwrite(&low, sizeof(low), 1, fp) == 1); + CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); + low = 0; upp = 1; + CHK(fwrite(&low, sizeof(low), 1, fp) == 1); + CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); + + /* Bands overlap */ + CHK(fp = tmpfile()); + write_sars(fp, 4096, 2, 1); + CHK(fseek(fp, 24, SEEK_SET) == 0); + low = 0; upp = 1; + CHK(fwrite(&low, sizeof(low), 1, fp) == 1); + CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); + low = 0.5; upp = 1.5; + CHK(fwrite(&low, sizeof(low), 1, fp) == 1); + CHK(fwrite(&upp, sizeof(upp), 1, fp) == 1); + rewind(fp); + CHK(sars_load_stream(sars, fp, NULL) == RES_BAD_ARG); + CHK(fclose(fp) == 0); +} + +static void +test_load_files(struct sars* sars, int argc, char** argv) +{ + int i; + CHK(sars); + FOR_EACH(i, 1, argc) { + size_t nnodes; + size_t nbands; + size_t iband; + + printf("Load %s\n", argv[1]); + + CHK(sars_load(sars, argv[i]) == RES_OK); + nbands = sars_get_bands_count(sars); + nnodes = sars_get_nodes_count(sars); + CHK(nbands); + CHK(nnodes); + + FOR_EACH(iband, 0, nbands) { + struct sars_band band = SARS_BAND_NULL; + size_t inode; + + CHK(sars_get_band(sars, iband, &band) == RES_OK); + printf("band %lu in [%g, %g] nm\n", + (unsigned long)band.id, + band.lower, band.upper); + + CHK(band.lower == band.lower); /* !NaN */ + CHK(band.upper == band.upper); /* !NaN */ + CHK(band.lower < band.upper); + + FOR_EACH(inode, 0, nnodes) { + CHK(band.ks_list[inode] == band.ks_list[inode]); /* !NaN */ + CHK(band.ka_list[inode] == band.ka_list[inode]); /* !NaN */ + } + } + } +} + +/******************************************************************************* + * Main function + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct sars_create_args args = SARS_CREATE_ARGS_DEFAULT; + struct sars* sars = NULL; + (void)argc, (void)argv; + + args.verbose = 1; + CHK(sars_create(&args, &sars) == RES_OK); + + test_load(sars); + test_load_fail(sars); + test_load_files(sars, argc, argv); + + CHK(sars_ref_put(sars) == RES_OK); + CHK(mem_allocated_size() == 0); + return 0; +}