def test_wrapper(self): r = Wrapper(Context()) with self.assertRaises(AttributeError): r.get() with self.assertRaises(AttributeError): r.post() with self.assertRaises(AttributeError): r.put() with self.assertRaises(AttributeError): r.delete() def hook(): return 'hello' def hook_patched(): return 'world' r = Wrapper(callable=hook, route='/wrapped') self.assertEqual(r.route, '/wrapped') self.assertTrue(r.callable is not None) self.assertEqual(r.get(), 'hello') self.assertEqual(r.post(), 'hello') self.assertEqual(r.put(), 'hello') self.assertEqual(r.delete(), 'hello') r.callable = hook_patched self.assertEqual(r.get(), 'world') self.assertEqual(r.post(), 'world') self.assertEqual(r.put(), 'world') self.assertEqual(r.delete(), 'world') context = Context() class Callable(object): def __init__(self, context): self.context = context def hook(self, **kwargs): self.context.set('signal', 'wrapped!') return 'OK' callable = Callable(context) r = Wrapper(context=context, callable=callable.hook, route='/wrapped') self.assertEqual(r.route, '/wrapped') self.assertEqual(r.callable, callable.hook) self.assertEqual(context.get('signal'), None) self.assertEqual(r.get(), 'OK') self.assertEqual(r.post(), 'OK') self.assertEqual(r.put(), 'OK') self.assertEqual(r.delete(), 'OK') self.assertEqual(context.get('signal'), 'wrapped!')
class ContextTests(unittest.TestCase): def setUp(self): self.context = Context() def tearDown(self): del self.context collected = gc.collect() if collected: logging.info("Garbage collector: collected %d objects." % (collected)) def test_init(self): settings = { 'bot': { 'name': 'testy', 'version': '17.4.1' }, } self.context = Context(settings) self.assertEqual(self.context.get('bot.name'), 'testy') self.assertEqual(self.context.get('bot.version'), '17.4.1') def test_init_filter(self): self.context = Context(filter=lambda x, y: x + '...') self.context.apply({'my.var': 'my value'}) self.context.check('my.var', filter=True) self.assertEqual(self.context.get('my.var'), 'my value...') def test_apply(self): self.assertEqual(self.context.get('port'), None) settings = { 'spark': { 'CISCO_SPARK_BTTN_BOT': 'who_knows' }, 'spark.room': 'title', 'DEBUG': True, 'server': { 'port': 80, 'url': 'http://www.acme.com/' }, 'bot.store': { 'planets': ['Uranus', 'Mercury'] }, } self.context.apply(settings) self.assertEqual(self.context.get('DEBUG'), True) self.assertEqual(self.context.get('spark.CISCO_SPARK_BTTN_BOT'), 'who_knows') self.assertEqual(self.context.get('spark.room'), 'title') self.assertEqual(self.context.get('server.port'), 80) self.assertEqual(self.context.get('server.url'), 'http://www.acme.com/') self.assertEqual(self.context.get('bot.store.planets'), ['Uranus', 'Mercury']) self.assertEqual(self.context.get('bot.store'), {'planets': ['Uranus', 'Mercury']}) def test_clear(self): self.assertEqual(self.context.get('port'), None) settings = { 'spark': { 'CISCO_SPARK_BTTN_BOT': 'who_knows' }, 'spark.room': 'title', 'DEBUG': True, 'server': { 'port': 80, 'url': 'http://www.acme.com/' }, } self.context.apply(settings) self.assertEqual(self.context.get('DEBUG'), True) self.assertEqual(self.context.get('spark.CISCO_SPARK_BTTN_BOT'), 'who_knows') self.assertEqual(self.context.get('spark.room'), 'title') self.assertEqual(self.context.get('server.port'), 80) self.assertEqual(self.context.get('server.url'), 'http://www.acme.com/') self.context.clear() self.assertEqual(self.context.get('DEBUG'), None) self.assertEqual(self.context.get('spark.CISCO_SPARK_BTTN_BOT'), None) self.assertEqual(self.context.get('spark.room'), None) self.assertEqual(self.context.get('server.port'), None) self.assertEqual(self.context.get('server.url'), None) def test_is_empty(self): self.assertTrue(self.context.is_empty) # set a key self.context.set('hello', 'world') self.assertEqual(self.context.get('hello'), 'world') self.assertFalse(self.context.is_empty) self.context.clear() self.assertTrue(self.context.is_empty) settings = { 'spark': { 'CISCO_SPARK_BTTN_BOT': 'who_knows' }, 'spark.room': 'title', 'DEBUG': True, 'server': { 'port': 80, 'url': 'http://www.acme.com/' }, } self.context.apply(settings) self.assertFalse(self.context.is_empty) def test_check(self): self.assertEqual(self.context.get('spark.room'), None) settings = { 'spark': { 'room': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY', 'weird_token': '$MY_FUZZY_SPARK_TOKEN', 'fuzzy_token': '$MY_FUZZY_SPARK_TOKEN', 'webhook': "http://73a1e282.ngrok.io", } } self.context.apply(settings) self.context.check('spark.room', is_mandatory=True) self.assertEqual(self.context.get('spark.room'), 'My preferred channel') self.context.check('spark.team') self.assertEqual(self.context.get('spark.team'), 'Anchor team') self.context.check('spark.*not*present') # will be set to None self.assertEqual(self.context.get('spark.*not*present'), None) self.context.check('spark.absent_list', default=[]) self.assertEqual(self.context.get('spark.absent_list'), []) self.context.check('spark.absent_dict', default={}) self.assertEqual(self.context.get('spark.absent_dict'), {}) self.context.check('spark.absent_text', default='*born') self.assertEqual(self.context.get('spark.absent_text'), '*born') # is_mandatory is useless if default is set self.context.check('spark.*not*present', default='*born', is_mandatory=True) self.assertEqual(self.context.get('spark.*not*present'), '*born') # missing key self.assertEqual(self.context.get('spark.*unknown*key*'), None) # we need the missing key with self.assertRaises(KeyError): self.context.check('spark.*unknown*key*', is_mandatory=True) # validate implies is_mandatory with self.assertRaises(KeyError): self.context.check('spark.*unknown*key*', validate=lambda line: True) # exception when is_mandatory is explicit with self.assertRaises(KeyError): self.context.check('spark.*unknown*key*', is_mandatory=True, filter=True) # yet filter does not imply is_mandatory by itself self.context.check('spark.*unknown*key*', filter=True) # warning in log # a web link has been set self.assertEqual(self.context.get('spark.webhook'), "http://73a1e282.ngrok.io") # validate http self.context.check('spark.webhook', validate=lambda line: line.startswith('http')) # validate https with self.assertRaises(ValueError): self.context.check('spark.webhook', validate=lambda line: line.startswith('https')) # a token has been set self.assertEqual(self.context.get('spark.token'), 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY') # validate length of token with self.assertRaises(ValueError): self.context.check('spark.token', validate=lambda line: len(line) == 32) # we rely on the environment for this key self.assertEqual(self.context.get('spark.weird_token'), '$MY_FUZZY_SPARK_TOKEN') # no change to the value self.context.check('spark.weird_token') # lookup the environment and change the value to None self.context.check('spark.weird_token', filter=True) # warning in log self.assertEqual(self.context.get('spark.weird_token'), None) # ensure the environment is clean def clear_env(name): try: os.environ.pop(name) except: pass clear_env('MY_FUZZY_SPARK_TOKEN') # a value based on the environment self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') self.context.check('spark.fuzzy_token') self.assertEqual(self.context.get('spark.fuzzy_token'), '$MY_FUZZY_SPARK_TOKEN') # default has no effect, mandatory is ok self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') self.context.check('spark.fuzzy_token', default='hello there') self.context.check('spark.fuzzy_token', is_mandatory=True) self.assertEqual(self.context.get('spark.fuzzy_token'), '$MY_FUZZY_SPARK_TOKEN') # default value is used if key is absent from the environment self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') self.context.check('spark.fuzzy_token', default='hello there', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), 'hello there') # is_mandatory is useless in that case self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') self.context.check('spark.fuzzy_token', is_mandatory=True, filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), None) # set the value to '' self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') os.environ['MY_FUZZY_SPARK_TOKEN'] = '' self.context.check('spark.fuzzy_token', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), '') # set the value to '' -- default value is useless in that case self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') os.environ['MY_FUZZY_SPARK_TOKEN'] = '' self.context.check('spark.fuzzy_token', default='ok?', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), '') # set the value to 'hello' self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') os.environ['MY_FUZZY_SPARK_TOKEN'] = 'hello' self.context.check('spark.fuzzy_token', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), 'hello') # set the value to 'hello' -- default value is useless in that case self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') os.environ['MY_FUZZY_SPARK_TOKEN'] = 'hello again' self.context.check('spark.fuzzy_token', default='ok?', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), 'hello again') # pass the variable name as default value self.context.set('spark.fuzzy_token', None) os.environ['MY_FUZZY_SPARK_TOKEN'] = 'hello' self.context.check('spark.fuzzy_token', default='$MY_FUZZY_SPARK_TOKEN', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), 'hello') # pass the variable name as default value -- no effect self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') os.environ['MY_FUZZY_SPARK_TOKEN'] = 'hello' self.context.check('spark.fuzzy_token', default='$MY_FUZZY_SPARK_TOKEN', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), 'hello') # pass as default the name of an empty variable -- tricky case self.context.set('spark.fuzzy_token', '$MY_FUZZY_SPARK_TOKEN') clear_env('MY_FUZZY_SPARK_TOKEN') self.context.check('spark.fuzzy_token', default='$MY_FUZZY_SPARK_TOKEN', filter=True) self.assertEqual(self.context.get('spark.fuzzy_token'), None) def test__filter(self): self.assertEqual(Context._filter(None), None) self.assertEqual(Context._filter(''), '') self.assertEqual(Context._filter('ZLOGQ0OVGlZWU1NmYtyY'), 'ZLOGQ0OVGlZWU1NmYtyY') if os.environ.get('PATH') is not None: self.assertTrue(Context._filter('$PATH') != '$PATH') Context._filter('$TOTALLY*UNKNOWN*HERE') # warning in log def test_has(self): self.context.apply({ 'spark': { 'room': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY', 'fuzzy_token': '$MY_FUZZY_SPARK_TOKEN', 'webhook': "http://73a1e282.ngrok.io", } }) # undefined prefix self.assertFalse(self.context.has('hello')) # top-level prefix self.assertTrue(self.context.has('spark')) # 2-level prefix self.assertTrue(self.context.has('spark.team')) # undefined 2-level prefix self.assertFalse(self.context.has('.token')) def test_getter(self): # undefined key self.assertEqual(self.context.get('hello'), None) # undefined key with default value whatever = 'whatever' self.assertEqual(self.context.get('hello', whatever), whatever) # set a key self.context.set('hello', 'world') self.assertEqual(self.context.get('hello'), 'world') # default value is meaningless when key has been set self.assertEqual(self.context.get('hello', 'whatever'), 'world') # except when set to None self.context.set('special', None) self.assertEqual(self.context.get('special', []), []) def test_unicode(self): self.context.set('hello', 'world') self.assertEqual(self.context.get('hello'), 'world') self.assertEqual(self.context.get(u'hello'), 'world') self.context.set('hello', u'wôrld') self.assertEqual(self.context.get('hello'), u'wôrld') self.context.set(u'hello', u'wôrld') self.assertEqual(self.context.get(u'hello'), u'wôrld') def test_increment(self): self.assertEqual(self.context.get('gauge'), None) value = self.context.increment('gauge') self.assertEqual(value, 1) self.context.set('gauge', 'world') self.assertEqual(self.context.get('gauge'), 'world') value = self.context.increment('gauge') self.assertEqual(value, 1) def test_decrement(self): self.assertEqual(self.context.get('gauge'), None) value = self.context.decrement('gauge') self.assertEqual(value, -1) self.context.set('gauge', 'world') self.assertEqual(self.context.get('gauge'), 'world') value = self.context.decrement('gauge') self.assertEqual(value, -1) def test_gauge(self): # undefined key self.assertEqual(self.context.get('gauge'), None) # see if type mismatch would create an error self.context.set('gauge', 'world') self.assertEqual(self.context.get('gauge'), 'world') # increment and decrement the counter value = self.context.increment('gauge') self.assertEqual(value, 1) self.assertEqual(self.context.get('gauge'), 1) self.assertEqual(self.context.decrement('gauge', 2), -1) self.assertEqual(self.context.increment('gauge', 4), 3) self.assertEqual(self.context.decrement('gauge', 10), -7) self.assertEqual(self.context.increment('gauge', 27), 20) self.assertEqual(self.context.get('gauge'), 20) # default value is meaningless when key has been set self.assertEqual(self.context.get('gauge', 'world'), 20) # reset the gauge self.context.set('gauge', 123) self.assertEqual(self.context.get('gauge'), 123) def test_concurrency(self): def worker(id, context): for i in range(4): r = random.random() time.sleep(r) value = context.increment('gauge') logging.info('worker %d:counter=%d' % (id, value)) logging.info('worker %d:done' % id) logging.info('Creating a counter') self.counter = Context() logging.info('Launching incrementing workers') workers = [] for i in range(4): p = Process(target=worker, args=( i, self.counter, )) p.start() workers.append(p) logging.info('Waiting for worker threads') for p in workers: p.join() logging.info('Counter: %d' % self.counter.get('gauge')) self.assertEqual(self.counter.get('gauge'), 16)
class SpaceTests(unittest.TestCase): def setUp(self): self.context = Context() self.space = Space(context=self.context) def tearDown(self): del self.space del self.context collected = gc.collect() if collected: logging.info("Garbage collector: collected %d objects." % (collected)) def test_init(self): logging.info("*** init") logging.debug("- default init") self.assertEqual(self.space.ears, None) self.assertEqual(self.space.fan, None) logging.debug("- unknown parameter") space = Space(context=self.context, weird='w') with self.assertRaises(AttributeError): self.assertEqual(space.weird, 'w') logging.debug("- extended parameters") class ExSpace(Space): def on_init(self, ex_token=None, **kwargs): self.token = ex_token space = ExSpace(context=self.context, ears='e', fan='f', ex_token='*token', ex_unknown='*weird') self.assertEqual(space.ears, 'e') self.assertEqual(space.fan, 'f') self.assertEqual(space.token, '*token') with self.assertRaises(AttributeError): self.assertTrue(space.unknown is not None) with self.assertRaises(AttributeError): self.assertTrue(space.ex_unknown is not None) logging.debug("- initialised via configuration") space = LocalSpace(context=self.context) space.configure({ 'space': { 'title': 'Another title', 'participants': ['*****@*****.**', '*****@*****.**'], } }) self.assertEqual(space.configured_title(), 'Another title') def test_on_start(self): logging.info("*** on_start") self.space.on_start() def test_on_stop(self): logging.info("*** on_stop") self.space.on_stop() def test_configure(self): logging.info("*** configure") class ExSpace(Space): def check(self): self.context.check('space.title', is_mandatory=True) settings = {'space.key': 'my value'} space = ExSpace(context=self.context) with self.assertRaises(KeyError): space.configure(settings=settings) self.assertEqual(space.context.get('space.title'), None) self.assertEqual(space.context.get('space.key'), 'my value') def test_configured_title(self): logging.info("*** configured_title") space = Space(context=self.context) self.assertEqual(space.configured_title(), space.DEFAULT_SPACE_TITLE) settings = {'space.title': 'my channel'} space.configure(settings=settings) self.assertEqual(self.context.get('space.title'), 'my channel') self.assertEqual(space.context.get('space.title'), 'my channel') self.assertEqual(space.configured_title(), 'my channel') def test_connect(self): logging.info("*** connect") self.space.connect() def test_list_group_channels(self): logging.info("*** list_group_channels") with self.assertRaises(NotImplementedError): channels = self.space.list_group_channels() def test_create(self): logging.info("*** create") with self.assertRaises(NotImplementedError): channel = self.space.create(title='*title') def test_get_by_title(self): logging.info("*** get_by_title") with self.assertRaises(AssertionError): self.space.get_by_title(None) with self.assertRaises(AssertionError): self.space.get_by_title('') self.assertEqual(self.space.get_by_title(title='*unknown'), None) def test_get_by_id(self): logging.info("*** get_by_id") with self.assertRaises(AssertionError): self.space.get_by_id(None) with self.assertRaises(AssertionError): self.space.get_by_id('') self.assertEqual(self.space.get_by_id(id='*unknown'), None) def test_get_by_person(self): logging.info("*** get_by_person") with self.assertRaises(AssertionError): self.space.get_by_person(None) with self.assertRaises(AssertionError): self.space.get_by_person('') self.assertEqual(self.space.get_by_person('*unknown'), None) def test_update(self): logging.info("*** update") with self.assertRaises(NotImplementedError): self.space.update(channel=FakeChannel()) def test_delete(self): logging.info("*** delete") with self.assertRaises(NotImplementedError): self.space.delete(id='*id') def test_list_participants(self): logging.info("*** list_participants") with self.assertRaises(NotImplementedError): self.space.list_participants(id='*id') def test_add_participants(self): logging.info("*** add_participants") with mock.patch.object(self.space, 'add_participant') as mocked: self.space.add_participants(id='*id', persons=[]) self.assertFalse(mocked.called) class MySpace(Space): def on_init(self): self._persons = [] def add_participant(self, id, person): self._persons.append(person) space = MySpace(context=self.context) space.add_participants(id='*id', persons=['*****@*****.**', '*****@*****.**']) self.assertEqual(space._persons, ['*****@*****.**', '*****@*****.**']) def test_add_participant(self): logging.info("*** add_participant") with self.assertRaises(NotImplementedError): self.space.add_participant(id='*id', person='*****@*****.**') def test_remove_participants(self): logging.info("*** remove_participants") with mock.patch.object(self.space, 'remove_participant') as mocked: self.space.remove_participants(id='*id', persons=[]) self.assertFalse(mocked.called) class MySpace(Space): def on_init(self): self._persons = ['*****@*****.**', '*****@*****.**'] def remove_participant(self, id, person): self._persons.remove(person) space = MySpace(context=self.context) space.remove_participants(id='*id', persons=['*****@*****.**', '*****@*****.**']) self.assertEqual(space._persons, []) def test_remove_participant(self): logging.info("*** remove_participant") with self.assertRaises(NotImplementedError): self.space.remove_participant(id='*id', person='*****@*****.**') def test_walk_messages(self): logging.info("*** walk_messages") with self.assertRaises(NotImplementedError): message = next(self.space.walk_messages(id='*id')) def test_post_message(self): logging.info("*** post_message") with self.assertRaises(AssertionError): # missing id and person self.space.post_message(text="What's up, Doc?") with self.assertRaises(AssertionError): # too much: id and person self.space.post_message(id='1', person='2', text="What's up, Doc?") with self.assertRaises(NotImplementedError): self.space.post_message(id='*id', text="What's up, Doc?") with self.assertRaises(NotImplementedError): self.space.post_message(person='*****@*****.**', text="What's up, Doc?") def test_webhook(self): logging.info("*** webhook") with self.assertRaises(NotImplementedError): self.space.webhook() def test_register(self): logging.info("*** register") with self.assertRaises(NotImplementedError): self.space.register(hook_url='http://no.where/') def test_deregister(self): logging.info("*** deregister") self.space.deregister() def test_start(self): logging.info("*** start") space = Space(context=self.context) space.register = mock.Mock() space.pull = mock.Mock() space.start(hook_url='http:/who.knows/') space.register.assert_called_with(hook_url='http:/who.knows/') self.assertFalse(space.pull.called) class ExSpace(Space): def on_reset(self): self._bot_id = None def on_start(self): self._bot_id = 123 space = ExSpace(context=self.context) space.register = mock.Mock() space.pull = mock.Mock() space.PULL_INTERVAL = 0.01 space.start() time.sleep(0.1) while space._bot_id is None: time.sleep(0.1) while self.context.get('puller.counter', 0) < 4: time.sleep(0.1) self.context.set('general.switch', 'off') self.assertFalse(space.register.called) self.assertEqual(space._bot_id, 123) self.assertTrue(self.context.get('puller.counter') > 3) def test_run(self): logging.info("*** run") space = Space(context=self.context) space.pull = mock.Mock(side_effect=Exception('TEST')) space.run() self.assertEqual(self.context.get('puller.counter'), 0) space = Space(context=self.context) space.pull = mock.Mock(side_effect=KeyboardInterrupt('ctl-C')) space.run() self.assertEqual(self.context.get('puller.counter'), 0) def test_pull(self): logging.info("*** pull") with self.assertRaises(NotImplementedError): self.space.pull()
class BusTests(unittest.TestCase): def setUp(self): self.context = Context() self.context.set('general.switch', 'on') self.context.set('bus.address', 'tcp://127.0.0.1:6666') self.bus = Bus(context=self.context) def tearDown(self): del self.bus del self.context collected = gc.collect() if collected: logging.info("Garbage collector: collected %d objects." % (collected)) def test_bus_init(self): logging.info(u"***** bus/init") self.assertEqual(self.bus.DEFAULT_ADDRESS, 'tcp://127.0.0.1:5555') self.assertEqual(self.bus.context, self.context) def test_bus_check(self): logging.info(u"***** bus/check") self.context.set('bus.address', None) self.bus.check() self.assertEqual(self.context.get('bus.address'), self.bus.DEFAULT_ADDRESS) def test_bus_subscribe(self): logging.info(u"***** bus/subscribe") with self.assertRaises(AssertionError): subscriber = self.bus.subscribe(None) with self.assertRaises(AssertionError): subscriber = self.bus.subscribe([]) with self.assertRaises(AssertionError): subscriber = self.bus.subscribe(()) subscriber = self.bus.subscribe('channel') def test_bus_publish(self): logging.info(u"***** bus/publish") publisher = self.bus.publish() def test_subscriber_init(self): logging.info(u"***** subscriber/init") subscriber = Subscriber(context=self.context, channels='channel') self.assertEqual(subscriber.context, self.context) self.assertTrue(subscriber.socket is None) def test_subscriber_get(self): logging.info(u"***** subscriber/get") subscriber = self.bus.subscribe('dummy') subscriber.socket = mock.Mock() with mock.patch.object( subscriber.socket, 'recv', return_value='dummy {"hello": "world"}') as mocked: message = subscriber.get() self.assertEqual(message, {u'hello': u'world'}) def test_publisher_init(self): logging.info(u"***** publisher/init") publisher = Publisher(context=self.context) self.assertEqual(publisher.context, self.context) self.assertTrue(publisher.socket is None) def test_publisher_run(self): logging.info(u"***** publisher/run") publisher = Publisher(context=self.context) self.context.set('general.switch', 'off') publisher.run() self.context.set('general.switch', 'on') publisher.put('*weird', '*message') publisher.fan.put(None) publisher.run() def test_publisher_static_test(self): logging.info(u"***** publisher/static test") publisher = Publisher(context=self.context) publisher.DEFER_DURATION = 0.0 self.context.set('general.switch', 'on') publisher.start() publisher.join(0.1) if publisher.is_alive(): logging.info('Stopping publisher') self.context.set('general.switch', 'off') publisher.join() self.assertFalse(publisher.is_alive()) self.assertEqual(self.context.get('publisher.counter', 0), 0) def test_publisher_dynamic_test(self): logging.info(u"***** publisher/dynamic test") publisher = Publisher(context=self.context) self.context.set('general.switch', 'on') items = [ ('channel_A', "hello"), ('channel_B', "world"), ('channel_C', { "hello": "world" }), ] for (channel, message) in items: publisher.put(channel, message) publisher.fan.put(None) class MySocket(object): def __init__(self, context): self.context = context def send_string(self, item): pipe = self.context.get('pipe', []) pipe.append(item) self.context.set('pipe', pipe) def close(self): pass publisher.socket = MySocket(self.context) publisher.run() self.assertEqual(self.context.get('publisher.counter', 0), 3) self.assertEqual(self.context.get('pipe'), [ 'channel_A "hello"', 'channel_B "world"', 'channel_C {"hello": "world"}' ]) def test_publisher_put(self): logging.info(u"***** publisher/put") publisher = self.bus.publish() with self.assertRaises(AssertionError): publisher.put(None, 'message') with self.assertRaises(AssertionError): publisher.put('', 'message') with self.assertRaises(AssertionError): publisher.put([], 'message') with self.assertRaises(AssertionError): publisher.put((), 'message') with self.assertRaises(AssertionError): publisher.put('channel', None) with self.assertRaises(AssertionError): publisher.put('channel', '') with mock.patch.object(publisher.fan, 'put') as mocked: publisher.put('channel', 'message') mocked.assert_called_with('channel "message"') publisher.put(['channel'], 'message') mocked.assert_called_with('channel "message"') def test_life_cycle(self): logging.info(u"***** life cycle") class Listener(Process): def __init__(self, bus): Process.__init__(self) self.daemon = True self.bus = bus def run(self): subscriber = self.bus.subscribe('') logging.info(u"Starting subscriber") while self.bus.context.get('general.switch', 'off') == 'on': message = subscriber.get() if not message: time.sleep(0.001) continue self.bus.context.set('received', message) logging.info(u"- {}".format(message)) logging.info(u"Stopping subscriber") listener = Listener(self.bus) listener.start() publisher = self.bus.publish() publisher.start() for value in range(1, 10): publisher.put('channel', {'counter': value}) publisher.fan.put(None) publisher.join() time.sleep(0.5) self.bus.context.set('general.switch', 'off') time.sleep(0.5) listener.join()
class SparkSpaceTests(unittest.TestCase): def setUp(self): self.context = Context() self.ears = Queue() self.fan = Queue() self.space = SparkSpace(context=self.context, ears=self.ears, fan=self.fan) def tearDown(self): del self.space del self.fan del self.ears del self.context collected = gc.collect() if collected: logging.info("Garbage collector: collected %d objects." % (collected)) def test_on_init(self): logging.info("*** on_init") self.assertEqual(self.space.context.get('space.token'), None) self.assertEqual(self.space.api, None) self.assertEqual(self.space._last_message_id, 0) space = SparkSpace(context=self.context, token='b') self.assertEqual(space.context.get('space.token'), 'b') def test_configure(self): logging.info("*** configure") settings = { # from settings to member attributes 'space': { 'type': 'spark', 'room': 'My preferred room', 'participants': ['*****@*****.**', '*****@*****.**'], 'token': 'hkNWEtMJNkODVGlZWU1NmYtyY', } } self.space.configure(settings=settings) self.assertEqual(self.space.context.get('space.room'), 'My preferred room') self.assertEqual(self.space.configured_title(), 'My preferred room') self.assertEqual(self.space.context.get('space.participants'), ['*****@*****.**', '*****@*****.**']) self.assertEqual(self.space.context.get('space.token'), 'hkNWEtMJNkODVGlZWU1NmYtyY') self.space.context.clear() self.space.configure({ 'space': { 'type': 'spark', 'room': 'My preferred room', 'participants': '*****@*****.**', } }) self.assertEqual(self.space.context.get('space.room'), 'My preferred room') self.assertEqual(self.space.context.get('space.participants'), ['*****@*****.**']) with self.assertRaises(KeyError): # missing key self.space.context.clear() self.space.configure({ 'spark': { 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY', } }) def test_connect(self): logging.info("*** connect") def my_factory(access_token): return FakeApi(access_token=access_token) self.space.context.set('space.token', None) with self.assertRaises(AssertionError): self.space.connect() self.space.context.set('space.token', 'a') self.space.connect(factory=my_factory) self.assertEqual(self.space.api.token, 'a') self.assertEqual(self.space.audit_api, None) self.space.context.set('space.token', 'a') self.space.context.set('space.audit_token', 'b') self.space.connect(factory=my_factory) self.assertEqual(self.space.api.token, 'a') self.assertEqual(self.space.audit_api.token, 'b') def test_on_connect(self): logging.info("*** on_connect") self.space.api = FakeApi(me=FakeBot()) self.space.on_connect() self.assertTrue(self.space.api.people.me.called) self.assertEqual(self.context.get('bot.address'), '*****@*****.**') self.assertEqual(self.context.get('bot.name'), 'shelly') self.assertTrue(len(self.context.get('bot.id')) > 20) def test_list_group_channels(self): logging.info("*** list_group_channels") self.space.api = FakeApi() channels = self.space.list_group_channels() self.assertEqual(len(channels), 1) self.assertTrue(self.space.api.rooms.list.called) channel = channels[0] self.assertEqual(channel.id, '*id') self.assertEqual(channel.title, '*title') def test_create(self): logging.info("*** create") with self.assertRaises(AssertionError): self.space.create(title=None) with self.assertRaises(AssertionError): self.space.create(title='') with self.assertRaises(AssertionError): self.space.create(title='*title') self.space.api = FakeApi() channel = self.space.create(title='*title') self.assertTrue(self.space.api.rooms.create.called) self.assertEqual(channel.id, '*id') self.assertEqual(channel.title, '*title') def test_get_by_title(self): logging.info("*** get_by_title") with self.assertRaises(AssertionError): channel = self.space.get_by_title(None) with self.assertRaises(AssertionError): channel = self.space.get_by_title('') with self.assertRaises(AssertionError): channel = self.space.get_by_title('*no*api*anyway') self.space.api = FakeApi() channel = self.space.get_by_title('*does*not*exist') self.assertEqual(channel, None) self.assertTrue(self.space.api.rooms.list.called) channel = self.space.get_by_title('*title') self.assertEqual( channel, Channel({ "id": "*id", "is_direct": False, "is_group": True, "is_moderated": True, "is_team": False, "team_id": "*team", "title": "*title", "type": "group", })) class Intruder(object): def list(self, **kwargs): raise Exception('TEST') self.space.api.rooms = Intruder() channel = self.space.get_by_title('*title') self.assertEqual(channel, None) def test_get_by_id(self): logging.info("*** get_by_id") with self.assertRaises(AssertionError): channel = self.space.get_by_id(None) with self.assertRaises(AssertionError): channel = self.space.get_by_id('') with self.assertRaises(AssertionError): channel = self.space.get_by_id('*no*api*anyway') self.space.api = FakeApi() channel = self.space.get_by_id('*id') self.assertEqual( channel, Channel({ "id": "*id", "is_direct": False, "is_group": True, "is_moderated": True, "is_team": False, "team_id": "*team", "title": "*title", "type": "group", })) class Intruder(object): def get(self, label, **kwargs): raise Exception('TEST') self.space.api.rooms = Intruder() channel = self.space.get_by_id('*id') self.assertEqual(channel, None) def test_get_by_person(self): logging.info("*** get_by_person") with self.assertRaises(AssertionError): channel = self.space.get_by_person(None) with self.assertRaises(AssertionError): channel = self.space.get_by_person('') with self.assertRaises(AssertionError): channel = self.space.get_by_person('*no*api*anyway') self.space.api = FakeApi(room=FakeDirectRoom()) channel = self.space.get_by_person('Marcel Jones') self.assertEqual( channel, Channel({ "id": "*direct_id", "is_direct": True, "is_group": False, "is_moderated": False, "is_team": False, "team_id": None, "title": "Marcel Jones", "type": "direct", })) class Intruder(object): def list(self, **kwargs): raise Exception('TEST') self.space.api.rooms = Intruder() channel = self.space.get_by_person('Marcel Jones') self.assertEqual(channel, None) def test_update(self): logging.info("*** update") self.space.api = FakeApi() self.space.update(channel=FakeChannel()) def test_delete(self): logging.info("*** delete") # explicit id, room exists self.space.api = FakeApi() self.space.delete(id='*id') self.assertTrue(self.space.api.rooms.delete.called) # explicit id, room does not exists self.space.api = FakeApi() self.space.delete(id='*ghost*room') self.assertTrue(self.space.api.rooms.delete.called) def test_get_team(self): logging.info("*** get_team") class Team(object): name = '*name' id = '456' self.space.api = FakeApi(teams=[Team()]) team = self.space.get_team(name='*name') self.assertTrue(self.space.api.teams.list.called) self.assertEqual(team.name, '*name') self.assertEqual(team.id, '456') self.space.api = FakeApi(teams=[Team()]) team = self.space.get_team(name='*unknown') self.assertTrue(self.space.api.teams.list.called) self.assertEqual(team, None) def test_list_participants(self): logging.info("*** list_participants") self.space.api = FakeApi() self.space.list_participants(id='*id') self.assertTrue(self.space.api.memberships.list.called) def test_add_participants(self): logging.info("*** add_participants") with mock.patch.object(self.space, 'add_participant') as mocked: self.space.add_participants(id='*id', persons=['*****@*****.**']) mocked.assert_called_with(id='*id', person='*****@*****.**') def test_add_participant(self): logging.info("*** add_participant") self.space.api = FakeApi() self.space.add_participant(id='*id', person='*****@*****.**') self.assertTrue(self.space.api.memberships.create.called) def test_remove_participants(self): logging.info("*** remove_participants") with mock.patch.object(self.space, 'remove_participant') as mocked: self.space.remove_participants(id='*id', persons=['*****@*****.**']) mocked.assert_called_with(id='*id', person='*****@*****.**') def test_remove_participant(self): logging.info("*** remove_participant") self.space.api = FakeApi() self.space.remove_participant(id='*id', person='*****@*****.**') self.assertTrue(self.space.api.memberships.delete.called) def test_post_message(self): logging.info("*** post_message") self.space.api = FakeApi() self.space.post_message(id='*id', text='hello world') self.assertTrue(self.space.api.messages.create.called) self.space.api = FakeApi() self.space.post_message(person='*****@*****.**', text='hello world') self.assertTrue(self.space.api.messages.create.called) self.space.api = FakeApi() self.space.post_message(id='*id', content='hello world') self.assertTrue(self.space.api.messages.create.called) self.space.api = FakeApi() self.space.post_message(person='*****@*****.**', content='hello world') self.assertTrue(self.space.api.messages.create.called) self.space.api = FakeApi() with self.assertRaises(AssertionError): self.space.post_message(text='hello world', content='hello world', file='./test_messages/sample.png') self.space.api = FakeApi() with self.assertRaises(AssertionError): self.space.post_message(id='*id', person='*****@*****.**', text='hello world', content='hello world', file='./test_messages/sample.png') self.space.api = FakeApi() self.space.post_message(id='*id', text='hello world', content='hello world', file='./test_messages/sample.png') self.assertTrue(self.space.api.messages.create.called) self.space.api = FakeApi() self.space.post_message(person='*****@*****.**', text='hello world', content='hello world', file='./test_messages/sample.png') self.assertTrue(self.space.api.messages.create.called) def test_register(self): logging.info("*** register") self.context.set('bot.id', '*id') self.context.set('spark.token', '*token') self.space.api = FakeApi() self.space.register('*hook') self.assertTrue(self.space.api.webhooks.create.called) self.assertFalse(self.context.get('audit.has_been_armed')) self.space.api = FakeApi() self.space.audit_api = FakeApi() self.space.register('*hook') self.assertTrue(self.space.api.webhooks.create.called) self.assertTrue(self.context.get('audit.has_been_armed')) def test_deregister(self): logging.info("*** deregister") self.space.api = FakeApi() self.context.set('bot.id', '*id') self.space.deregister() self.assertTrue(self.space.api.webhooks.list.called) def test_run(self): logging.info("*** run") self.space.api = FakeApi() self.space.PULL_INTERVAL = 0.001 mocked = mock.Mock(return_value=[]) self.space.pull = mocked p = self.space.start() p.join(0.01) if p.is_alive(): logging.info('Stopping puller') self.context.set('general.switch', 'off') p.join() self.assertFalse(p.is_alive()) def test_webhook(self): logging.info("*** webhook") fake_message = { u'status': u'active', u'resource': u'messages', u'name': u'shellbot-messages', u'created': u'2017-07-30T20:14:24.050Z', u'appId': u'Y2lzY29zcGFyazovL3VzLmM3ZDUxNWNiNGEwY2M5MWFh', u'id': u'Y2lzY29zcGFyazovL3VzjI0MTM2ZjgwY2Yy', u'orgId': u'Y2lzY29zcGFyazovL3VYjU1ZS00ODYzY2NmNzIzZDU', u'createdBy': u'Y2lzY29zcGFyazovL3VzLS01ZGI5M2Y5MjI5MWM', u'targetUrl': u'http://0dab1.ngrok.io/hook', u'ownedBy': u'creator', u'actorId': u'Y2lzY29zcGFyazovL3VzL1BFkyMzU', u'data': { u'roomType': u'group', u'created': u'2017-07-30T20:14:50.882Z', u'personId': u'Y2lzY29zcGFyayYi1mYWYwZWQwMjkyMzU', u'personEmail': u'*****@*****.**', u'mentionedPeople': [u'Y2lzY29zcGFyazovL3VGI5M2Y5MjI5MWM'], u'roomId': u'Y2lzY29zcGFyazovL3VzL1NzUtYzc2ZDMyOGY0Y2Rj', u'id': '*123', }, u'event': u'created', } self.space.api = FakeApi() self.assertEqual(self.space.webhook(fake_message), 'OK') self.assertTrue(self.space.api.messages.get.called) data = self.space.ears.get() self.assertEqual( yaml.safe_load(data), { 'text': '*message', 'content': '*message', 'from_id': None, 'from_label': None, 'hook': 'shellbot-messages', 'stamp': '2017-07-19T05:29:23.962Z', 'created': '2017-07-19T05:29:23.962Z', 'channel_id': None, 'type': 'message', 'is_direct': False, 'mentioned_ids': [] }) with self.assertRaises(Exception): print(self.space.ears.get_nowait()) with self.assertRaises(Exception): print(self.space.fan.get_nowait()) fake_message = { u'status': u'active', u'resource': u'messages', u'name': u'shellbot-audit', u'created': u'2017-07-30T20:25:29.924Z', u'appId': u'Y2lzY29zcGFyazovL3VzL0FQUE2YyNjZhYmY2NmM5OTllYzFm', u'id': u'Y2lzY29zcGFyazovL3VzL1dFC00NzllLTg0MDQtZGQ2NGJiNTk3Nzdi', u'orgId': u'Y2lzY29zcGFyazovL3VzL09SR0FOSVpBVY2NmNzIzZDU', u'createdBy': u'Y2lzY29zcGFyazovL3VzL1BFTTIyYi1mYWYwZWQwMjkyMzU', u'targetUrl': u'http://0dab1.ngrok.io/hook', u'ownedBy': u'creator', u'actorId': u'Y2lzY29zcGFyazovL3VzLM2Y5MjI5MWM', u'data': { u'files': [u'http://hydra-a5.wbx2.com/contents/Y2lzY29zcGFWY5LzA'], u'roomType': u'group', u'created': u'2017-07-30T20:25:33.803Z', u'personId': u'Y2lzY29zcGFyazovL3VzL1BFT5M2Y5MjI5MWM', u'personEmail': u'*****@*****.**', u'roomId': u'Y2lzY29zcGFyazovL3VzL1JPTyNmFhNWYxYTY4', u'id': u'*123', }, u'event': u'created', } self.space.audit_api = FakeApi() self.assertEqual(self.space.webhook(fake_message), 'OK') self.assertTrue(self.space.audit_api.messages.get.called) data = self.space.fan.get() self.assertEqual( yaml.safe_load(data), { 'text': '*message', 'content': '*message', 'from_id': None, 'from_label': None, 'hook': 'shellbot-audit', 'stamp': '2017-07-19T05:29:23.962Z', 'created': '2017-07-19T05:29:23.962Z', 'channel_id': None, 'type': 'message', 'is_direct': False, 'mentioned_ids': [] }) with self.assertRaises(Exception): print(self.space.ears.get_nowait()) with self.assertRaises(Exception): print(self.space.fan.get_nowait()) def test_pull(self): logging.info("*** pull") self.space.api = FakeApi(messages=[FakeMessage()]) self.assertEqual(self.space._last_message_id, 0) self.space.pull() self.assertEqual(self.context.get('puller.counter'), 1) self.assertTrue(self.space.api.messages.list.called) self.assertEqual(self.space._last_message_id, '*123') self.space.pull() self.assertEqual(self.context.get('puller.counter'), 2) self.assertEqual(self.space._last_message_id, '*123') self.space.pull() self.assertEqual(self.context.get('puller.counter'), 3) self.assertEqual(self.space._last_message_id, '*123') self.assertEqual( yaml.safe_load(self.ears.get()), { 'text': '*message', 'content': '*message', 'from_id': None, 'from_label': None, 'hook': 'pull', 'stamp': '2017-07-19T05:29:23.962Z', 'created': '2017-07-19T05:29:23.962Z', 'channel_id': None, 'type': 'message', 'is_direct': False, 'mentioned_ids': [] }) with self.assertRaises(Exception): print(self.ears.get_nowait()) def test_on_message(self): logging.info("*** on_message") class MySpace(SparkSpace): def name_attachment(self, url, token=None): return 'some_file.pdf' def get_attachment(self, url, token=None): return b'hello world' self.space = MySpace(context=self.context) self.space.on_message(my_message, self.ears) message = my_message.copy() message.update({"type": "message"}) message.update({"content": message['text']}) message.update({"attachment": "some_file.pdf"}) message.update({"url": "http://www.example.com/images/media.png"}) message.update({"from_id": '*matt*id'}) message.update({"from_label": '*****@*****.**'}) message.update({'is_direct': False}) message.update({"mentioned_ids": ['*matt*id', '*julie*id']}) message.update({"channel_id": '*id1'}) message.update({"stamp": '2015-10-18T14:26:16+00:00'}) self.maxDiff = None self.assertEqual(yaml.safe_load(self.ears.get()), message) self.space.on_message(my_private_message, self.ears) message = my_private_message.copy() message.update({"type": "message"}) message.update({"content": message['text']}) message.update({"from_id": '*foo*id'}) message.update({"from_label": '*****@*****.**'}) message.update({'is_direct': True}) message.update({"mentioned_ids": []}) message.update({"channel_id": '*direct*id'}) message.update({"stamp": '2017-07-22T16:49:22.008Z'}) self.maxDiff = None self.assertEqual(yaml.safe_load(self.ears.get()), message) with self.assertRaises(Exception): print(self.ears.get_nowait()) def test_download_attachment(self): logging.info("*** download_attachment") class MySpace(SparkSpace): def name_attachment(self, url, token=None): return 'some_file.pdf' def get_attachment(self, url, token=None): return BytesIO(b'hello world') space = MySpace(context=self.context) outcome = space.download_attachment(url='/dummy') with open(outcome, "rb") as handle: self.assertEqual(handle.read(), space.get_attachment('/dummy').read()) try: os.remove(outcome) except: pass def test_name_attachment(self): logging.info("*** name_attachment") class MyResponse(object): def __init__(self, status_code=200, headers={}): self.status_code = status_code self.headers = headers self.space.token = None response = MyResponse(headers={'Content-Disposition': 'who cares'}) self.assertEqual( self.space.name_attachment(url='/dummy', response=response), 'downloadable') self.space.token = '*void' response = MyResponse( headers={'Content-Disposition': 'filename="some_file.pdf"'}) self.assertEqual( self.space.name_attachment(url='/dummy', response=response), 'some_file.pdf') self.space.token = None response = MyResponse( status_code=400, headers={'Content-Disposition': 'filename="some_file.pdf"'}) with self.assertRaises(Exception): name = self.space.name_attachment(url='/dummy', response=response) def test_get_attachment(self): logging.info("*** get_attachment") class MyResponse(object): def __init__(self, status_code=200, headers={}): self.status_code = status_code self.headers = headers self.encoding = 'encoding' self.content = b'content' self.space.token = None response = MyResponse(headers={}) content = self.space.get_attachment(url='/dummy', response=response).getvalue() self.assertEqual(content, b'content') self.space.token = '*void' response = MyResponse(headers={}) content = self.space.get_attachment(url='/dummy', response=response).getvalue() self.assertEqual(content, b'content') self.space.token = None response = MyResponse(status_code=400, headers={}) with self.assertRaises(Exception): content = self.space.get_attachment(url='/dummy', response=response) def test_on_join(self): logging.info("*** on_join") self.space.on_join(my_join, self.ears) item = my_join.copy() item.update({"type": "join"}) item.update( {"actor_id": 'Y2lzY29zcGFyazovL3VRiMTAtODZkYy02YzU0Yjg5ODA5N2U'}) item.update({"actor_address": '*****@*****.**'}) item.update({"actor_label": 'Foo Bar'}) item.update({ "channel_id": 'Y2lzY29zcGFyazovL3VzL1JP3LTk5MDAtMDU5MDI2YjBiNDUz' }) item.update({"stamp": '2017-05-31T21:25:30.424Z'}) self.maxDiff = None self.assertEqual(yaml.safe_load(self.ears.get()), item) def test_on_leave(self): logging.info("*** on_leave") self.space.on_leave(my_leave, self.ears) item = my_leave.copy() item.update({"type": "leave"}) item.update( {"actor_id": 'Y2lzY29zcGFyazovL3VRiMTAtODZkYy02YzU0Yjg5ODA5N2U'}) item.update({"actor_address": '*****@*****.**'}) item.update({"actor_label": 'Foo Bar'}) item.update({ "channel_id": 'Y2lzY29zcGFyazovL3VzL1JP3LTk5MDAtMDU5MDI2YjBiNDUz' }) item.update({"stamp": '2017-05-31T21:25:30.424Z'}) self.maxDiff = None self.assertEqual(yaml.safe_load(self.ears.get()), item) def test__to_channel(self): logging.info("*** _to_channel") channel = self.space._to_channel(FakeRoom()) self.assertEqual(channel.id, '*id') self.assertEqual(channel.title, '*title') self.assertFalse(channel.is_direct) self.assertTrue(channel.is_group) self.assertFalse(channel.is_team) self.assertTrue(channel.is_moderated) channel = self.space._to_channel(FakeDirectRoom()) self.assertEqual(channel.id, '*direct_id') self.assertEqual(channel.title, 'Marcel Jones') self.assertTrue(channel.is_direct) self.assertFalse(channel.is_group) self.assertFalse(channel.is_team) self.assertFalse(channel.is_moderated) channel = self.space._to_channel(FakeTeamRoom()) self.assertEqual(channel.id, '*team_id') self.assertEqual(channel.title, '*team_title') self.assertFalse(channel.is_direct) self.assertTrue(channel.is_group) self.assertTrue(channel.is_team) self.assertFalse(channel.is_moderated)
'label': u'Terminated', 'message': u'Process is closed, yet conversation can continue', }, ], } context = Context(settings) context.check('server.trigger', '/trigger') context.check('server.hook', '/hook') engine = Engine( # use Cisco Spark and setup the environment type='spark', context=context, configure=True, commands=['shellbot.commands.step', 'shellbot.commands.close'], machine_factory=MyFactory(steps=context.get('process.steps')), ears=Queue(), ) server = Server(context=context, check=True) # set web front-end server.add_route( Notifier(queue=engine.ears, notification={ 'type': 'event', 'trigger': 'click' }, route=context.get('server.trigger'))) server.add_route( Wrapper(callable=engine.get_hook(), route=context.get('server.hook')))
class SpaceFactoryTests(unittest.TestCase): def setUp(self): self.context = Context() def tearDown(self): del self.context collected = gc.collect() if collected: logging.info("Garbage collector: collected %d objects." % (collected)) def test_build_space(self): logging.info("***** build generic space from settings") self.context.apply( settings={ # from settings to member attributes 'space': { 'title': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODVGlZWU1NmYtyY', 'webhook': "http://73a1e282.ngrok.io", } }) space = SpaceFactory.build(context=self.context) self.assertEqual(self.context.get('space.title'), 'My preferred channel') self.assertEqual(space.configured_title(), 'My preferred channel') def test_build_local(self): logging.info("***** build local space from settings") self.context.apply( settings={ # from settings to member attributes 'space': { 'title': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'input': ['help', 'version'], } }) space = SpaceFactory.build(context=self.context) self.assertEqual(self.context.get('space.title'), 'My preferred channel') self.assertEqual(space.configured_title(), 'My preferred channel') def test_build_spark(self): logging.info("***** build Cisco Spark space from settings") self.context.apply( settings={ # from settings to member attributes 'space': { 'type': 'spark', 'room': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODVGlZWU1NmYtyY', } }) space = SpaceFactory.build(context=self.context) self.assertEqual(space.context.get('space.token'), 'hkNWEtMJNkODVGlZWU1NmYtyY') self.assertEqual(space.context.get('space.room'), 'My preferred channel') self.assertEqual(space.configured_title(), 'My preferred channel') def test_sense_space(self): logging.info("***** sense generic space") self.context.apply( settings={ # sense='space' 'space': { 'room': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY', 'fuzzy_token': '$MY_FUZZY_SPARK_TOKEN', } }) self.assertEqual(SpaceFactory.sense(self.context), 'space') def test_sense_local(self): logging.info("***** sense local space") self.context.apply( settings={ # sense='local' 'space': { 'type': 'local', 'title': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'input': ['help', 'version'], } }) self.assertEqual(SpaceFactory.sense(self.context), 'local') def test_sense_spark(self): logging.info("***** sense Cisco Spark space") self.context.apply( settings={ # sense='spark' 'space': { 'type': 'spark', 'room': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY', 'fuzzy_token': '$MY_FUZZY_SPARK_TOKEN', } }) self.assertEqual(SpaceFactory.sense(self.context), 'spark') def test_sense_void(self): logging.info("***** sense nothing on bad configuration") self.context.apply(settings={ # no recognizable space type 'space': { 'type': 'not_a_space_type', 'room': 'My preferred channel', 'participants': ['*****@*****.**', '*****@*****.**'], 'team': 'Anchor team', 'token': 'hkNWEtMJNkODk3ZDZLOGQ0OVGlZWU1NmYtyY', 'fuzzy_token': '$MY_FUZZY_SPARK_TOKEN', }, }) with self.assertRaises(ValueError): SpaceFactory.sense(self.context) def test_get_space(self): logging.info("***** get generic space") space = SpaceFactory.get(type='space') space = SpaceFactory.get(type='space', context='c', weird='w') self.assertEqual(space.context, 'c') with self.assertRaises(AttributeError): self.assertEqual(space.weird, 'w') def test_get_local(self): logging.info("***** get local space") space = SpaceFactory.get(type='local', input=['hello', 'world']) self.assertEqual(space.participants, []) def test_get_spark(self): logging.info("***** get Cisco Spark space") space = SpaceFactory.get(type='spark', context=self.context, token='b') self.assertEqual(space.context.get('space.token'), 'b') def test_get_unknown(self): logging.info("***** get invalid space") with self.assertRaises(ValueError): space = SpaceFactory.get(type='*unknown', ex_token='b', ex_ears='c')
class StoreFactoryTests(unittest.TestCase): def setUp(self): self.context = Context() def tearDown(self): del self.context collected = gc.collect() if collected: logging.info("Garbage collector: collected %d objects." % (collected)) def test_build_memory(self): store = StoreFactory.build(context=self.context) self.assertTrue(isinstance(store, MemoryStore)) def test_build_sqlite(self): self.context.apply(settings={ # from settings to member attributes 'sqlite': { 'db': 'self.store.db', } }) store = StoreFactory.build(context=self.context) self.assertTrue(isinstance(store, SqliteStore)) self.assertEqual(self.context.get('sqlite.db'), 'self.store.db') def test_sense(self): self.context.apply(settings={ # default is 'memory' 'oracle': { 'db': 'self.store.db', } }) self.assertEqual(StoreFactory.sense(self.context), 'memory') self.context.clear() self.context.apply(settings={ # sense='sqlite' 'sqlite': { 'db': 'self.store.db', } }) self.assertEqual(StoreFactory.sense(self.context), 'sqlite') def test_get_memory(self): store = StoreFactory.get(type='memory') self.assertTrue(isinstance(store, MemoryStore)) store = StoreFactory.get(type='memory', context=self.context, weird='w') self.assertEqual(store.context, self.context) with self.assertRaises(AttributeError): self.assertEqual(store.weird, 'w') def test_get_sqlite(self): store = StoreFactory.get(type='sqlite', context=self.context) self.assertTrue(isinstance(store, SqliteStore)) self.assertEqual(store.context, self.context) def test_get_unknown(self): with self.assertRaises(ValueError): store = StoreFactory.get(type='*unknown', ex_token='b', ex_ears='c')