solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit de77d2e416a9b55c0376db6bbf1f69bc2bd7ddd7
parent 1c1f0e99609e926ba6073a7aa33fcc18b08fd0cc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu,  9 Mar 2017 14:39:43 +0100

Major refactoring & rewrite of the test_model project

Transform the test_model sub-project into a solstice test and rename it
in test_solstice_simulation. Replace the error managements by CHECK
directives. Provide the path toward the solstice program as an argument
of the test. In order to handle multiple build configurations, this path
is dynamically resolved by the build system.

Diffstat:
Mcmake/CMakeLists.txt | 17++++++++++++++++-
Dcmake/test_model/CMakeLists.txt | 57---------------------------------------------------------
Dsrc/test_model/test_model.c | 373-------------------------------------------------------------------------------
Asrc/test_solstice_simulation.c | 327+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 343 insertions(+), 431 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -59,7 +59,6 @@ include_directories( ################################################################################ add_subdirectory(parser) add_subdirectory(receivers) -add_subdirectory(test_model) ################################################################################ # Generate files @@ -140,6 +139,22 @@ if(NOT NO_TEST) new_test(test_solstice_args) + build_test(test_solstice_simulation) + function(add_test_simulation _name) + add_test(NAME test_solstice_simulation_${_name} + COMMAND test_solstice_simulation + $<TARGET_FILE:solstice> + ${SOLSTICE_SOURCE_DIR}/../yaml/ + ${_name}) + endfunction() + + add_test_simulation(beam_down) + add_test_simulation(test01) + add_test_simulation(test02) + add_test_simulation(test03) + add_test_simulation(test04) + add_test_simulation(test05) + endif() ################################################################################ diff --git a/cmake/test_model/CMakeLists.txt b/cmake/test_model/CMakeLists.txt @@ -1,57 +0,0 @@ -# Copyright (C) CNRS 2016-2017 -# -# This program is free software: you can redistribute 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 distributed 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/>. - -cmake_minimum_required(VERSION 2.8) -project(test_model C) - -set(TESTMODEL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/test_model) - -################################################################################ -# Define include directories -################################################################################ -include_directories( - ${LibYAML_INCLUDE_DIR} - ${RSys_INCLUDE_DIR} - ${TESTMODEL_SOURCE_DIR}/../) - -################################################################################ -# Configure and define targets -################################################################################ -set(TESTMODEL_FILES_SRC - test_model.c) - -# Prepend each file in the `TESTMODEL_FILES_<SRC|INC>' list by `TESTMODEL_SOURCE_DIR' -rcmake_prepend_path(TESTMODEL_FILES_SRC ${TESTMODEL_SOURCE_DIR}) - -if(CMAKE_COMPILER_IS_GNUCC) - set(MATH_LIB m) -endif() - -add_executable(test_model ${TESTMODEL_FILES_SRC}) - -################################################################################ -# Tests -################################################################################ -if(NOT NO_TEST) - add_test(test_beam_down test_model beam_down) - add_test(test_01 test_model test01) - add_test(test_02 test_model test02) - add_test(test_03 test_model test03) - add_test(test_04 test_model test04) - add_test(test_05 test_model test05) - - rcmake_copy_runtime_libraries(test_model) - -endif() diff --git a/src/test_model/test_model.c b/src/test_model/test_model.c @@ -1,373 +0,0 @@ -/* Copyright (C) CNRS 2016-2017 -* -* This program is free software: you can redistribute 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 distributed 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 <rsys/rsys.h> -#include <rsys/math.h> - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#ifdef COMPILER_CL - /* Wrap POSIX functions and constants */ - #include <io.h> - #define fdopen _fdopen - #define fileno _fileno - #define execvp _execvp -#endif - -#ifndef COMPILER_CL -#include <linux/limits.h> /* MAX_PATH */ -#endif - -enum side { - FRONT, - BACK -}; - -enum RESULTS { - FRONT_INTEGRATED_IRRADIANCE, - BACK_INTEGRATED_IRRADIANCE, - FRONT_REFLECTIVITY_LOSS, - BACK_REFLECTIVITY_LOSS, - FRONT_ABSORPTIVITY_LOSS, - BACK_ABSORPTIVITY_LOSS, - FRONT_COS_LOSS, - BACK_COS_LOSS, - FRONT_EFFICIENCY, - BACK_EFFICIENCY, - MAX_RESULTS_COUNT__ -}; - -static int -file_exists(const char* name) -{ - FILE* f = fopen(name, "r"); - if (!f) return 0; - fclose(f); - return 1; -} - -#define MAX_LINE_LEN 2048 - -static const char -sundir_header [] = "#--- Sun direction:"; - -#define IS_NEW_BLOC(Line, Header) (!strncmp((Line), (Header), strlen(Header))) - -static res_T -get_dir_and_counts - (FILE* ref_file, - double sun_angles[2], - size_t* recv_count, - size_t* realisation_count) -{ - char line[MAX_LINE_LEN]; - - ASSERT(ref_file && sun_angles); - if (!fgets(line, sizeof(line), ref_file)) return RES_BAD_ARG; - if (!IS_NEW_BLOC(line, sundir_header)) - return RES_BAD_ARG; - /* get sun dir */ - if (2 != sscanf(line + strlen(sundir_header), - "%lg%lg", &sun_angles[0], &sun_angles[1])) { - return RES_BAD_ARG; - } - /* get sun dir */ - if (!fgets(line, sizeof(line), ref_file)) return RES_BAD_ARG; - if (2 != sscanf(line, "%zu%zu", recv_count, realisation_count)) - return RES_BAD_ARG; - return RES_OK; -} - -#define READ_RECV(Name, Values, Std) \ -{ \ - if (2 * MAX_RESULTS_COUNT__ + 1 \ - != sscanf(line, \ - "%s%*zu%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg", \ - Name, \ - &Values[FRONT_INTEGRATED_IRRADIANCE], &Std[FRONT_INTEGRATED_IRRADIANCE], \ - &Values[BACK_INTEGRATED_IRRADIANCE], &Std[BACK_INTEGRATED_IRRADIANCE], \ - &Values[FRONT_REFLECTIVITY_LOSS], &Std[FRONT_REFLECTIVITY_LOSS], \ - &Values[BACK_REFLECTIVITY_LOSS], &Std[BACK_REFLECTIVITY_LOSS], \ - &Values[FRONT_ABSORPTIVITY_LOSS], &Std[FRONT_ABSORPTIVITY_LOSS], \ - &Values[BACK_ABSORPTIVITY_LOSS], &Std[BACK_ABSORPTIVITY_LOSS], \ - &Values[FRONT_COS_LOSS], &Std[FRONT_COS_LOSS], \ - &Values[BACK_COS_LOSS], &Std[BACK_COS_LOSS], \ - &Values[FRONT_EFFICIENCY], &Std[FRONT_EFFICIENCY], \ - &Values[BACK_EFFICIENCY], &Std[BACK_EFFICIENCY]) \ - ) \ - { \ - res = RES_BAD_ARG; \ - goto error; \ - } \ -} - -#define POSITIVE_OR_M_ONE(x) ((x) == -1 || (x) >= 0) - -static FINLINE int -is_compatible_with - (const double ref_E, - const double ref_SE, - const double test_E, - const double test_SE) -{ - double SE; - ASSERT(POSITIVE_OR_M_ONE(ref_E) && POSITIVE_OR_M_ONE(ref_SE) - && POSITIVE_OR_M_ONE(test_E) && POSITIVE_OR_M_ONE(test_SE)); - if (ref_E == -1) { - ASSERT(ref_SE == -1); - return (test_E == -1 && test_SE == -1); - } - ASSERT(ref_SE != -1); - SE = ref_SE > 0 ? 2 * ref_SE : (ref_E > 0 ? ref_E * 1e-6 : 1e-6); - return (fabs(ref_E - test_E) <= SE && test_SE <= SE); -} - -static res_T -check_1_reference - (FILE* tested_file, - const char* rcv_name, - const double* reference_E, - const double* reference_SE) -{ - res_T res = RES_OK; - ASSERT(tested_file && rcv_name && reference_E && reference_SE); - double a[2]; - size_t c1, c2; - - res = get_dir_and_counts(tested_file, a, &c1, &c2); /* skip headers */ - if (res != RES_OK) goto error; - while(!feof(tested_file)) { - char line[MAX_LINE_LEN]; - char tested_rcv_name[MAX_LINE_LEN]; - double tested_E[MAX_RESULTS_COUNT__], tested_SE[MAX_RESULTS_COUNT__]; - enum RESULTS r; - if (!fgets(line, sizeof(line), tested_file)) { - res = RES_BAD_ARG; - goto error; - } - READ_RECV(tested_rcv_name, tested_E, tested_SE); - if (strcmp(rcv_name, tested_rcv_name)) continue; - for (r = FRONT_INTEGRATED_IRRADIANCE; r < MAX_RESULTS_COUNT__; r++) { - if (!is_compatible_with - (reference_E[r], reference_SE[r], tested_E[r], tested_SE[r])) - { - res = RES_BAD_ARG; - goto error; - } - } - goto end; /* success */ - } - res = RES_BAD_ARG; /* could not find data */ -end: - return res; -error: - goto end; -} - -static res_T -check_1_global - (FILE* tested_file, - const double reference_E, - const double reference_SE, - const unsigned rank) -{ - res_T res = RES_OK; - char line[MAX_LINE_LEN]; - double a[2]; - size_t recv_count, r2; - unsigned i; - int nb; - double tested_E, tested_SE; - - res = get_dir_and_counts(tested_file, a, &recv_count, &r2); - if (res != RES_OK) goto error; - /* skip receivers */ - for ( ; recv_count--; ) { - if (!fgets(line, sizeof(line), tested_file)) { - res = RES_BAD_ARG; - goto error; - } - } - /* read the rank th global data */ - for (i = 0; i <= rank; i++) { - if (!fgets(line, sizeof(line), tested_file)) { - res = RES_BAD_ARG; - goto error; - } - } - nb = sscanf(line, "%lg%lg", &tested_E, &tested_SE); - if (nb != 2) { - res = RES_BAD_ARG; - goto error; - } - if (!is_compatible_with - (reference_E, reference_SE, tested_E, tested_SE)) { - res = RES_BAD_ARG; - goto error; - } - -end: - return res; -error: - goto end; -} - -static res_T -check_references - (FILE* ref_file, const char* tested_file_name) -{ - res_T res = RES_OK; - char line[MAX_LINE_LEN]; - int nb_global = 0; - FILE* tested_file; - - ASSERT(ref_file && tested_file_name); - tested_file = fopen(tested_file_name, "r"); - if (!tested_file) { - res = RES_IO_ERR; - goto error; - } - for ( ; ; ) { - int nb = 0; - double val, std; - fpos_t pos; - - CHECK(fgetpos(ref_file, &pos), 0); - if (!fgets(line, sizeof(line), ref_file)) { - if (feof(ref_file)) goto end; - res = RES_BAD_ARG; - goto error; - } - if (IS_NEW_BLOC(line, sundir_header)) { - /* keep the header as a part of the following bloc */ - CHECK(fsetpos(ref_file, &pos), 0); - goto end; - } - nb = sscanf(line, "%lg%lg", &val, &std); - if (nb == EOF) goto end; - rewind(tested_file); - ASSERT(nb == 0 || nb == 2); - if (nb != 0) { - res = check_1_global(tested_file, val, std, nb_global); - if (res != RES_OK) goto error; - nb_global++; - } - else { - char ref_name[MAX_LINE_LEN]; - double reference_E[MAX_RESULTS_COUNT__], reference_SE[MAX_RESULTS_COUNT__]; - READ_RECV(ref_name, reference_E, reference_SE); - res = - check_1_reference(tested_file, ref_name, reference_E, reference_SE); - if (res != RES_OK) goto error; - } - }; - -end: - if (tested_file) CHECK(fclose(tested_file), 0); - CHECK(remove(tested_file_name), 0); - return res; -error: - goto end; -} - -static FINLINE res_T -create_tmp_file_name(char* out_name) -{ - ASSERT(out_name); -#ifdef COMPILER_CL - if (tmpnam_s(out_name, L_tmpnam_s)) return RES_IO_ERR; -#else - int fd; - strncpy(out_name, "solstice_tmp_file_XXXXXX", L_tmpnam_s); - fd = mkstemp(out_name); - if (-1 == fd) return RES_IO_ERR; - /* just want a name */ - close(fd); -#endif - return RES_OK; -} - -static res_T -do_check(const char* base_name) -{ - res_T res = RES_OK; - FILE* ref_file; - char ref_file_name[MAX_PATH]; - size_t c1, realisation_count; - const char* dir = "../../yaml/"; - - ASSERT(base_name); - snprintf(ref_file_name, MAX_PATH, "%s%s.ref", dir, base_name); - ref_file = fopen(ref_file_name, "r"); - if (!ref_file) { - res = RES_IO_ERR; - printf("Cannot open file '%s'\n", base_name); - goto end; - } - while (!feof(ref_file)) { - char cmd[128 + 3 * MAX_PATH]; - double sun_angles[2]; - char tested_file_name[L_tmpnam_s]; -#ifdef COMPILER_CL - const char* exe_name = "..\\Debug\\solstice.exe"; -#else - const char* exe_name = "../Debug/solstice.exe"; -#endif - - res = get_dir_and_counts(ref_file, sun_angles, &c1, &realisation_count); - if (res != RES_OK) goto end; - - res = create_tmp_file_name(tested_file_name); - if (res != RES_OK) goto end; - - snprintf(cmd, sizeof(cmd), - "%s -o %s -f -D %g,%g -n %zu -R %s%s_receiver.yaml %s%s.yaml", - exe_name, tested_file_name, SPLIT2(sun_angles), realisation_count, - dir, base_name, dir, base_name); - if (system(cmd)) { - res = RES_BAD_ARG; - goto end; - } - res = check_references(ref_file, tested_file_name); - if (res != RES_OK) { - goto end; - } - } -end: - if (ref_file) fclose(ref_file); - return res; -} - -int -main(int argc, char** argv) -{ - int err = 0; - - if (argc != 2) goto usage; - - if (RES_OK != do_check(argv[1])) - goto error; - -exit: - return err; -usage: - printf("Usage: %s <file_base_name>\n", argv[0]); -error: - err = 1; - goto exit; -} - diff --git a/src/test_solstice_simulation.c b/src/test_solstice_simulation.c @@ -0,0 +1,327 @@ +/* Copyright (C) CNRS 2016-2017 + * + * This program is free software: you can redistribute 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 distributed 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/>. */ + +#define _POSIX_C_SOURCE 200809L /* mkstemp support */ + +#include <rsys/rsys.h> +#include <rsys/math.h> + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef COMPILER_CL + /* Wrap POSIX functions and constants */ + #include <io.h> + #define fdopen _fdopen +#endif + +enum side { + FRONT, + BACK +}; + +enum result_type { + FRONT_INTEGRATED_IRRADIANCE, + BACK_INTEGRATED_IRRADIANCE, + FRONT_REFLECTIVITY_LOSS, + BACK_REFLECTIVITY_LOSS, + FRONT_ABSORPTIVITY_LOSS, + BACK_ABSORPTIVITY_LOSS, + FRONT_COS_LOSS, + BACK_COS_LOSS, + FRONT_EFFICIENCY, + BACK_EFFICIENCY, + MAX_RESULTS_COUNT__ +}; + +#define MAX_LINE_LEN 2048 + +static const char +sundir_header [] = "#--- Sun direction:"; + +#define IS_NEW_BLOCK(Line, Header) (!strncmp((Line), (Header), strlen(Header))) + +static int +read_line(char* line, size_t max_line_len, FILE* stream) +{ + ASSERT(stream && line && max_line_len); + line = fgets(line, (int)max_line_len, stream); + if(!line) return 0; + CHECK(strlen(line) + 1 < max_line_len, 1); + return 1; +} + +static void +get_dir_and_counts + (FILE* ref_file, + double angles[2], + unsigned long* recv_count, + unsigned long* realisation_count) +{ + char line[MAX_LINE_LEN]; + int n; + + NCHECK(ref_file, NULL); + NCHECK(angles, NULL); + NCHECK(recv_count, NULL); + NCHECK(realisation_count, NULL); + + /* Get sun dir */ + CHECK(read_line(line, sizeof(line), ref_file), 1); + CHECK(IS_NEW_BLOCK(line, sundir_header), 1); + n = sscanf(line+strlen(sundir_header), "%lg%lg", &angles[0], &angles[1]); + CHECK(n, 2); + + /* Get #receivers and #realisations */ + CHECK(read_line(line, sizeof(line), ref_file), 1); + n = sscanf(line, "%lu%lu", recv_count, realisation_count); + CHECK(n, 2); +} + +static void +read_recv(const char* line, char name[], double E[], double SE[]) +{ + int n; + + NCHECK(line, NULL); + NCHECK(name, NULL); + NCHECK(E, NULL); + NCHECK(SE, NULL); + + n = sscanf(line, + "%s%*u%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg", + name, + &E[FRONT_INTEGRATED_IRRADIANCE], &SE[FRONT_INTEGRATED_IRRADIANCE], + &E[BACK_INTEGRATED_IRRADIANCE], &SE[BACK_INTEGRATED_IRRADIANCE], + &E[FRONT_REFLECTIVITY_LOSS], &SE[FRONT_REFLECTIVITY_LOSS], + &E[BACK_REFLECTIVITY_LOSS], &SE[BACK_REFLECTIVITY_LOSS], + &E[FRONT_ABSORPTIVITY_LOSS], &SE[FRONT_ABSORPTIVITY_LOSS], + &E[BACK_ABSORPTIVITY_LOSS], &SE[BACK_ABSORPTIVITY_LOSS], + &E[FRONT_COS_LOSS], &SE[FRONT_COS_LOSS], + &E[BACK_COS_LOSS], &SE[BACK_COS_LOSS], + &E[FRONT_EFFICIENCY], &SE[FRONT_EFFICIENCY], + &E[BACK_EFFICIENCY], &SE[BACK_EFFICIENCY]); + + CHECK(n, 2*MAX_RESULTS_COUNT__+1); +} + +#define POSITIVE_OR_M_ONE(x) ((x) == -1 || (x) >= 0) + +static FINLINE int +is_compatible_with + (const double ref_E, + const double ref_SE, + const double test_E, + const double test_SE) +{ + double SE; + + CHECK(POSITIVE_OR_M_ONE(ref_E), 1); + CHECK(POSITIVE_OR_M_ONE(ref_SE), 1); + CHECK(POSITIVE_OR_M_ONE(test_E), 1); + CHECK(POSITIVE_OR_M_ONE(test_SE), 1); + + if(ref_E == -1) { + CHECK(ref_SE, -1); + return (test_E == -1 && test_SE == -1); + } + + NCHECK(ref_SE, -1); + SE = ref_SE > 0 ? 2 * ref_SE : (ref_E > 0 ? ref_E * 1e-6 : 1e-6); + return (fabs(ref_E - test_E) <= SE && test_SE <= SE); +} + +static void +check_1_reference + (FILE* tested_file, + const char* rcv_name, + const double* reference_E, + const double* reference_SE) +{ + double a[2]; + size_t c1, c2; + int found = 0; + + NCHECK(tested_file, NULL); + NCHECK(rcv_name, NULL); + NCHECK(reference_E, NULL); + NCHECK(reference_SE, NULL); + + get_dir_and_counts(tested_file, a, &c1, &c2); /* Skip headers */ + + while(!feof(tested_file) && !found) { + char line[MAX_LINE_LEN]; + char tested_rcv_name[MAX_LINE_LEN]; + double tested_E[MAX_RESULTS_COUNT__], tested_SE[MAX_RESULTS_COUNT__]; + enum result_type r; + + CHECK(read_line(line, sizeof(line), tested_file), 1); + + read_recv(line, tested_rcv_name, tested_E, tested_SE); + if(strcmp(rcv_name, tested_rcv_name)) continue; + + FOR_EACH(r, FRONT_INTEGRATED_IRRADIANCE, MAX_RESULTS_COUNT__) { + CHECK(is_compatible_with + (reference_E[r], reference_SE[r], tested_E[r], tested_SE[r]), 1); + } + found = 1; + } + CHECK(found, 1); +} + +static void +check_1_global + (FILE* tested_file, + const double reference_E, + const double reference_SE, + const unsigned rank) +{ + char line[MAX_LINE_LEN]; + double a[2]; + size_t recv_count, r2; + unsigned i; + int nb; + double tested_E, tested_SE; + + get_dir_and_counts(tested_file, a, &recv_count, &r2); + + /* Skip receivers */ + while(recv_count--) CHECK(read_line(line, sizeof(line), tested_file), 1); + + /* Read the rank th global data */ + FOR_EACH(i, 0, rank+1) CHECK(read_line(line, sizeof(line), tested_file), 1); + + nb = sscanf(line, "%lg%lg", &tested_E, &tested_SE); + CHECK(nb, 2); + CHECK(is_compatible_with(reference_E, reference_SE, tested_E, tested_SE), 1); +} + +static void +check_references(FILE* ref_file, FILE* tested_file) +{ + char line[MAX_LINE_LEN]; + unsigned nb_global = 0; + fpos_t pos; + + NCHECK(ref_file, NULL); + NCHECK(tested_file, NULL); + + CHECK(fgetpos(ref_file, &pos), 0); + while(read_line(line, sizeof(line), ref_file)) { + double val, std; + int nb = 0; + + if(IS_NEW_BLOCK(line, sundir_header)) { + /* Keep the header as a part of the following block */ + CHECK(fsetpos(ref_file, &pos), 0); + break; + } + + nb = sscanf(line, "%lg%lg", &val, &std); + CHECK(nb == 0 || nb == 2, 1); + + rewind(tested_file); + if(nb != 0) { + check_1_global(tested_file, val, std, nb_global); + nb_global++; + } else { + char ref_name[MAX_LINE_LEN]; + double reference_E[MAX_RESULTS_COUNT__]; + double reference_SE[MAX_RESULTS_COUNT__]; + read_recv(line, ref_name, reference_E, reference_SE); + check_1_reference(tested_file, ref_name, reference_E, reference_SE); + } + + CHECK(fgetpos(ref_file, &pos), 0); + } +} + +static FINLINE int +create_tmp_file_name(char* name, const size_t max_sizeof_name) +{ + const char* template = "solstice_tmp_file_XXXXXX"; + int fd; + NCHECK(name, NULL); + CHECK(strlen(template)+1 <= max_sizeof_name-1, 1); + strcpy(name, template); + fd = mkstemp(name); + NCHECK(fd, -1); + return fd; +} + +static void +do_check(const char* binary, const char* dir, const char* base_name) +{ + char ref_file_name[128]; + FILE* ref_file; + unsigned long c1, realisation_count; + int n; + ASSERT(base_name); + + n = snprintf(ref_file_name, sizeof(ref_file_name), "%s%s.ref", dir, base_name); + CHECK((size_t)n < sizeof(ref_file_name), 1); + + ref_file = fopen(ref_file_name, "r"); + NCHECK(ref_file, NULL); + + while(!feof(ref_file)) { + char cmd[512]; + char tested_file_name[128]; + double sun_angles[2]; + FILE* fp = NULL; + int fd = -1; + + get_dir_and_counts(ref_file, sun_angles, &c1, &realisation_count); + + fd = create_tmp_file_name(tested_file_name, sizeof(tested_file_name)); + fp = fdopen(fd, "r"); + NCHECK(fp, NULL); + + n = snprintf(cmd, sizeof(cmd), + "%s -o %s -f -D %g,%g -n %lu -R %s%s_receiver.yaml %s%s.yaml", + binary, tested_file_name, SPLIT2(sun_angles), realisation_count, + dir, base_name, dir, base_name); + CHECK((unsigned)n < sizeof(cmd), 1); + + CHECK(system(cmd), RES_OK); + + check_references(ref_file, fp); + + fclose(fp); + remove(tested_file_name); + } +} + +int +main(int argc, char** argv) +{ + int err = 0; + + if(argc != 4) { + printf("Usage: %s <solstice-binary> <file-path> <file-base-name>\n", argv[0]); + goto error; + } + + do_check(argv[1], argv[2], argv[3]); + +exit: + return err; +error: + err = 1; + goto exit; +} +