diff --git a/src/python/espressomd/particle_data.pyx b/src/python/espressomd/particle_data.pyx index 6eda576485d..862ce23c80f 100644 --- a/src/python/espressomd/particle_data.pyx +++ b/src/python/espressomd/particle_data.pyx @@ -378,6 +378,8 @@ cdef class ParticleHandle: IF MASS == 1: check_type_or_throw_except( _mass, 1, float, "Mass has to be 1 float") + if _mass <= 0.: + raise ValueError("mass must be a float > 0") set_particle_mass(self._id, _mass) ELSE: raise AttributeError("You are trying to set the particle mass " diff --git a/testsuite/python/particle.py b/testsuite/python/particle.py index ece1306dadd..274392e4d29 100644 --- a/testsuite/python/particle.py +++ b/testsuite/python/particle.py @@ -358,6 +358,36 @@ def test_invalid_particle_creation(self): with self.assertRaisesRegex(ValueError, err_msg): self.system.part.add([1, 2]) + def test_invalid_particle_attributes(self): + p = self.partcl + with self.assertRaisesRegex(ValueError, "type must be an integer >= 0"): + p.type = -1 + with self.assertRaisesRegex(ValueError, "mol_id must be an integer >= 0"): + p.mol_id = -1 + if espressomd.has_features("ENGINE"): + with self.assertRaisesRegex(Exception, "You can't set v_swim and f_swim at the same time"): + p.swimming = {"v_swim": 0.3, "f_swim": 0.6} + with self.assertRaisesRegex(Exception, "'mode' has to be either 'pusher', 'puller' or 'N/A'"): + p.swimming = {"v_swim": 0.3, "mode": "invalid"} + if espressomd.has_features("MASS"): + for mass in [0., -1., -2.]: + with self.assertRaisesRegex(ValueError, "mass must be a float > 0"): + p.mass = mass + + def test_missing_features(self): + def check(feature, prop, throwing_values, valid_value=None): + if not espressomd.has_features(feature): + if valid_value is not None: + # this should not throw + setattr(self.partcl, prop, valid_value) + for throwing_value in throwing_values: + with self.assertRaisesRegex(RuntimeError, f"Feature {feature} not compiled in"): + setattr(self.partcl, prop, throwing_value) + + check("MASS", "mass", [1.1, 0., -1.], 1.) + check("ELECTROSTATICS", "q", [1., -1.], 0.) + check("VIRTUAL_SITES", "virtual", [True], False) + def test_parallel_property_setters(self): s = self.system s.part.clear()