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!')
Exemple #2
0
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)
Exemple #3
0
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()
Exemple #4
0
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()
Exemple #5
0
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)
Exemple #6
0
                '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')