From 8bf9c4402750e97b37db6ebc541830adbd64025f Mon Sep 17 00:00:00 2001 From: Abdallah Ammar Date: Fri, 15 Nov 2024 17:22:07 +0100 Subject: [PATCH] workflow for testing --- .github/workflows/compilation.yml | 35 ++++++++++++---------- .github/workflows/testing.yml | 37 +++++++++++++++++++++++ src/QuAcK/QuAcK.f90 | 2 +- src/test/init_test.f90 | 34 ++++++++++++++++----- tests/lunch_bench.py | 50 +++++++++++++++++++++---------- tests/work/.gitignore | 2 ++ 6 files changed, 121 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/testing.yml create mode 100644 tests/work/.gitignore diff --git a/.github/workflows/compilation.yml b/.github/workflows/compilation.yml index e1c6f12..b164328 100644 --- a/.github/workflows/compilation.yml +++ b/.github/workflows/compilation.yml @@ -11,27 +11,30 @@ on: jobs: - configuration: + build: runs-on: ubuntu-20.04 name: Dependencies steps: - - name: install dependencies - run: | - sudo apt install gfortran gcc liblapack-dev libblas-dev wget python3 make m4 pkg-config + - name: Checkout repository + uses: actions/checkout@v3 - compilation: - name: Compilation - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v3 - - name: Configuration - run: | - ./configure -i ninja || : - - name: Compilation - run: | - bash -c "source quack.rc ; cd src ; exec make" + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y gfortran gcc liblapack-dev libblas-dev wget python3 make m4 pkg-config + + - name: Configuration + run: | + ./configure -i ninja || : + - name: Compilation + run: | + bash -c "source quack.rc ; cd src ; make" + - name: Upload compiled binary + uses: actions/upload-artifact@v3 + with: + name: fortran-binary + path: ./bin/QuAcK diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 0000000..a9e16ba --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,37 @@ +name: QuAcK Testing + +on: + workflow_run: + workflows: ["QuAcK Compilation"] + types: + - completed + +jobs: + + test: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Download compiled binary from previous workflow + uses: actions/download-artifact@v3 + with: + name: fortran-binary + path: ./bin/QuAcK + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install pyscf + + - name: Run tests + run: | + bash -c "source quack.rc ; cd tests ; python lunch_bench.py -s light -t 1e-1" + diff --git a/src/QuAcK/QuAcK.f90 b/src/QuAcK/QuAcK.f90 index b58660c..586bfff 100644 --- a/src/QuAcK/QuAcK.f90 +++ b/src/QuAcK/QuAcK.f90 @@ -212,7 +212,7 @@ program QuAcK dotest = doRtest .or. doUtest .or. doGtest - if(dotest) call init_test(doRtest,doUtest,doGtest) + if(dotest) call init_test(working_dir,doRtest,doUtest,doGtest) !-------------------------! ! Restricted QuAcK branch ! diff --git a/src/test/init_test.f90 b/src/test/init_test.f90 index b5ef295..0a91e84 100755 --- a/src/test/init_test.f90 +++ b/src/test/init_test.f90 @@ -1,21 +1,41 @@ -subroutine init_test(doRtest,doUtest,doGtest) +subroutine init_test(working_dir,doRtest,doUtest,doGtest) implicit none ! Input variables - logical,intent(in) :: doRtest - logical,intent(in) :: doUtest - logical,intent(in) :: doGtest + character(len=256),intent(in) :: working_dir + logical,intent(in) :: doRtest + logical,intent(in) :: doUtest + logical,intent(in) :: doGtest ! Local variables + integer :: status + character(len=256) :: file_path + ! Output variables - if(doRtest) open(unit=1231597, file='test/Rtest.dat') + if(doRtest) then + file_path = trim(working_dir) // '/test/Rtest.dat' + open(unit=1231597, file=file_path, iostat=status) + if(status /= 0) then + print *, "Error opening file: ", file_path + stop + else + print *, "opening file successed" + endif + endif - if(doUtest) open(unit=1232584, file='test/Utest.dat') + if(doUtest) then + file_path = trim(working_dir) // '/test/Utest.dat' + open(unit=1232584, file=file_path) + endif - if(doGtest) open(unit=1234181, file='test/Gtest.dat') + if(doGtest) then + file_path = trim(working_dir) // '/test/Gtest.dat' + open(unit=1234181, file=file_path) + endif end subroutine + diff --git a/tests/lunch_bench.py b/tests/lunch_bench.py index 02d6db5..d73b369 100644 --- a/tests/lunch_bench.py +++ b/tests/lunch_bench.py @@ -57,11 +57,13 @@ parser.add_argument( default='light', help="Specify the type of data set: light (default), medium, or heavy." ) + +thresh_default = 1e-7 parser.add_argument( '-t', '--thresh', type=float, - default=1e-7, - help='Threshold for acceptable difference (default: 1e-8)' + default=thresh_default, + help='Threshold for acceptable difference, default = {}'.format(thresh_default) ) @@ -91,29 +93,32 @@ print("\n\n") class Quack_Job: - def __init__(self, mol, multip, basis, geom, methd): + def __init__(self, mol, multip, basis, geom, methd, workdir): self.mol = mol self.multip = multip self.basis = basis self.geom = geom self.methd = methd + self.workdir = workdir def prep_inp(self): # geometry - generate_xyz(self.geom, filename="{}/mol/{}.xyz".format(quack_root, self.mol)) + if not os.path.exists("{}/mol".format(self.workdir)): + os.makedirs("{}/mol".format(self.workdir)) + generate_xyz(self.geom, filename="{}/mol/{}.xyz".format(self.workdir, self.mol)) # input files for inp in ["methods", "options"]: inp_file = "{}.{}".format(inp, self.methd.upper()) if os.path.exists("inp/{}".format(inp_file)): shutil.copy("{}/tests/inp/{}".format(quack_root, inp_file), - "{}/input/{}".format(quack_root, inp)) + "{}/input/{}".format(self.workdir, inp)) else: print_col("File 'inp/{}' does not exist.".format(inp_file), "red") sys.exit(1) - def run(self, work_path): + def run(self): def display_spinner(): spinner = ['|', '/', '-', '\\'] @@ -137,13 +142,14 @@ class Quack_Job: command = [ 'python{}'.format(PYTHON_VERSION), 'PyDuck.py', + '--working_dir', '{}'.format(self.workdir), '-x', '{}'.format(self.mol), '-b', '{}'.format(self.basis), '-m', '{}'.format(self.multip) ] #print_col(f" $ {' '.join(command)}", "magenta") - file_out = "{}/{}/{}_{}_{}.out".format(work_path, self.methd, self.mol, self.multip, self.basis) + file_out = "{}/{}/{}_{}_{}.out".format(self.workdir, self.methd, self.mol, self.multip, self.basis) with open(file_out, 'w') as fobj: result = subprocess.run(command, stdout=fobj, stderr=subprocess.PIPE, text=True) if result.stderr: @@ -161,8 +167,8 @@ class Quack_Job: done_event.set() spinner_thread.join() - def check_data(self, data_ref): - filepath = '../test/Rtest.dat' + def check_data(self, data_ref, test_failed_): + filepath = '{}/test/Rtest.dat'.format(self.workdir) data_new = {} try: # read data_new @@ -177,12 +183,14 @@ class Quack_Job: for key in data_ref: if key not in data_new: print_col(f" 😐 {key} missing ⚠ī¸ ", "yellow") + test_failed_ = True else: diff = abs(data_new[key] - data_ref[key]) / (1e-15 + abs(data_ref[key])) if(diff <= THRESH): print_col(f" 🙂 {key}", "green") else: print_col(f" ☚ī¸ {key}: ❌ {data_ref[key]} ≠ {data_new[key]}", "red") + test_failed_ = True except FileNotFoundError: print_col(f"Error: The file '{filepath}' does not exist.", "red") sys.exit(1) @@ -201,6 +209,11 @@ def main(): work_path.mkdir(parents=True, exist_ok=True) print(f"Directory '{work_path}' created.\n") + # to save QuAcK output + if not os.path.exists("{}/test".format(work_path)): + os.makedirs("{}/test".format(work_path)) + + test_failed = False for mol in molecules: mol_name = mol.name @@ -225,19 +238,26 @@ def main(): work_methd = Path('{}/{}'.format(work_path, methd)) if not work_methd.exists(): work_methd.mkdir(parents=True, exist_ok=True) - - New_Quack_Job = Quack_Job(mol_name, mol_mult, basis_name, mol_geom, methd) + + New_Quack_Job = Quack_Job(mol_name, mol_mult, basis_name, mol_geom, methd, work_path) New_Quack_Job.prep_inp() - New_Quack_Job.run(work_path) - New_Quack_Job.check_data(basis_data) + New_Quack_Job.run() + + test_failed_ = False + New_Quack_Job.check_data(basis_data, test_failed_) + if (test_failed_): + test_failed = True print() print() print() - quit() + if test_failed: + sys.exit(1) + + sys.exit(0) + - db_name = '{}.db'.format(bench) molecules = get_molecules_from_db(db_name) diff --git a/tests/work/.gitignore b/tests/work/.gitignore new file mode 100644 index 0000000..235a3a8 --- /dev/null +++ b/tests/work/.gitignore @@ -0,0 +1,2 @@ + +*