Exemple #1
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 #2
0
                'participants': '*****@*****.**',
            },
            {
                'label': u'Level 3',
                'message': u'Escalation to decision stakeholders',
                'participants': '*****@*****.**',
            },
            {
                '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,