From 84beba1d1beebf350c0cc61fa78a1160555e2e4e Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 17 Aug 2026 16:11:54 -0700 Subject: [PATCH 1/5] WIP: adding file_t test --- test/driver.F90 | 2 + test/modules/file_test_m.F90 | 94 ++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/modules/file_test_m.F90 diff --git a/test/driver.F90 b/test/driver.F90 index c1800afec..f7651c671 100644 --- a/test/driver.F90 +++ b/test/driver.F90 @@ -16,6 +16,7 @@ program test_suite_driver use character_stop_code_test_m ,only : character_stop_code_test_t #endif use command_line_test_m ,only : command_line_test_t + use file_test_m ,only : file_test_t use formats_test_m ,only : formats_test_t use multi_image_test_m ,only : multi_image_test_t, multi_image_setup use string_test_m ,only : string_test_t @@ -40,6 +41,7 @@ program test_suite_driver ,test_fixture_t( test_description_test_t()) & ,test_fixture_t( test_diagnosis_test_t()) & ,test_fixture_t( test_result_test_t()) & + ,test_fixture_t( file_test_t()) & ,test_fixture_t( command_line_test_t()) & ])) call test_harness%report_results diff --git a/test/modules/file_test_m.F90 b/test/modules/file_test_m.F90 new file mode 100644 index 000000000..cfea69787 --- /dev/null +++ b/test/modules/file_test_m.F90 @@ -0,0 +1,94 @@ +! Copyright (c) 2024-2025, The Regents of the University of California and Sourcery Institute +! Terms of use are as specified in LICENSE.txt + +#include "language-support.F90" + +module file_test_m + !! Check data partitioning across files + use julienne_m, only : & + file_t & + ,operator(.all.) & + ,operator(.equalsExpected.) & + ,passing_test & + ,string_t & + ,test_description_t & + ,test_diagnosis_t & + ,test_result_t & + ,test_t & + ,usher + use assert_m, only : assert + implicit none + + private + public :: file_test_t + + type, extends(test_t) :: file_test_t + contains + procedure, nopass :: subject + procedure, nopass :: results + end type + +contains + + pure function subject() result(specimen) + character(len=:), allocatable :: specimen + specimen = "A file_t object" + end function + + function results() result(test_results) + type(test_result_t), allocatable :: test_results(:) + type(test_description_t), allocatable :: test_descriptions(:) + type(file_test_t) file_test + + test_descriptions = [ & + test_description_t(string_t("reading a written file"), usher(check_write_then_read)) & + ] + test_results = file_test%run(test_descriptions) + end function + + function check_write_then_read() result(test_diagnosis) + !! Check that a written file can be read correctly + type(test_diagnosis_t) test_diagnosis + integer l + character(len=:), allocatable :: line + character(len=*), parameter :: file_name = "build/file_t-unit-test-data.txt" + + test_diagnosis = passing_test() + + associate(output_lines => [string_t("foo"), string_t("yada yada"), string_t("bar ")]) + associate(output_file => file_t(output_lines)) + + call output_file%write_lines() + call output_file%write_lines(file_name) + + associate(input_file => file_t(file_name)) + associate(input_lines => input_file%lines()) + + print '(a)', "-------><------" + do l = 1, size(input_lines) + print '(a)', input_lines(l)%string() + end do + print '(a)', "-------><------" + call input_file%write_lines() + + stop "-------> here <------" + + + !do l = 1, size(lines) + ! allocate(character(len=len(file%lines_(l)%string_)) :: line) + ! read(file%lines_(l)%string_, '(a)') line + ! line == lines(l) + ! deallocate(line) + !end do + + !test_diagnosis = .all. (output_lines .equalsExpected. input_lines) + test_diagnosis = all(output_lines == input_lines) + + end associate + end associate + end associate + end associate + + end function + +end module file_test_m From 52405d329b718be95b17ccf8ad9465ac94803e9a Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 17 Aug 2026 18:36:30 -0700 Subject: [PATCH 2/5] test(file_t): check file write/read --- src/julienne/julienne_file_s.F90 | 12 ++++++++++-- test/modules/file_test_m.F90 | 31 +++++++++---------------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/julienne/julienne_file_s.F90 b/src/julienne/julienne_file_s.F90 index e243640eb..2772e5f69 100644 --- a/src/julienne/julienne_file_s.F90 +++ b/src/julienne/julienne_file_s.F90 @@ -26,16 +26,24 @@ module procedure write_to_character_file_name integer file_unit, l - logical file_open + logical file_open, i_opened call_assert(allocated(self%lines_)) inquire(file=file_name, opened=file_open, number=file_unit) - if (.not. file_open) open(newunit=file_unit, file=file_name, form='formatted', status='unknown', action='write') + + if (.not. file_open) then + open(newunit=file_unit, file=file_name, form='formatted', status='unknown', action='write') + i_opened = .true. + else + i_opened = .false. + end if do l = 1, size(self%lines_) write(file_unit, '(a)') self%lines_(l)%string() end do + + if (i_opened) close(file_unit) end procedure module procedure write_to_string_file_name diff --git a/test/modules/file_test_m.F90 b/test/modules/file_test_m.F90 index cfea69787..9e599cfea 100644 --- a/test/modules/file_test_m.F90 +++ b/test/modules/file_test_m.F90 @@ -8,6 +8,7 @@ module file_test_m use julienne_m, only : & file_t & ,operator(.all.) & + ,operator(.also.) & ,operator(.equalsExpected.) & ,passing_test & ,string_t & @@ -55,36 +56,22 @@ function check_write_then_read() result(test_diagnosis) test_diagnosis = passing_test() - associate(output_lines => [string_t("foo"), string_t("yada yada"), string_t("bar ")]) + associate(output_lines => [string_t("foo"), string_t(""), string_t("bar ")]) associate(output_file => file_t(output_lines)) - call output_file%write_lines() call output_file%write_lines(file_name) associate(input_file => file_t(file_name)) - associate(input_lines => input_file%lines()) - print '(a)', "-------><------" - do l = 1, size(input_lines) - print '(a)', input_lines(l)%string() - end do - print '(a)', "-------><------" - call input_file%write_lines() + !do l = 1, size(lines) + ! allocate(character(len=len(file%lines_(l)%string_)) :: line) + ! read(file%lines_(l)%string_, '(a)') line + ! line == lines(l) + ! deallocate(line) + !end do - stop "-------> here <------" + test_diagnosis = test_diagnosis .also. (.all. (input_file%lines() .equalsExpected. output_lines)) - - !do l = 1, size(lines) - ! allocate(character(len=len(file%lines_(l)%string_)) :: line) - ! read(file%lines_(l)%string_, '(a)') line - ! line == lines(l) - ! deallocate(line) - !end do - - !test_diagnosis = .all. (output_lines .equalsExpected. input_lines) - test_diagnosis = all(output_lines == input_lines) - - end associate end associate end associate end associate From e72703d213713159f9a0e3b41050b4274c60c1dc Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 17 Aug 2026 18:55:44 -0700 Subject: [PATCH 3/5] chore(file_test_m): rm commented code --- test/modules/file_test_m.F90 | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/modules/file_test_m.F90 b/test/modules/file_test_m.F90 index 9e599cfea..5cd637e8f 100644 --- a/test/modules/file_test_m.F90 +++ b/test/modules/file_test_m.F90 @@ -58,20 +58,9 @@ function check_write_then_read() result(test_diagnosis) associate(output_lines => [string_t("foo"), string_t(""), string_t("bar ")]) associate(output_file => file_t(output_lines)) - call output_file%write_lines(file_name) - associate(input_file => file_t(file_name)) - - !do l = 1, size(lines) - ! allocate(character(len=len(file%lines_(l)%string_)) :: line) - ! read(file%lines_(l)%string_, '(a)') line - ! line == lines(l) - ! deallocate(line) - !end do - test_diagnosis = test_diagnosis .also. (.all. (input_file%lines() .equalsExpected. output_lines)) - end associate end associate end associate From 224da8ff771e54dc71581111fff400efffe27516 Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 17 Aug 2026 18:56:30 -0700 Subject: [PATCH 4/5] fix(file_t): work around lfortran issue --- src/julienne/julienne_file_s.F90 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/julienne/julienne_file_s.F90 b/src/julienne/julienne_file_s.F90 index 2772e5f69..813049b21 100644 --- a/src/julienne/julienne_file_s.F90 +++ b/src/julienne/julienne_file_s.F90 @@ -78,12 +78,22 @@ allocate(file_object%lines_(num_lines)) + read_and_store_lines: & do line_num = 1, num_lines +#ifdef __LFORTRAN__ + if (lengths(line_num)==0) then + file_object%lines_(line_num) = string_t("") + if (allocated(line)) deallocate(line) + allocate(character(len=1) :: line) + read(file_unit, '(a)') line + cycle read_and_store_lines + end if +#endif + if (allocated(line)) deallocate(line) allocate(character(len=lengths(line_num)) :: line) read(file_unit, '(a)') line file_object%lines_(line_num) = string_t(line) - deallocate(line) - end do + end do read_and_store_lines end associate From 9dbe068a7320e89653d9d33b2552ef0290b13085 Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Mon, 17 Aug 2026 23:01:54 -0700 Subject: [PATCH 5/5] chore(file_test_m): rm unneeded declarations --- test/modules/file_test_m.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/modules/file_test_m.F90 b/test/modules/file_test_m.F90 index 5cd637e8f..6d2194cd9 100644 --- a/test/modules/file_test_m.F90 +++ b/test/modules/file_test_m.F90 @@ -50,8 +50,6 @@ function results() result(test_results) function check_write_then_read() result(test_diagnosis) !! Check that a written file can be read correctly type(test_diagnosis_t) test_diagnosis - integer l - character(len=:), allocatable :: line character(len=*), parameter :: file_name = "build/file_t-unit-test-data.txt" test_diagnosis = passing_test()