view test.py @ 30:6b0a17f31342

we should work w/ python 2.6+ now
author Atul Varma <varmaa@toolness.com>
date Thu, 24 Dec 2009 14:27:56 -0800
parents ce19838a318d
children
line wrap: on
line source

import unittest
import StringIO
from copy import deepcopy
from datetime import datetime, timedelta

import pymongo
import bzapi

# Easier than having to duplicate import logic...
json = bzapi.json

connection = pymongo.Connection('localhost', 27017)
testdb = connection.bzapi_testing_db

class MiscTests(unittest.TestCase):
    def test_split_seq_with_tiny_seq(self):
        self.assertEqual(repr(bzapi.split_seq([1], 2)),
                         '[[1]]')

    def test_split_seq_with_imperfect_split(self):
        self.assertEqual(repr(bzapi.split_seq([1,2,3,4,5], 2)),
                         '[[1, 2], [3, 4], [5]]')

    def test_split_seq_with_perfect_split(self):
        self.assertEqual(repr(bzapi.split_seq([1,2,3,4], 2)),
                         '[[1, 2], [3, 4]]')

class TimestampTests(unittest.TestCase):
    def test_datetime_from_iso(self):
        date = bzapi.datetime_from_iso('2009-06-11T22:31:24Z')
        self.assertEqual(str(date), '2009-06-11 22:31:24')

    def test_datetime_from_rfc1123(self):
        date = bzapi.datetime_from_rfc1123('Wed, 23 Dec 2009 20:42:59 GMT')
        self.assertEqual(str(date), '2009-12-23 20:42:59')

class OpenUrlTests(unittest.TestCase):
    class FakeUrllib2(object):
        class FakeRequest(object):
            def __init__(self, url):
                self.url = url

            def add_header(self, name, value):
                pass

        def __init__(self):
            self._responses = {}

        def Request(self, url):
            return self.FakeRequest(url)

        def set_url(self, url, response):
            if not isinstance(response, basestring):
                response = json.dumps(response)
            self._responses[url] = response

        def urlopen(self, request):
            return StringIO.StringIO(self._responses[request.url])

    def test_open_url_works_without_query_args(self):
        urllib2 = self.FakeUrllib2()
        urllib2.set_url('http://foo/', 'boo')
        self.assertEqual(
            bzapi.open_url(url='http://foo/',
                           headers={'Content-Type': 'text/plain'},
                           urllib2=urllib2).read(),
            'boo'
            )

    def test_open_url_works_with_query_args(self):
        urllib2 = self.FakeUrllib2()
        urllib2.set_url('http://foo/?blah=hi+there', 'meh')
        self.assertEqual(
            bzapi.open_url(url='http://foo/',
                           query_args={'blah': 'hi there'},
                           headers={'Content-Type': 'text/plain'},
                           urllib2=urllib2).read(),
            'meh'
            )

class _MongoTestCase(unittest.TestCase):
    _collections = []

    def _reset_collections(self):
        for name in self._collections:
            testdb[name].remove({})

    def setUp(self):
        self._reset_collections()

    def tearDown(self):
        self._reset_collections()

class CachedSearchTests(_MongoTestCase):
    class ImpartialObserver(object):
        def __init__(self):
            self.history = []

        def notify(self, info):
            self.history.append(info)

    class FakeApi(object):
        def __init__(self):
            self._bugs = {}
            self._time = bzapi.datetime_from_iso('2009-01-01T00:00:00Z')

        def fake_time_travel(self, **kwargs):
            self._time += timedelta(**kwargs)

        def update_fake_bug(self, **info):
            bug = self._bugs[info['id']]
            bug.update(info)
            bug['last_change_time'] = bzapi.datetime_to_iso(self._time)

        def add_fake_bug(self, **info):
            for name in ['last_change_time', 'creation_time']:
                if name not in info:
                    info[name] = bzapi.datetime_to_iso(self._time)
            self._bugs[info['id']] = info

        def get(self, url, **kwargs):
            if url != '/bug':
                raise ValueError(url)
            if 'id' in kwargs and kwargs['id_mode'] == 'include':
                ids = kwargs['id'].split(",")
                bugs = [self._bugs[bugid] for bugid in ids]
            else:
                bugs = self._bugs.values()
            bugs = deepcopy(bugs)
            if kwargs.get('comments') != '1':
                for info in bugs:
                    if 'comments' in info:
                        del info['comments']
            return {'data': {'bugs': bugs},
                    'date': self._time}

    _collections = ['bugs']

    def setUp(self):
        _MongoTestCase.setUp(self)
        self.api = self.FakeApi()
        self.search = bzapi.CachedSearch(self.api, testdb.bugs)
        self.observer = self.ImpartialObserver()
        self.search.add_observer(self.observer)

    def test_update_with_no_bugs_does_not_crash(self):
        self.search.update()
        self.assertEqual(testdb.bugs.find().count(), 0)

    def test_update_with_one_bug_adds_it_to_collection(self):
        self.api.add_fake_bug(id='1034', comments='blah')
        self.search.update()
        self.assertEqual(testdb.bugs.find({'comments': 'blah'}).count(), 1)

    def test_one_bug_update_notifies_observers(self):
        self.api.add_fake_bug(id='1034')
        self.search.update()
        self.api.fake_time_travel(days=1)
        self.api.update_fake_bug(id='1034', comments='yo')
        self.search.update()
        self.assertEqual(len(self.observer.history), 2)

    def test_one_bug_addition_notifies_observers(self):
        self.api.add_fake_bug(id='1034')
        self.assertEqual(len(self.observer.history), 0)
        self.search.update()
        self.assertEqual(len(self.observer.history), 1)
        self.assertEqual(self.observer.history[0]['bug'], '1034')

    def test_no_bug_changes_do_not_notify_observers(self):
        self.api.add_fake_bug(id='1034')
        self.search.update()
        self.assertEqual(len(self.observer.history), 1)

        self.api.fake_time_travel(days=1)
        self.search.update()
        self.assertEqual(len(self.observer.history), 1)

class ApiTests(_MongoTestCase):
    class FakeOpenUrl(object):
        def __init__(self):
            self._responses = {}

        def set(self, url, query_args, response):
            if not isinstance(response, basestring):
                response = json.dumps(response)
            self._responses[url + repr(query_args)] = response

        def __call__(self, url, headers, query_args=None):
            response = self._responses[url + repr(query_args)]
            return StringIO.StringIO(response)

    _FAKE_CONFIG = {'product': {}}

    _collections = ['api']

    def setUp(self):
        _MongoTestCase.setUp(self)
        self.config = deepcopy(self._FAKE_CONFIG)

    def _get_basic_fake_api(self, **kwargs):
        opener = self.FakeOpenUrl()
        opener.set('http://foo/latest/configuration', kwargs,
                   self.config)
        api = bzapi.BugzillaApi('http://foo/latest', testdb.api,
                                open_url=opener, **kwargs)
        return api

    def test_bzapi_uses_username_and_password(self):
        api = self._get_basic_fake_api(username='foo',
                                       password='bar')
        api._open_url.set('http://foo/latest/stuff',
                          {'username': 'foo',
                           'password': 'bar'},
                          {})
        api.get('/stuff')

    def test_bzapi_raises_err_on_bad_component(self):
        self.config['product']['Mozilla Labs'] = {'component': {'Jetpack': {}}}
        api = self._get_basic_fake_api()
        self.assertRaises(ValueError,
                          api.get,
                          '/blah',
                          product='Mozilla Labs',
                          component='nonexistent')

    def test_bzapi_raises_err_on_bad_product(self):
        api = self._get_basic_fake_api()
        self.assertRaises(ValueError,
                          api.get,
                          '/blah',
                          product='nonexistent')

    def test_bzapi_validates_product_and_component(self):
        self.config['product']['Mozilla Labs'] = {'component': {'Jetpack': {}}}
        api = self._get_basic_fake_api()
        api._open_url.set('http://foo/latest/stuff',
                          {'product': 'Mozilla Labs',
                           'component': 'Jetpack'},
                          {})
        api.get('/stuff', product='Mozilla Labs', component='Jetpack')

    def test_bzapi_removes_dots_from_config(self):
        self.config['product']['addons.mozilla.org'] = {}
        api = self._get_basic_fake_api()
        self.assertTrue('addons_DOT_mozilla_DOT_org' in api.config['product'])

if __name__ == '__main__':
    unittest.main()