def setUp(self): def restore_env(env): os.environ.clear() os.environ.update(env) self.addCleanup(restore_env, os.environ.copy()) os.environ['PATH'] = "{}:{}".format( Path(__file__).parent / 'bin', os.environ['PATH']) os.environ['JUJU_UNIT_NAME'] = 'local/0' self.tmpdir = Path(tempfile.mkdtemp()) self.addCleanup(shutil.rmtree, str(self.tmpdir)) self.meta = CharmMeta() class CustomEvent(EventBase): pass class TestCharmEvents(CharmEvents): custom = EventSource(CustomEvent) # Relations events are defined dynamically and modify the class attributes. # We use a subclass temporarily to prevent these side effects from leaking. CharmBase.on = TestCharmEvents() def cleanup(): CharmBase.on = CharmEvents() self.addCleanup(cleanup)
def setUp(self): self._path = os.environ['PATH'] os.environ['PATH'] = str(Path(__file__).parent / 'bin') os.environ['JUJU_UNIT_NAME'] = 'local/0' self.tmpdir = Path(tempfile.mkdtemp()) self.addCleanup(shutil.rmtree, self.tmpdir) self.meta = CharmMeta() class CustomEvent(EventBase): pass class TestCharmEvents(CharmEvents): custom = EventSource(CustomEvent) # Relations events are defined dynamically and modify the class attributes. # We use a subclass temporarily to prevent these side effects from leaking. CharmBase.on = TestCharmEvents() def cleanup(): os.environ['PATH'] = self._path del os.environ['JUJU_UNIT_NAME'] CharmBase.on = CharmEvents() self.addCleanup(cleanup)
def create_framework(self): framework = Framework(self.tmpdir / "framework.data", self.tmpdir, CharmMeta(), None) # Ensure that the Framework object is closed and cleaned up even # when the test fails or errors out. self.addCleanup(framework.close) return framework
def test_relation_events(self): class MyCharm(CharmBase): def __init__(self, *args): super().__init__(*args) self.seen = [] for rel in ('req1', 'req-2', 'pro1', 'pro-2', 'peer1', 'peer-2'): # Hook up relation events to generic handler. self.framework.observe(self.on[rel].relation_joined, self.on_any_relation) self.framework.observe(self.on[rel].relation_changed, self.on_any_relation) self.framework.observe(self.on[rel].relation_departed, self.on_any_relation) self.framework.observe(self.on[rel].relation_broken, self.on_any_relation) def on_any_relation(self, event): assert event.relation.name == 'req1' assert event.relation.app.name == 'remote' self.seen.append(type(event).__name__) self.meta = CharmMeta({ 'name': 'my-charm', 'requires': { 'req1': {'interface': 'req1'}, 'req-2': {'interface': 'req2'}, }, 'provides': { 'pro1': {'interface': 'pro1'}, 'pro-2': {'interface': 'pro2'}, }, 'peers': { 'peer1': {'interface': 'peer1'}, 'peer-2': {'interface': 'peer2'}, }, }) charm = MyCharm(self.create_framework(), None) rel = charm.framework.model.get_relation('req1', 1) unit = charm.framework.model.get_unit('remote/0') charm.on['req1'].relation_joined.emit(rel, unit) charm.on['req1'].relation_changed.emit(rel, unit) charm.on['req-2'].relation_changed.emit(rel, unit) charm.on['pro1'].relation_departed.emit(rel, unit) charm.on['pro-2'].relation_departed.emit(rel, unit) charm.on['peer1'].relation_broken.emit(rel) charm.on['peer-2'].relation_broken.emit(rel) self.assertEqual(charm.seen, [ 'RelationJoinedEvent', 'RelationChangedEvent', 'RelationChangedEvent', 'RelationDepartedEvent', 'RelationDepartedEvent', 'RelationBrokenEvent', 'RelationBrokenEvent', ])
def create_model(self): """Create a Model object.""" unit_name = 'myapp/0' patcher = patch.dict(os.environ, {'JUJU_UNIT_NAME': unit_name}) patcher.start() self.addCleanup(patcher.stop) backend = _ModelBackend() meta = CharmMeta() model = Model('myapp/0', meta, backend) return model
class MRRMTestCharm(CharmBase): __name__ = self.app_name on = MRRMTestEvents() meta = CharmMeta({ self.ROLE: { self._default_endpoint: { "role": self.ROLE, "interface": self.INTERFACE, "limit": self.LIMIT, }, }, }) app = harness.model.get_app(self.app_name) unit = harness.model.get_unit(self.unit_name)
def create_framework(self): model = create_autospec(Model) model.unit = create_autospec(Unit) model.unit.is_leader = MagicMock(return_value=False) model.app = create_autospec(Application) model.pod = create_autospec(Pod) model.config = create_autospec(ConfigData) raw_meta = {'provides': {'mongo': {"interface": "mongodb"}}} framework = Framework( self.tmpdir / "framework.data.{}".format(str(uuid4)), self.tmpdir, CharmMeta(raw=raw_meta), model) framework.model.app.name = "test-app" self.addCleanup(framework.close) return framework
def _get_function_test_meta(cls): return CharmMeta({'name': 'my-charm'}, { 'foo-bar': { 'description': 'Foos the bar.', 'title': 'foo-bar', 'required': 'foo-bar', 'params': { 'foo-name': { 'type': 'string', 'description': 'A foo name to bar', }, 'silent': { 'type': 'boolean', 'description': '', 'default': False, }, }, }, 'start': { 'description': 'Start the unit.' } })
def create_model(self): """Create a Model object.""" backend = _ModelBackend(unit_name='myapp/0') meta = CharmMeta() model = Model(meta, backend) return model
def test_storage_events(self): class MyCharm(CharmBase): def __init__(self, *args): super().__init__(*args) self.seen = [] self.framework.observe(self.on['stor1'].storage_attached, self) self.framework.observe(self.on['stor2'].storage_detaching, self) self.framework.observe(self.on['stor3'].storage_attached, self) self.framework.observe(self.on['stor-4'].storage_attached, self) def on_stor1_storage_attached(self, event): self.seen.append(f'{type(event).__name__}') def on_stor2_storage_detaching(self, event): self.seen.append(f'{type(event).__name__}') def on_stor3_storage_attached(self, event): self.seen.append(f'{type(event).__name__}') def on_stor_4_storage_attached(self, event): self.seen.append(f'{type(event).__name__}') self.meta = CharmMeta({ 'name': 'my-charm', 'storage': { 'stor1': { 'type': 'filesystem' }, 'stor2': { 'type': 'filesystem', 'multiple': { 'range': '2', }, }, 'stor3': { 'type': 'filesystem', 'multiple': { 'range': '2-', }, }, 'stor-4': { 'type': 'filesystem', 'multiple': { 'range': '2-4', }, }, }, }) self.assertIsNone(self.meta.storages['stor1'].multiple_range) self.assertEqual(self.meta.storages['stor2'].multiple_range, (2, 2)) self.assertEqual(self.meta.storages['stor3'].multiple_range, (2, None)) self.assertEqual(self.meta.storages['stor-4'].multiple_range, (2, 4)) charm = MyCharm(self.create_framework(), None) charm.on['stor1'].storage_attached.emit() charm.on['stor2'].storage_detaching.emit() charm.on['stor3'].storage_attached.emit() charm.on['stor-4'].storage_attached.emit() self.assertEqual(charm.seen, [ 'StorageAttachedEvent', 'StorageDetachingEvent', 'StorageAttachedEvent', 'StorageAttachedEvent', ])