def test_base(self): """unit tests for Qadapter subclasses. A more complete coverage would require integration testing.""" self.maxDiff = None aequal, atrue, afalse = self.assertEqual, self.assertTrue, self.assertFalse sub_classes = QueueAdapter.__subclasses__() # Test if we can instantiate the concrete classes with the abc protocol. for subc in sub_classes: print("subclass: ", subc) # Create the adapter subclass. self.QDICT["queue"]["qtype"] = subc.QTYPE qad = make_qadapter(**self.QDICT) print(qad) hw = qad.hw giga = 1024 # Test the programmatic interface used to change job parameters. aequal(qad.num_launches, 0) afalse(qad.has_omp) atrue(qad.has_mpi) qad.set_mpi_procs(2) aequal(qad.mpi_procs, 2) atrue(qad.pure_mpi) afalse(qad.pure_omp) afalse(qad.hybrid_mpi_omp) aequal(qad.mem_per_proc, giga) qad.set_mem_per_proc(2 * giga) aequal(qad.mem_per_proc, 2 * giga) aequal(qad.timelimit, 120) # Enable OMP qad.set_omp_threads(2) aequal(qad.omp_threads, 2) atrue(qad.has_omp) afalse(qad.pure_mpi) afalse(qad.pure_omp) atrue(qad.hybrid_mpi_omp) atrue( qad.hw.can_use_omp_threads(hw.sockets_per_node * hw.cores_per_socket)) afalse( qad.hw.can_use_omp_threads(hw.sockets_per_node * hw.cores_per_socket + 1)) # Test the creation of the script script = qad.get_script_str("job.sh", "/launch/dir", "executable", "qout_path", "qerr_path", stdin="STDIN", stdout="STDOUT", stderr="STDERR") # Test whether qad can be serialized with Pickle. deserialized_qads = self.serialize_with_pickle(qad, test_eq=False) for new_qad in deserialized_qads: new_script = new_qad.get_script_str("job.sh", "/launch/dir", "executable", "qout_path", "qerr_path", stdin="STDIN", stdout="STDOUT", stderr="STDERR") aequal(new_script, script) # Test can_run and distribute # The hardware has num_nodes=3, sockets_per_node=2, cores_per_socket=4, mem_per_node="8 Gb" afalse( qad.can_run_pconf( ParalConf(mpi_ncpus=hw.num_cores + 1, omp_ncpus=1, mem_per_cpu=0.1))) afalse( qad.can_run_pconf( ParalConf(mpi_ncpus=4, omp_ncpus=9, mem_per_cpu=0.1))) afalse( qad.can_run_pconf( ParalConf(mpi_ncpus=4, omp_ncpus=1, mem_per_cpu=10 * giga))) d = qad.distribute(mpi_procs=4, omp_threads=1, mem_per_proc=giga) assert d.num_nodes == 1 and d.mpi_per_node == 4 and d.exact d = qad.distribute(mpi_procs=16, omp_threads=1, mem_per_proc=giga) assert d.num_nodes == 2 and d.mpi_per_node == 8 and d.exact # not enough memory per node but can distribute. d = qad.distribute(mpi_procs=8, omp_threads=1, mem_per_proc=2 * giga) assert d.num_nodes == 2 and d.mpi_per_node == 4 and not d.exact # mem_per_proc > mem_per_node! with self.assertRaises(qad.Error): d = qad.distribute(mpi_procs=9, omp_threads=1, mem_per_proc=10 * giga) # TODO # not commensurate with node #d = qad.distribute(mpi_procs=9, omp_threads=1, mem_per_proc=giga) #assert d.num_nodes == 3 and d.mpi_per_node == 3 and not d.exact with self.assertRaises(qad.Error): qad.set_mpi_procs(25) qad.validate() with self.assertRaises(qad.Error): qad.set_mpi_procs(100) qad.validate() with self.assertRaises(qad.Error): qad.set_omp_threads(10) qad.validate() with self.assertRaises(qad.Error): qad.set_mem_per_proc(9 * giga) qad.validate() # Test if one can register a customized class. class MyAdapter(SlurmAdapter): QTYPE = "myslurm" SlurmAdapter.register(MyAdapter) assert issubclass(MyAdapter, QueueAdapter) self.QDICT["queue"]["qtype"] = "myslurm" qad = make_qadapter(**self.QDICT) assert isinstance(qad, MyAdapter)
def test_base(self): """unit tests for Qadapter subclasses. A more complete coverage would require integration testing.""" self.maxDiff = None aequal, atrue, afalse = self.assertEqual, self.assertTrue, self.assertFalse sub_classes = QueueAdapter.__subclasses__() # Test if we can instantiate the concrete classes with the abc protocol. for subc in sub_classes: print("subclass: ", subc) # Create the adapter subclass. self.QDICT["queue"]["qtype"] = subc.QTYPE qad = make_qadapter(**self.QDICT) print(qad) hw = qad.hw giga = 1024 # Test the programmatic interface used to change job parameters. aequal(qad.num_launches, 0) afalse(qad.has_omp) atrue(qad.has_mpi) qad.set_mpi_procs(2) aequal(qad.mpi_procs, 2) atrue(qad.pure_mpi) afalse(qad.pure_omp) afalse(qad.hybrid_mpi_omp) aequal(qad.mem_per_proc, giga) qad.set_mem_per_proc(2 * giga) aequal(qad.mem_per_proc, 2 * giga) aequal(qad.timelimit, 120) # Enable OMP qad.set_omp_threads(2) aequal(qad.omp_threads, 2) atrue(qad.has_omp) afalse(qad.pure_mpi) afalse(qad.pure_omp) atrue(qad.hybrid_mpi_omp) atrue(qad.hw.can_use_omp_threads(hw.sockets_per_node * hw.cores_per_socket)) afalse(qad.hw.can_use_omp_threads(hw.sockets_per_node * hw.cores_per_socket + 1)) # Test the creation of the script script = qad.get_script_str("job.sh", "/launch/dir", "executable", "qout_path", "qerr_path", stdin="STDIN", stdout="STDOUT", stderr="STDERR") # Test whether qad can be serialized with Pickle. deserialized_qads = self.serialize_with_pickle(qad, test_eq=False) for new_qad in deserialized_qads: new_script = new_qad.get_script_str("job.sh", "/launch/dir", "executable", "qout_path", "qerr_path", stdin="STDIN", stdout="STDOUT", stderr="STDERR") aequal(new_script, script) # Test can_run and distribute # The hardware has num_nodes=3, sockets_per_node=2, cores_per_socket=4, mem_per_node="8 Gb" afalse(qad.can_run_pconf(ParalConf(mpi_ncpus=hw.num_cores+1, omp_ncpus=1, mem_per_cpu=0.1))) afalse(qad.can_run_pconf(ParalConf(mpi_ncpus=4, omp_ncpus=9, mem_per_cpu=0.1))) afalse(qad.can_run_pconf(ParalConf(mpi_ncpus=4, omp_ncpus=1, mem_per_cpu=10 * giga))) d = qad.distribute(mpi_procs=4, omp_threads=1, mem_per_proc=giga) assert d.num_nodes == 1 and d.mpi_per_node == 4 and d.exact d = qad.distribute(mpi_procs=16, omp_threads=1, mem_per_proc=giga) assert d.num_nodes == 2 and d.mpi_per_node == 8 and d.exact # not enough memory per node but can distribute. d = qad.distribute(mpi_procs=8, omp_threads=1, mem_per_proc=2 * giga) assert d.num_nodes == 2 and d.mpi_per_node == 4 and not d.exact # mem_per_proc > mem_per_node! with self.assertRaises(qad.Error): d = qad.distribute(mpi_procs=9, omp_threads=1, mem_per_proc=10 * giga) # TODO # not commensurate with node #d = qad.distribute(mpi_procs=9, omp_threads=1, mem_per_proc=giga) #assert d.num_nodes == 3 and d.mpi_per_node == 3 and not d.exact with self.assertRaises(qad.Error): qad.set_mpi_procs(25) qad.validate() with self.assertRaises(qad.Error): qad.set_mpi_procs(100) qad.validate() with self.assertRaises(qad.Error): qad.set_omp_threads(10) qad.validate() with self.assertRaises(qad.Error): qad.set_mem_per_proc(9 * giga) qad.validate() # Test if one can register a customized class. class MyAdapter(SlurmAdapter): QTYPE = "myslurm" SlurmAdapter.register(MyAdapter) assert issubclass(MyAdapter, QueueAdapter) self.QDICT["queue"]["qtype"] = "myslurm" qad = make_qadapter(**self.QDICT) assert isinstance(qad, MyAdapter)