Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yaml parser error checking #1563

Merged
merged 2 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions parser/yaml_parser.F90
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,24 @@ module yaml_parser_mod
module procedure get_value_from_key_1d
end interface get_value_from_key

!! Error codes from open_and_parse_file_wrap
integer, parameter :: MISSING_FILE = -1 !< Error code if the yaml file is missing
integer, parameter :: PARSER_INIT_ERROR = -2 !< Error code if unable to create a parser object
integer, parameter :: INVALID_YAML = -3 !< Error code if unable to parse a yaml file
integer, parameter :: SUCCESSFUL = 1 !< "Error" code if the parsing was successful

!> @brief c functions binding
!> @ingroup yaml_parser_mod
interface

!> @brief Private c function that opens and parses a yaml file (see yaml_parser_binding.c)
!! @return Flag indicating if the read was successful
function open_and_parse_file_wrap(filename, file_id) bind(c) &
result(success)
result(error_code)
use iso_c_binding, only: c_char, c_int, c_bool
character(kind=c_char), intent(in) :: filename(*) !< Filename of the yaml file
integer(kind=c_int), intent(out) :: file_id !< File id corresponding to the yaml file that was opened
logical(kind=c_bool) :: success !< Flag indicating if the read was successful
logical(kind=c_int) :: error_code !< Flag indicating the error message (1 if sucessful)
end function open_and_parse_file_wrap

!> @brief Private c function that checks if a file_id is valid (see yaml_parser_binding.c)
Expand Down Expand Up @@ -240,7 +246,7 @@ function open_and_parse_file(filename) &
result(file_id)

character(len=*), intent(in) :: filename !< Filename of the yaml file
logical :: success !< Flag indicating if the read was successful
integer :: error_code !< Flag indicating any errors in the parsing or 1 if sucessful
logical :: yaml_exists !< Flag indicating whether the yaml exists

integer :: file_id
Expand All @@ -251,11 +257,28 @@ function open_and_parse_file(filename) &
call mpp_error(NOTE, "The yaml file:"//trim(filename)//" does not exist, hopefully this is your intent!")
return
end if
success = open_and_parse_file_wrap(trim(filename)//c_null_char, file_id)
if (.not. success) call mpp_error(FATAL, "Error opening the yaml file:"//trim(filename)//". Check the file!")
error_code = open_and_parse_file_wrap(trim(filename)//c_null_char, file_id)
call check_error_code(error_code, filename)

end function open_and_parse_file

!> @brief Checks the error code from a open_and_parse_file_wrap function call
subroutine check_error_code(error_code, filename)
integer, intent(in) :: error_code
character(len=*), intent(in) :: filename

select case (error_code)
case (SUCCESSFUL)
return
case (MISSING_FILE)
call mpp_error(FATAL, "Error opening the yaml file:"//trim(filename))
case (PARSER_INIT_ERROR)
call mpp_error(FATAL, "Error initializing the parser for the file:"//trim(filename))
case (INVALID_YAML)
call mpp_error(FATAL, "Error parsing the file:"//trim(filename)//". Check that your yaml file is valid")
end select
end subroutine check_error_code

!> @brief Gets the key from a file id
subroutine get_key_name(file_id, key_id, key_name)
integer, intent(in) :: key_id !< Id of the key-value pair of interest
Expand Down
12 changes: 7 additions & 5 deletions parser/yaml_parser_binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ bool is_valid_file_id(int *file_id)

/* @brief Private c function that opens and parses a yaml file and saves it in a struct
@return Flag indicating if the read was sucessful */
bool open_and_parse_file_wrap(char *filename, int *file_id)
int open_and_parse_file_wrap(char *filename, int *file_id)
{
yaml_parser_t parser;
yaml_token_t token;
Expand Down Expand Up @@ -330,9 +330,9 @@ bool open_and_parse_file_wrap(char *filename, int *file_id)

/* printf("Opening file: %s.\nThere are %i files opened.\n", filename, j); */
file = fopen(filename, "r");
if (file == NULL) return false;
if (file == NULL) return -1;

if(!yaml_parser_initialize(&parser)) return false;
if(!yaml_parser_initialize(&parser)) return -2;

my_files.files[j].keys = (key_value_pairs*)calloc(1, sizeof(key_value_pairs));

Expand All @@ -341,7 +341,9 @@ bool open_and_parse_file_wrap(char *filename, int *file_id)
/* Set input file */
yaml_parser_set_input_file(&parser, file);
do {
yaml_parser_scan(&parser, &token);
if (!yaml_parser_scan(&parser, &token)) {
return -3;
}
switch(token.type)
{
case YAML_KEY_TOKEN:
Expand Down Expand Up @@ -420,7 +422,7 @@ bool open_and_parse_file_wrap(char *filename, int *file_id)
/* printf("closing file: %s\n", filename); */
fclose(file);

return true;
return 1;
}

#endif
2 changes: 1 addition & 1 deletion test_fms/parser/parser_demo.F90
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ program parser_demo
real(kind=r8_kind) :: r8_buffer !< Buffer to read r8 to

call fms_init
call fms_end

diag_yaml_id = open_and_parse_file("diag_table.yaml")
print *, ""
Expand Down Expand Up @@ -113,6 +112,7 @@ program parser_demo
print *, ""
enddo
deallocate(file_ids)
call fms_end

#endif
end program parser_demo
2 changes: 1 addition & 1 deletion test_fms/parser/parser_demo2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ program parser_demo
character(len=255) :: key_name !< The name of a key

call fms_init
call fms_end

diag_yaml_id = open_and_parse_file("diag_table.yaml")
print *, ""
Expand Down Expand Up @@ -102,6 +101,7 @@ program parser_demo
print *, ""
enddo
deallocate(file_ids)
call fms_end

#endif

Expand Down
37 changes: 36 additions & 1 deletion test_fms/parser/test_yaml_parser.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
. ../test-lib.sh

if [ ! -z $parser_skip ]; then
SKIP_TESTS='test_yaml_parser.[1-23]'
SKIP_TESTS='test_yaml_parser.[1-25]'
fi

touch input.nml
Expand Down Expand Up @@ -294,4 +294,39 @@ _EOF
test_expect_success "Generic blocks names" '
mpirun -n 1 ./generic_blocks
'

cat <<_EOF > diag_table.yaml
title: c384L49_esm5PIcontrol
baseDate: [1960 1 1 1 1 1 1]
diag_files:
- fileName: "atmos_daily"
freq: 24
frequnit: hours
timeunit: days
unlimdim: time
varlist:
- varName: tdata
reduction: False
module: mullions
mullions: 10
fill_value: -999.9
- varName: pdata
outName:pressure
reduction: False
kind: double
module: "moist"
- fileName: atmos_8xdaily
freq: 3
frequnit: hours
timeunit: days
unlimdim: time
varlist:
- varName: tdata
reduction: False
module: "moist"
_EOF

test_expect_failure "Use an invalid yaml" '
mpirun -n 1 ./parser_demo
'
test_done
Loading