from diceplayer.player import Player from diceplayer import logger import io from unittest import mock import unittest def get_config_example(): return """ diceplayer: maxcyc: 3 opt: no ncores: 4 nprocs: 4 qmprog: 'g16' lps: no ghosts: no altsteps: 20000 dice: nmol: [1, 50] dens: 0.75 nstep: [2000, 3000, 4000] isave: 1000 outname: 'phb' progname: '~/.local/bin/dice' ljname: 'phb.ljc' randominit: 'first' gaussian: qmprog: 'g16' level: 'MP2/aug-cc-pVDZ' keywords: 'freq' """ def get_potentials_exemple(): return """\ * 2 1 TEST 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 1 PLACEHOLDER 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 """ def get_potentials_error_combrule(): return """\ . 2 1 TEST 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 1 PLACEHOLDER 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 """ def get_potentials_error_ntypes(): return """\ * a 1 TEST 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 1 PLACEHOLDER 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 """ def get_potentials_error_ntypes_config(): return """\ * 3 1 TEST 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 1 PLACEHOLDER 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 """ def get_potentials_error_nsites(): return """\ * 2 . TEST 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 1 PLACEHOLDER 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 """ def get_potentials_error_molname(): return """\ * 2 1 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 1 PLACEHOLDER 1 1 0.000000 0.000000 0.000000 0.000000 0.0000 0.0000 """ def mock_open(file, *args, **kwargs): values = { "control.test.yml": get_config_example(), "phb.ljc": get_potentials_exemple(), "phb.error.combrule.ljc": get_potentials_error_combrule(), "phb.error.ntypes.ljc": get_potentials_error_ntypes(), "phb.error.ntypes.config.ljc": get_potentials_error_ntypes_config(), "phb.error.nsites.ljc": get_potentials_error_nsites(), "phb.error.molname.ljc": get_potentials_error_molname(), } mock_file = mock.mock_open(read_data=values[file]) return mock_file() class TestPlayer(unittest.TestCase): def setUp(self): logger.set_logger(stream=io.StringIO()) @mock.patch("builtins.open", mock_open) def test_class_instantiation(self): # This file does not exist and it will be mocked player = Player("control.test.yml") self.assertIsInstance(player, Player) @mock.patch("builtins.open", mock_open) def test_start(self): player = Player("control.test.yml") player.print_keywords = mock.MagicMock() player.create_simulation_dir = mock.MagicMock() player.read_potentials = mock.MagicMock() player.print_potentials = mock.MagicMock() player.dice_start = mock.MagicMock() player.start(1) self.assertTrue(player.print_keywords.called) self.assertTrue(player.create_simulation_dir.called) self.assertTrue(player.read_potentials.called) self.assertTrue(player.print_potentials.called) self.assertEqual(player.dice_start.call_count, 3) @mock.patch("builtins.open", mock_open) @mock.patch("diceplayer.player.Path") def test_create_simulation_dir_if_already_exists(self, mock_path): player = Player("control.test.yml") mock_path.return_value.exists.return_value = True with self.assertRaises(FileExistsError): player.create_simulation_dir() self.assertTrue(mock_path.called) @mock.patch("builtins.open", mock_open) @mock.patch("diceplayer.player.Path") def test_create_simulation_dir_if_not_exists(self, mock_path): player = Player("control.test.yml") mock_path.return_value.exists.return_value = False player.create_simulation_dir() self.assertTrue(mock_path.called) @mock.patch("diceplayer.player.sys") @mock.patch("diceplayer.player.weekday_date_time") @mock.patch("builtins.open", mock_open) def test_print_keywords(self, mock_date_func, mock_sys): player = Player("control.test.yml") mock_sys.version = 'TEST' mock_date_func.return_value = '00 Test 0000 at 00:00:00' with self.assertLogs() as cm: player.print_keywords() expected_output = ['INFO:diceplayer:##########################################################################################\n############# Welcome to DICEPLAYER version 1.0 #############\n##########################################################################################\n\n', 'INFO:diceplayer:Your python version is TEST\n', 'INFO:diceplayer:\n', 'INFO:diceplayer:Program started on 00 Test 0000 at 00:00:00\n', 'INFO:diceplayer:\n', 'INFO:diceplayer:Environment variables:\n', 'INFO:diceplayer:OMP_STACKSIZE = Not set\n', 'INFO:diceplayer:\n==========================================================================================\n CONTROL variables being used in this run:\n------------------------------------------------------------------------------------------\n\n', 'INFO:diceplayer:\n', 'INFO:diceplayer:------------------------------------------------------------------------------------------\n DICE variables being used in this run:\n------------------------------------------------------------------------------------------\n\n', 'INFO:diceplayer:dens = 0.75', 'INFO:diceplayer:isave = 1000', 'INFO:diceplayer:ljname = phb.ljc', 'INFO:diceplayer:nmol = [ 1 50 ]', 'INFO:diceplayer:nstep = [ 2000 3000 4000 ]', 'INFO:diceplayer:outname = phb', 'INFO:diceplayer:press = 1.0', 'INFO:diceplayer:progname = ~/.local/bin/dice', 'INFO:diceplayer:randominit = first', 'INFO:diceplayer:temp = 300.0', 'INFO:diceplayer:\n', 'INFO:diceplayer:------------------------------------------------------------------------------------------\n GAUSSIAN variables being used in this run:\n------------------------------------------------------------------------------------------\n\n', 'INFO:diceplayer:keywords = freq', 'INFO:diceplayer:level = MP2/aug-cc-pVDZ', 'INFO:diceplayer:pop = chelpg', 'INFO:diceplayer:qmprog = g16', 'INFO:diceplayer:\n'] self.assertEqual(cm.output, expected_output) def test_validate_atom_dict(self): with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0 } ) self.assertEqual( str(context.exception), "Invalid number of fields for site 1 for molecule type 1." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": '', "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid lbl fields for site 1 for molecule type 1." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": '', "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid na fields for site 1 for molecule type 1." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": 1, "rx": '', "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid rx fields for site 1 for molecule type 1. Value must be a float." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": 1, "rx": 1.0, "ry": '', "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid ry fields for site 1 for molecule type 1. Value must be a float." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": '', "chg": 1.0, "eps": 1.0, "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid rz fields for site 1 for molecule type 1. Value must be a float." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": '', "eps": 1.0, "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid chg fields for site 1 for molecule type 1. Value must be a float." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": '', "sig": 1.0 } ) self.assertEqual( str(context.exception), "Invalid eps fields for site 1 for molecule type 1. Value must be a float." ) with self.assertRaises(ValueError) as context: Player.validate_atom_dict( molecule_type=0, molecule_site=0, atom_dict={ "lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": '' } ) self.assertEqual( str(context.exception), "Invalid sig fields for site 1 for molecule type 1. Value must be a float." ) @mock.patch("builtins.open", mock_open) @mock.patch("diceplayer.player.Path.exists", return_value=True) def test_read_potentials(self, mock_path_exists): player = Player("control.test.yml") player.read_potentials() self.assertEqual(player.system.molecule[0].molname, "TEST") self.assertEqual(len(player.system.molecule[0].atom), 1) self.assertEqual(player.system.molecule[1].molname, "PLACEHOLDER") self.assertEqual(len(player.system.molecule[1].atom), 1) @mock.patch("builtins.open", mock_open) @mock.patch("diceplayer.player.Path.exists") def test_read_potentials_error(self, mock_path_exists): player = Player("control.test.yml") # Testing file not found error mock_path_exists.return_value = False with self.assertRaises(RuntimeError) as context: player.read_potentials() self.assertEqual( str(context.exception), "Potential file phb.ljc not found." ) # Enabling file found for next tests mock_path_exists.return_value = True # Testing combrule error with self.assertRaises(SystemExit) as context: player.dice.config.ljname = "phb.error.combrule.ljc" player.read_potentials() self.assertEqual( str(context.exception), "Error: expected a '*' or a '+' sign in 1st line of file phb.error.combrule.ljc" ) # Testing ntypes error with self.assertRaises(SystemExit) as context: player.dice.config.ljname = "phb.error.ntypes.ljc" player.read_potentials() self.assertEqual( str(context.exception), "Error: expected an integer in the 2nd line of file phb.error.ntypes.ljc" ) # Testing ntypes error on config with self.assertRaises(SystemExit) as context: player.dice.config.ljname = "phb.error.ntypes.config.ljc" player.read_potentials() self.assertEqual( str(context.exception), "Error: number of molecule types in file phb.error.ntypes.config.ljc " "must match that of 'nmol' keyword in config file" ) # Testing nsite error with self.assertRaises(ValueError) as context: player.dice.config.ljname = "phb.error.nsites.ljc" player.read_potentials() self.assertEqual( str(context.exception), "Error: expected nsites to be an integer for molecule type 1" ) # Testing molname error with self.assertRaises(ValueError) as context: player.dice.config.ljname = "phb.error.molname.ljc" player.read_potentials() self.assertEqual( str(context.exception), "Error: expected nsites and molname for the molecule type 1" ) @mock.patch("builtins.open", mock_open) @mock.patch("diceplayer.player.Path.exists", return_value=True) def test_print_potentials(self, mock_path_exists): player = Player("control.test.yml") player.read_potentials() with self.assertLogs(level='INFO') as context: player.print_potentials() expected_output = ['INFO:diceplayer:==========================================================================================\n', 'INFO:diceplayer: Potential parameters from file phb.ljc:', 'INFO:diceplayer:------------------------------------------------------------------------------------------\n', 'INFO:diceplayer:Combination rule: *', 'INFO:diceplayer:Types of molecules: 2\n', 'INFO:diceplayer:1 atoms in molecule type 1:', 'INFO:diceplayer:---------------------------------------------------------------------------------', 'INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass', 'INFO:diceplayer:---------------------------------------------------------------------------------', 'INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079', 'INFO:diceplayer:\n', 'INFO:diceplayer:1 atoms in molecule type 2:', 'INFO:diceplayer:---------------------------------------------------------------------------------', 'INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass', 'INFO:diceplayer:---------------------------------------------------------------------------------', 'INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079', 'INFO:diceplayer:\n', 'INFO:diceplayer:=========================================================================================='] self.assertEqual( context.output, expected_output ) @mock.patch("builtins.open", mock_open) def test_dice_start(self): player = Player("control.test.yml") player.dice = mock.MagicMock() player.dice.start = mock.MagicMock() player.dice_start(1) player.dice.start.assert_called_once() @mock.patch("builtins.open", mock_open) def test_gaussian_start(self): player = Player("control.test.yml") player.gaussian = mock.MagicMock() player.gaussian.start = mock.MagicMock() player.gaussian_start(1) player.gaussian.start.assert_called_once() if __name__ == '__main__': unittest.main()