Example #1
0
class DatabaseConnector:
    """Base class for establishing connection with database, creating and dropping tables"""
    def __init__(self, database_name='./task-manager.db'):
        self.database_name = database_name
        self.database = SqliteDatabase(database_name)
        self.connected = False
        database_proxy.initialize(self.database)
        self.create_tables()

    def create_tables(self):
        if not self.connected:
            self.database.connect()
            self.connected = True
        Category.create_table(True)
        Notification.create_table(True)
        Task.create_table(True)
        TaskPlan.create_table(True)
        UsersReadTasks.create_table(True)
        UsersWriteTasks.create_table(True)

    def drop_tables(self):
        self.database.drop_tables([
            Task, UsersReadTasks, UsersWriteTasks, Category, Notification,
            TaskPlan
        ])
        self.database.close()
        self.connected = False
class NonDeterminismCatcher:

    __db = None
    __logging = None

    def __init__(self, logger) -> None:
        self.__db = SqliteDatabase('non_determinism_quic.db')
        self.__db.connect()
        self.__db.drop_tables(
            [LearningRunModel, NonDeterministicResponseModel])
        self.__db.create_tables(
            [LearningRunModel, NonDeterministicResponseModel])
        self.__logging = logger
        logger = logging.getLogger('peewee')
        logger.addHandler(logging.StreamHandler())
        logger.setLevel(logging.DEBUG)

    def add_run(self, q, res):
        # Check if there is already a record with this query
        try:
            if not res:
                res = "---"
            previous_run = LearningRunModel.get(LearningRunModel.run == q)
            self.__logging.info("Received query {}".format(q))
            if not previous_run.result == res:
                self.__logging.info("Not deterministic with {}".format(
                    previous_run.result))
                NonDeterministicResponseModel(run=q, result=res).save()
        except LearningRunModel.DoesNotExist:
            self.__logging.info("New run inserted.")
            LearningRunModel(run=q, result=res).save()
Example #3
0
def create_db():
    import os
    if not ('HEROKU' in os.environ):
        db = SqliteDatabase('sender.sqlite')
        db.connect(True)

        db.drop_tables([Account, Subscription, Messenger, AccessToken])
        db.create_tables([Account, Subscription, Messenger, AccessToken])

        vk = Messenger.create(name='VK', cost=200)
        vk.save()

        telegram = Messenger.create(name='Telegram', cost=200)
        telegram.save()

    else:
        init_db()

        db_proxy.connect(True)
        print('CONNECTED')

        db_proxy.create_tables([AdminPage, TargetGroup, UserPage, SenderPage],
                               safe=True)

        print('before AdminPage')
        yuri = AdminPage(vkid=142872618)
        yuri.save()

        print('before db.close()')
        db_proxy.close()

        return 'DB is created!'
Example #4
0
def create_db():
    import os
    if not ('DYNO' in os.environ):
        db = SqliteDatabase('../sender.sqlite')
        db.connect(True)

        db.drop_tables([AdminPage, TargetGroup, UserPage, SenderPage])
        db.create_tables([AdminPage, TargetGroup, UserPage, SenderPage])

        yuri = AdminPage(vkid=142872618)
        yuri.save()
    else:
        init_db()

        db_proxy.connect(True)
        print('CONNECTED')
        # TODO сделать так, чтобы дубликаты не добавлялись
        db_proxy.create_tables([AdminPage, TargetGroup, UserPage, SenderPage],
                               safe=True)

        print('before AdminPage')
        yuri = AdminPage(vkid=142872618)
        yuri.save()

        print('before db.close()')
        db_proxy.close()

        return 'DB is created!'
Example #5
0
def setup_db_before_test():
    """Sets up database automatically before each test"""
    _db = SqliteDatabase(":memory:")
    with _db.bind_ctx(MODELS):
        _db.create_tables(MODELS)
        yield _db
        _db.drop_tables(MODELS)
Example #6
0
def create_relations():
    # запоминаем все используемые в бд модели
    models = [User, RunSettings]

    # чистим базу данных
    print('чистим базу данных')
    db = SqliteDatabase('data.db')
    try:
        db.drop_tables(models)
    except OperationalError:
        pass

    # создаем таблицы в бд
    print('\nсоздаем модели в бд:')
    for i in models:
        print(i)
        i.create_table()

    # добавляем пользователя
    print('\nдобавляем пользователя')
    admin_user = User(mail="*****@*****.**", password=get_hash('1'), port=56001)
    admin_user.save()

    test_user = User(mail="*****@*****.**", password=get_hash('1'), port=9701)
    test_user.save()
class TestArtRoutes(TestCase):
    def setUp(self):
        database_config.db_path = 'test_db.sqlite'
        self.database = SqliteDatabase(database_config.db_path,
                                       pragmas={'foreign_keys': 1})

        self.database.drop_tables([Art, Artist])
        self.database.create_tables([Art, Artist])

        self.test_app = app.test_client()

    def test_add_artist(self):
        response = self.test_app.post('/artists',
                                      data={
                                          'name': 'cheese',
                                          'email_address':
                                          '*****@*****.**'
                                      },
                                      follow_redirects=True)

        # response is a stream of bytes, decode into a string
        response_text = response.data.decode('utf-8')

        # Is data on page? Could also assert data is in specific HTML elements with a little more work
        # A HTML parser like Beautiful Soup could help https://www.crummy.com/software/BeautifulSoup/bs4/doc/
        self.assertIn('cheese', response_text)
        self.assertIn('*****@*****.**', response_text)

        # Flash message shown?
        self.assertIn('The new artist has been added!', response_text)

        # new artist in DB?
        new_artist = Artist.get_or_none(
            Artist.name == 'cheese'
            and Artist.email_address == '*****@*****.**')
        self.assertIsNotNone(new_artist)

    def test_no_duplicate_artist(self):
        self.ats1 = Artist.create(name='ats1',
                                  email_address='*****@*****.**').save()
        response = self.test_app.post('/artists',
                                      data={
                                          'name': 'ats1',
                                          'email_address': '*****@*****.**'
                                      })

        response_text = response.data.decode('utf-8')

        # Flash message?
        self.assertIn('Artist ats1 has already been added.', response_text)

        # Still only one artist in DB?
        artist_count = Artist.select().count()
        self.assertEqual(1, artist_count)

        # artist with duplicate name not added
        new_artist = Artist.get_or_none(
            Artist.name == 'ats1' and Artist.email_address == '*****@*****.**')
        self.assertIsNone(new_artist)
Example #8
0
def db_connection():
    models = [Metric]
    db = SqliteDatabase(':memory:')
    with db:
        db.bind(models)
        db.create_tables(models)
        yield db
        db.drop_tables(models)
Example #9
0
def db_connection():
    models = [ClubUser, ClubMessage]
    db = SqliteDatabase(':memory:')
    with db:
        db.bind(models)
        db.create_tables(models)
        yield db
        db.drop_tables(models)
def db_connection():
    models = [Event, EventSpeaking, MessageAuthor]
    db = SqliteDatabase(':memory:')
    with db:
        db.bind(models)
        db.create_tables(models)
        yield db
        db.drop_tables(models)
Example #11
0
def app():
    app = create_app({"TESTING": True})

    database = SqliteDatabase(get_db_path())
    database.create_tables([Poll, Choice, VoteCast])

    yield app

    database.drop_tables([Poll, Choice, VoteCast])
 def test_db_closure(*args, **kwargs):
     test_db = SqliteDatabase(":memory:")
     with test_db.bind_ctx(dbs):
         test_db.create_tables(dbs)
         try:
             func(*args, **kwargs)
         finally:
             test_db.drop_tables(dbs)
             test_db.close()
Example #13
0
class ValveDriverTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        fakesleep.monkey_patch()
        SetTestMode()

    @classmethod
    def tearDownClass(cls):
        fakesleep.monkey_restore()

    def setUp(self):
        self.test_db = SqliteDatabase(':memory:')
        self.test_db.bind(MODELS)
        self.test_db.connect()
        self.test_db.create_tables(MODELS)

    def tearDown(self):
        self.test_db.drop_tables(MODELS)
        self.test_db.close()

    def test_valve_driver(self):
        valve_output_1 = Output.create(number=2)
        valve_1 = Valve.create(number=1,
                               name='valve 1',
                               delay=30,
                               output=valve_output_1)

        SetUpTestInjections(output_controller=mock.Mock(OutputController))
        driver_1 = ValveDriver(valve_1)

        self.assertEqual(valve_1.id, driver_1.id)
        self.assertEqual(0, driver_1.percentage)
        self.assertEqual(0, driver_1._desired_percentage)
        self.assertFalse(driver_1.is_open)
        self.assertFalse(driver_1.in_transition)

        driver_1.set(50)
        self.assertEqual(50, driver_1._desired_percentage)
        driver_1.close()
        self.assertEqual(0, driver_1._desired_percentage)
        driver_1.open()
        self.assertEqual(100, driver_1._desired_percentage)
        self.assertTrue(driver_1.will_open)
        driver_1.steer_output()
        driver_1._output_controller.set_output_status.assert_called_once()
        self.assertFalse(driver_1.will_open)
        self.assertEqual(100, driver_1.percentage)
        self.assertFalse(driver_1.is_open)
        self.assertTrue(driver_1.in_transition)

        time.sleep(20)
        self.assertFalse(driver_1.is_open)
        self.assertTrue(driver_1.in_transition)

        time.sleep(15)
        self.assertTrue(driver_1.is_open)
        self.assertFalse(driver_1.in_transition)
Example #14
0
class PumpDriverTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        SetTestMode()

    def setUp(self):
        self.test_db = SqliteDatabase(':memory:')
        self.test_db.bind(MODELS)
        self.test_db.connect()
        self.test_db.create_tables(MODELS)

    def tearDown(self):
        self.test_db.drop_tables(MODELS)
        self.test_db.close()

    def test_pump_driver(self):
        output = Output.create(number=0)
        pump = Pump.create(number=1,
                           name='pump',
                           output=output)

        SetUpTestInjections(output_controller=mock.Mock(OutputController))
        driver = PumpDriver(pump)
        self.assertIsNone(driver.state)
        self.assertFalse(driver.error)
        self.assertEqual(pump.id, driver.id)

        driver.turn_on()
        self.assertTrue(driver.state)
        self.assertFalse(driver.error)

        driver.turn_off()
        self.assertFalse(driver.state)
        self.assertFalse(driver.error)

        driver._output_controller.set_output_status.side_effect = RuntimeError()
        with self.assertRaises(RuntimeError):
            driver.turn_on()
        self.assertFalse(driver.state)
        self.assertTrue(driver.error)

        driver._output_controller.set_output_status.side_effect = None
        driver.turn_on()
        self.assertTrue(driver.state)
        self.assertFalse(driver.error)

        driver._output_controller.set_output_status.side_effect = RuntimeError()
        with self.assertRaises(RuntimeError):
            driver.turn_off()
        self.assertTrue(driver.state)
        self.assertTrue(driver.error)

        driver._output_controller.set_output_status.side_effect = None
        driver.turn_off()
        self.assertFalse(driver.state)
        self.assertFalse(driver.error)
Example #15
0
def db_in_memory():
    """Binds all models to in-memory SQLite and creates all tables`"""
    db = SqliteDatabase(':memory:')
    db.bind(ALL_MODELS)
    db.connect()
    db.create_tables(ALL_MODELS)

    yield db

    db.drop_tables(ALL_MODELS)
    db.close()
 def wrapped_test_function(*a, **k):
     db = SqliteDatabase(":memory:",
                         pragmas={'foreign_keys': 1},
                         autoconnect=False)
     db.bind(models.REGISTRY, bind_refs=True, bind_backrefs=True)
     db.connect()
     db.create_tables(models.REGISTRY)
     try:
         return func(*a, **k)
     finally:
         db.drop_tables(models.REGISTRY)
         db.close()
class TestBase(TestCase):
    def setUp(self):
        self.db = SqliteDatabase(":memory:",
                                 pragmas={'foreign_keys': 1},
                                 autoconnect=False)
        self.db.bind(models.REGISTRY, bind_refs=False, bind_backrefs=False)
        self.db.connect()
        self.db.create_tables(models.REGISTRY)

    def tearDown(self):
        #[cls.delete().where(True).execute() for cls in models.REGISTRY]
        self.db.drop_tables(models.REGISTRY)
        self.db.close()
class IndexServerUnitTests(unittest.TestCase):
    """Index server unit and integration tests."""

    # pylint: disable=invalid-name
    def setUp(self):
        """Setup the database with in memory sqlite."""
        self._db = SqliteDatabase('file:cachedb?mode=memory&cache=shared')
        for model in [UniqueIndex]:
            model.bind(self._db, bind_refs=False, bind_backrefs=False)
        self._db.connect()
        self._db.create_tables([UniqueIndex])

    def tearDown(self):
        """Tear down the database."""
        self._db.drop_tables([UniqueIndex])
        self._db.close()
        self._db = None
    # pylint: enable=invalid-name

    def test_index_update(self):
        """Test return and update of unique index."""
        test_object = UniqueIndex.create(idid='file', index=892)
        self.assertEqual(test_object.idid, 'file')

        index, index_range = update_index(10, 'file')
        self.assertEqual(index, 892)
        self.assertEqual(index_range, 10)

        index, index_range = update_index(10, 'file')
        self.assertEqual(index, 902)
        self.assertEqual(index_range, 10)

        index, index_range = update_index(10, 'new')
        self.assertEqual(index, 1)
        self.assertEqual(index_range, 10)

        index, index_range = update_index(10, 'new')
        self.assertEqual(index, 11)
        self.assertEqual(index_range, 10)

        index, index_range = update_index(None, 'new')
        self.assertEqual(index, -1)
        self.assertEqual(index_range, -1)

        index, index_range = update_index(2, None)
        self.assertEqual(index, -1)
        self.assertEqual(index_range, -1)

        index, index_range = update_index(-5, 'new')
        self.assertEqual(index, -1)
        self.assertEqual(index_range, -1)
Example #19
0
class BaseTestCase(unittest.TestCase):
    """Base class for testing DB."""
    def setUp(self):
        """Set up database."""
        super(BaseTestCase, self).setUp()
        self.conn = SqliteDatabase(":memory:")
        self.conn.bind(MODELS, bind_refs=False, bind_backrefs=False)
        self.conn.connect()
        self.conn.create_tables(MODELS)

    def tearDown(self):
        """Cleanup database."""
        self.conn.drop_tables(MODELS)
        self.conn.close()
Example #20
0
 def l(loop):
     logging.basicConfig(stream=open('/dev/null', 'w'))
     db = SqliteDatabase(":memory:",
                         pragmas={'foreign_keys': 1},
                         autoconnect=False)
     db.bind(models.REGISTRY, bind_refs=False, bind_backrefs=False)
     db.connect()
     db.create_tables(models.REGISTRY)
     asyncio.set_event_loop(loop)
     loop.run_forever()
     click.echo(
         f"{models.Run.select().count()} runs, {models.File.select().count()} files"
     )
     db.drop_tables(models.REGISTRY)
     db.close()
Example #21
0
class DB:
    def __init__(self, tmpdir):
        self.db = SqliteDatabase(os.path.join(tmpdir, 'bills_test.db'))
        self.db.bind(MODELS)
        self.db.connect()
        self.db.create_tables(MODELS)
        self.db.close()

    def connect(self):
        self.db.connect()

    def close(self):
        self.db.close()

    def drop_tables(self):
        self.db.drop_tables(MODELS)
class IngestDBSetup(TestCase):
    """Contain all the tests for the Cart Interface."""

    # pylint: disable=invalid-name
    def setUp(self):
        """Setup the database with in memory sqlite."""
        self._db = SqliteDatabase('file:cachedb?mode=memory&cache=shared')
        for model in [IngestState]:
            model.bind(self._db, bind_refs=False, bind_backrefs=False)
        self._db.connect()
        self._db.create_tables([IngestState])

    def tearDown(self):
        """Tear down the database."""
        self._db.drop_tables([IngestState])
        self._db.close()
        self._db = None
class DBTestCase(unittest.TestCase):
    def setUp(self):
        # use an in-memory SQLite for tests.
        self.test_db = SqliteDatabase(':memory:', pragmas={'foreign_keys': 1})

        # Bind model classes to test db. Since we have a complete list of
        # all models, we do not need to recursively bind dependencies.
        self.test_db.bind(MODELS, bind_refs=False, bind_backrefs=False)

        self.test_db.connect()
        self.test_db.create_tables(MODELS)

    def tearDown(self):
        # Not strictly necessary since SQLite in-memory databases only live
        # for the duration of the connection, and in the next step we close
        # the connection...but a good practice all the same.
        self.test_db.drop_tables(MODELS)

        # Close connection to db.
        self.test_db.close()
Example #24
0
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        db = SqliteDatabase(self.db_name)

        class BaseModel(Model):
            class Meta:
                database = db

        class Org(BaseModel):
            name = CharField(unique=True)

        class ProjectCount(BaseModel):
            org = ForeignKeyField(Org)
            year = IntegerField()
            count = IntegerField()

        models = [Org, ProjectCount]

        db.connect()
        db.drop_tables(models)
        db.create_tables(models)

        self._OrgModel = Org
        self._ProjectCountModel = ProjectCount
Example #25
0
class Autor(BaseModel):
    autor = TextField(unique=True)
    user = TextField(default="keyuser")
    date = DateTimeField(default=datetime.now)


class Quote(BaseModel):
    autor = ForeignKeyField(Autor, backref="quotes")
    title = TextField()
    # author = TextField()
    tags = TextField(default="tag")
    date = DateTimeField(default=datetime.now)


db.drop_tables([Quote, Autor])
db.create_tables([Quote, Autor])


class QuotesSpider(scrapy.Spider):

    name = "QuotesSpider"
    start_urls = ["https://quotes.toscrape.com/"]

    def parse(self, response):
        quotes = response.xpath('*//div[@class="quote"]')
        yield
        for q in quotes:
            title = q.xpath('.//span[@class="text"]/text()').get()
            author = q.xpath('.//small[@class="author"]/text()').get()
            tag = q.xpath(
Example #26
0
class TestStrangerService(asynctest.TestCase):
    def __init__(self, *args, **kwargs):
        super(TestStrangerService, self).__init__(*args, **kwargs)
        self.database = SqliteDatabase(':memory:')

    def setUp(self):
        self.stranger_service = StrangerService()
        stranger.DATABASE_PROXY.initialize(self.database)
        self.database.create_tables([Stranger])
        self.stranger_0 = Stranger.create(
            invitation='foo',
            languages='["foo"]',
            telegram_id=27183,
            sex='female',
            partner_sex='male',
        )
        self.stranger_1 = Stranger.create(
            invitation='bar',
            languages='["foo"]',
            telegram_id=31416,
            sex='male',
            partner_sex='female',
        )
        self.stranger_2 = Stranger.create(
            invitation='baz',
            languages='["foo"]',
            telegram_id=23571,
            sex='male',
            partner_sex='female',
        )
        self.stranger_3 = Stranger.create(
            invitation='zen',
            languages='["foo"]',
            telegram_id=11317,
            sex='male',
            partner_sex='female',
        )
        self.stranger_4 = Stranger.create(
            invitation='zig',
            languages='["foo"]',
            telegram_id=19232,
            sex='male',
            partner_sex='female',
        )
        self.stranger_5 = Stranger.create(
            invitation='zam',
            languages='["foo"]',
            telegram_id=93137,
            sex='male',
            partner_sex='female',
        )
        self.stranger_6 = Stranger.create(invitation='zom',
                                          languages=None,
                                          telegram_id=0,
                                          sex=None,
                                          partner_sex=None)

    def tearDown(self):
        self.database.drop_tables([Stranger])

    @patch('randtalkbot.stranger_service.StrangerService.__init__',
           Mock(return_value=None))
    @asynctest.ignore_loop
    def test_get_instance(self):
        self.assertEqual(StrangerService.get_instance(),
                         StrangerService._instance)
        StrangerService.__init__.assert_not_called()
        del StrangerService._instance
        instance = StrangerService.get_instance()
        self.assertEqual(StrangerService._instance, instance)
        self.assertTrue(StrangerService.__init__.called)

    @asynctest.ignore_loop
    def test_get_cached_stranger__cached(self):
        cached_stranger = Mock()
        cached_stranger.id = 31416
        self.stranger_service._strangers_cache[31416] = cached_stranger
        stranger.id = 31416
        self.assertEqual(self.stranger_service.get_cached_stranger(stranger),
                         cached_stranger)

    @asynctest.ignore_loop
    def test_get_cached_stranger__not_cached(self):
        stranger_mock = Mock()
        stranger_mock.id = 31416
        stranger_mock.invited_by = None
        self.assertEqual(
            self.stranger_service.get_cached_stranger(stranger_mock),
            stranger_mock)
        self.assertEqual(self.stranger_service._strangers_cache[31416],
                         stranger_mock)

    @asynctest.ignore_loop
    def test_get_cache_size(self):
        self.assertEqual(self.stranger_service.get_cache_size(), 0)
        self.stranger_service._strangers_cache = {
            0: 0,
            1: 1,
        }
        self.assertEqual(self.stranger_service.get_cache_size(), 2)

    @asynctest.ignore_loop
    def test_get_full_strangers(self):
        full_strangers = list(self.stranger_service.get_full_strangers())
        self.assertEqual(len(full_strangers), 6)

    @patch('randtalkbot.stranger_service.Stranger', create_autospec(Stranger))
    @asynctest.ignore_loop
    def test_get_or_create_stranger__stranger_found(self):
        from randtalkbot.stranger_service import Stranger as stranger_cls_mock
        stranger_cls_mock.get.return_value = self.stranger_0
        self.stranger_service.get_cached_stranger = Mock()
        self.stranger_service.get_cached_stranger.return_value = 'cached_stranger'
        self.assertEqual(
            self.stranger_service.get_or_create_stranger(31416),
            'cached_stranger',
        )
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_0)

    @patch('randtalkbot.stranger_service.Stranger', create_autospec(Stranger))
    @asynctest.ignore_loop
    def test_get_or_create_stranger__stranger_not_found(self):
        from randtalkbot.stranger_service import Stranger as stranger_cls_mock
        stranger_cls_mock.get.side_effect = DoesNotExist()
        stranger_cls_mock.create.return_value = self.stranger_0
        self.stranger_service.get_cached_stranger = Mock()
        self.stranger_service.get_cached_stranger.return_value = 'cached_stranger'
        self.assertEqual(
            self.stranger_service.get_or_create_stranger(31416),
            'cached_stranger',
        )
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_0)

    @patch('randtalkbot.stranger_service.Stranger', create_autospec(Stranger))
    @asynctest.ignore_loop
    def test_get_or_create_stranger__database_error(self):
        from randtalkbot.stranger_service import Stranger as stranger_cls_mock
        self.stranger_service.get_cached_stranger = Mock()
        stranger_cls_mock.get.side_effect = DatabaseError()
        with self.assertRaises(StrangerServiceError):
            self.stranger_service.get_or_create_stranger(31416)

    @asynctest.ignore_loop
    def test_get_stranger__stranger_found(self):
        self.stranger_service.get_cached_stranger = Mock()
        self.stranger_service.get_cached_stranger.return_value = 'cached_stranger'
        self.assertEqual(
            self.stranger_service.get_stranger(31416),
            'cached_stranger',
        )
        self.assertEqual(
            self.stranger_service.get_cached_stranger.call_args[0][0].id,
            self.stranger_1.id,
        )

    @patch('randtalkbot.stranger_service.Stranger.get',
           Mock(side_effect=DatabaseError()))
    @asynctest.ignore_loop
    def test_get_stranger__database_error(self):
        with self.assertRaises(StrangerServiceError):
            self.stranger_service.get_stranger(31416)

    @patch('randtalkbot.stranger_service.INVITATION_LENGTH', 3)
    @asynctest.ignore_loop
    def test_get_stranger_by_invitation__ok(self):
        self.stranger_service.get_cached_stranger = Mock()
        self.stranger_service.get_cached_stranger.return_value = 'cached_stranger'
        self.assertEqual(
            self.stranger_service.get_stranger_by_invitation('zam'),
            'cached_stranger',
        )
        self.assertEqual(
            self.stranger_service.get_cached_stranger.call_args[0][0].id,
            self.stranger_5.id,
        )

    @patch('randtalkbot.stranger_service.INVITATION_LENGTH', 3)
    @asynctest.ignore_loop
    def test_get_stranger_by_invitation__wrong_length(self):
        self.stranger_service.get_cached_stranger = Mock()
        self.stranger_service.get_cached_stranger.return_value = 'cached_stranger'
        with self.assertRaises(StrangerServiceError):
            self.stranger_service.get_stranger_by_invitation('booo')
        self.stranger_service.get_cached_stranger.assert_not_called()

    @patch('randtalkbot.stranger_service.INVITATION_LENGTH', 3)
    @patch('randtalkbot.stranger_service.Stranger.get',
           Mock(side_effect=DatabaseError()))
    @asynctest.ignore_loop
    def test_get_stranger_by_invitation__database_error(self):
        with self.assertRaises(StrangerServiceError):
            self.stranger_service.get_stranger_by_invitation('zam')

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_the_longest_waiting_stranger_1(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        # The longest waiting stranger with max bonus count.
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.bonus_count = 1
        self.stranger_1.save()
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.bonus_count = 1
        self.stranger_3.save()
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_1)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_the_longest_waiting_stranger_2(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1994, 1, 1)
        self.stranger_2.bonus_count = 1
        self.stranger_2.save()
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # The longest waiting stranger with max bonus count.
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.bonus_count = 1
        self.stranger_4.save()
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_with_proper_sex_1(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.sex = 'female'
        self.stranger_1.partner_sex = 'female'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'female'
        self.stranger_2.partner_sex = 'female'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        # Stranger with proper sex.
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'female'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.sex = 'female'
        self.stranger_4.partner_sex = 'female'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'female'
        self.stranger_5.partner_sex = 'female'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_3)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_with_proper_sex_2(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.sex = 'female'
        self.stranger_1.partner_sex = 'female'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'female'
        self.stranger_2.partner_sex = 'female'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.sex = 'female'
        self.stranger_3.partner_sex = 'female'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger with proper sex.
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'female'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'female'
        self.stranger_5.partner_sex = 'female'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_looking_for_proper_sex_1(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        # Stranger looking for proper sex.
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'female'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'male'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_3)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_looking_for_proper_sex_2(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'male'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger looking for proper sex.
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'female'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__filters_strangers_when_stranger_partner_sex_isnt_specified_1(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.partner_sex = 'not_specified'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        # Stranger looking for proper sex.
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'female'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'male'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_3)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__filters_strangers_when_stranger_partner_sex_isnt_specified_2(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.partner_sex = 'not_specified'
        self.stranger_0.save()
        # Stranger looking for proper sex.
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'female'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'male'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'male'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_1)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_looking_for_any_sex_in_case_of_rare_sex_1(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        # Stranger looking for any sex.
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'not_specified'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'male'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_3)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_looking_for_any_sex_in_case_of_rare_sex_2(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'male'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger looking for any sex.
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'not_specified'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_looking_for_any_sex_if_sex_is_not_specified_1(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.sex = 'not_specified'
        self.stranger_0.partner_sex = 'not_specified'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        # Stranger looking for any sex.
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'not_specified'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'male'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_3)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_looking_for_any_sex_if_sex_is_not_specified_2(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz"]'
        self.stranger_0.sex = 'not_specified'
        self.stranger_0.partner_sex = 'not_specified'
        self.stranger_0.save()
        self.stranger_1.sex = 'male'
        self.stranger_1.partner_sex = 'male'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.sex = 'male'
        self.stranger_2.partner_sex = 'male'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.sex = 'male'
        self.stranger_3.partner_sex = 'male'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger looking for any sex.
        self.stranger_4.sex = 'male'
        self.stranger_4.partner_sex = 'not_specified'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.sex = 'male'
        self.stranger_5.partner_sex = 'male'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_speaking_on_highest_priority_language_1(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz", "boo", "bim"]'
        self.stranger_0.save()
        self.stranger_1.languages = '["BAR", "baz", "FOO"]'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.languages = '["boo"]'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        # Stranger speaking on highest priority language (foo).
        self.stranger_3.languages = '["BAR", "BAZ", "foo"]'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        self.stranger_4.languages = '["BAR", "BAZ", "boo", "BIM"]'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.languages = '["bar"]'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_3)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_stranger_speaking_on_highest_priority_language_2(
            self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["foo", "bar", "baz", "boo", "bim"]'
        self.stranger_0.save()
        self.stranger_1.languages = '["BAR", "baz", "FOO"]'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        self.stranger_2.languages = '["boo"]'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.languages = '["BAR", "BAZ", "bim"]'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger speaking on highest priority language (foo).
        self.stranger_4.languages = '["BAR", "BAZ", "BOO", "foo", "BIM"]'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.languages = '["bar"]'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_fresh_stranger_1(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = [
            self.stranger_2.id, 11111, 22222
        ]
        self.stranger_0.languages = '["foo", "bar", "baz", "boo", "bim"]'
        self.stranger_0.save()
        self.stranger_1.languages = '["BAR", "baz", "FOO"]'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        # Stranger speaking on highest priority language, NOT FRESH
        self.stranger_2.languages = '["foo"]'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.languages = '["BAR", "BAZ", "bim"]'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger speaking on highest priority language (foo), FRESH
        self.stranger_4.languages = '["BAR", "BAZ", "BOO", "foo", "BIM"]'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.languages = '["bar"]'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_4)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__returns_fresh_stranger_2(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = [
            self.stranger_4.id, 33333, 44444
        ]
        self.stranger_0.languages = '["foo", "bar", "baz", "boo", "bim"]'
        self.stranger_0.save()
        self.stranger_1.languages = '["BAR", "baz", "FOO"]'
        self.stranger_1.looking_for_partner_from = datetime.datetime(
            1990, 1, 1)
        self.stranger_1.save()
        # Stranger speaking on highest priority language, FRESH
        self.stranger_2.languages = '["foo"]'
        self.stranger_2.looking_for_partner_from = datetime.datetime(
            1980, 1, 1)
        self.stranger_2.save()
        self.stranger_3.languages = '["BAR", "BAZ", "bim"]'
        self.stranger_3.looking_for_partner_from = datetime.datetime(
            1991, 1, 1)
        self.stranger_3.save()
        # Stranger speaking on highest priority language (foo), NOT FRESH
        self.stranger_4.languages = '["BAR", "BAZ", "BOO", "foo", "BIM"]'
        self.stranger_4.looking_for_partner_from = datetime.datetime(
            1993, 1, 1)
        self.stranger_4.save()
        self.stranger_5.languages = '["bar"]'
        self.stranger_5.looking_for_partner_from = datetime.datetime(
            1992, 1, 1)
        self.stranger_5.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        self.assertEqual(self.stranger_service._match_partner(self.stranger_0),
                         'cached_partner')
        self.stranger_service.get_cached_stranger.assert_called_once_with(
            self.stranger_2)

    @patch('randtalkbot.talk.Talk', Mock())
    @asynctest.ignore_loop
    def test_match_partner__does_not_exist(self):
        from randtalkbot.talk import Talk
        Talk.get_last_partners_ids.return_value = []
        self.stranger_0.languages = '["boo"]'
        self.stranger_0.save()
        self.stranger_service.get_cached_stranger = Mock(
            return_value='cached_partner')
        with self.assertRaises(PartnerObtainingError):
            self.stranger_service._match_partner(self.stranger_0)
        self.stranger_service.get_cached_stranger.assert_not_called()

    async def test_match_partner__ok(self):
        stranger_mock = CoroutineMock()
        partner = CoroutineMock()
        partner.id = 31416
        self.stranger_service._match_partner = Mock(return_value=partner)
        self.stranger_service._locked_strangers_ids = Mock()
        await self.stranger_service.match_partner(stranger_mock)
        self.stranger_service._locked_strangers_ids.discard. \
            assert_called_once_with(31416)
        stranger_mock.notify_partner_found.assert_called_once_with(partner)
        partner.notify_partner_found.assert_called_once_with(stranger_mock)
        stranger_mock.set_partner.assert_called_once_with(partner)

    async def test_match_partner__stranger_error(self):
        stranger_mock = CoroutineMock()
        partner = CoroutineMock()
        partner.id = 31416
        self.stranger_service._match_partner = Mock(return_value=partner)
        self.stranger_service._locked_strangers_ids = Mock()
        stranger_mock.notify_partner_found.side_effect = StrangerError()
        with self.assertRaises(StrangerServiceError):
            await self.stranger_service.match_partner(stranger_mock)
        self.stranger_service._locked_strangers_ids.discard. \
            assert_called_once_with(31416)
        stranger_mock.set_partner.assert_not_called()

    async def test_match_partner__first_partner_has_blocked_the_bot(self):
        stranger_mock = CoroutineMock()
        partner = CoroutineMock()
        partner.id = 31416
        self.stranger_service._match_partner = Mock(return_value=partner)
        self.stranger_service._locked_strangers_ids = Mock()
        partner.notify_partner_found.side_effect = [StrangerError(), None]
        await self.stranger_service.match_partner(stranger_mock)
        self.assertEqual(
            self.stranger_service._locked_strangers_ids.discard.call_args_list,
            [
                call(31416),
                call(31416),
            ],
        )
        self.assertEqual(
            partner.notify_partner_found.call_args_list,
            [
                call(stranger_mock),
                call(stranger_mock),
            ],
        )
        stranger_mock.notify_partner_found.assert_called_once_with(partner)

    async def test_match_partner__partner_obtaining_error(self):
        stranger_mock = CoroutineMock()
        self.stranger_service._match_partner = Mock(
            side_effect=PartnerObtainingError, )
        with self.assertRaises(PartnerObtainingError):
            await self.stranger_service.match_partner(stranger_mock)
Example #27
0
class PumpValveControllerTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        fakesleep.monkey_patch()
        SetTestMode()
        logger = logging.getLogger('openmotics')
        logger.setLevel(logging.DEBUG)
        logger.propagate = False
        handler = logging.StreamHandler()
        handler.setLevel(logging.DEBUG)
        handler.setFormatter(
            logging.Formatter(
                "%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
        logger.addHandler(handler)

    @classmethod
    def tearDownClass(cls):
        fakesleep.monkey_restore()

    def setUp(self):
        self.test_db = SqliteDatabase(':memory:')
        self.test_db.bind(MODELS)
        self.test_db.connect()
        self.test_db.create_tables(MODELS)
        self._gateway_api = mock.Mock(GatewayApi)
        self._gateway_api.get_sensor_temperature_status.return_value = 0.0
        self._pump_valve_controller = mock.Mock(PumpValveController)
        SetUpTestInjections(gateway_api=self._gateway_api)
        self._thermostat_group = ThermostatGroup.create(
            number=0,
            name='thermostat group',
            on=True,
            threshold_temperature=10.0,
            sensor=Sensor.create(number=1),
            mode='heating')

    def tearDown(self):
        self.test_db.drop_tables(MODELS)
        self.test_db.close()

    def _get_thermostat_pid(self):
        thermostat = Thermostat.create(number=1,
                                       name='thermostat 1',
                                       sensor=Sensor.create(number=10),
                                       pid_heating_p=200,
                                       pid_heating_i=100,
                                       pid_heating_d=50,
                                       pid_cooling_p=200,
                                       pid_cooling_i=100,
                                       pid_cooling_d=50,
                                       automatic=True,
                                       room=None,
                                       start=0,
                                       valve_config='equal',
                                       thermostat_group=self._thermostat_group)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=Valve.create(
                                     number=1,
                                     name='valve 1',
                                     output=Output.create(number=1)),
                                 mode=ThermostatGroup.Modes.HEATING,
                                 priority=0)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=Valve.create(
                                     number=2,
                                     name='valve 2',
                                     output=Output.create(number=2)),
                                 mode=ThermostatGroup.Modes.COOLING,
                                 priority=0)
        Preset.create(type=Preset.Types.SCHEDULE,
                      heating_setpoint=20.0,
                      cooling_setpoint=25.0,
                      active=True,
                      thermostat=thermostat)
        return ThermostatPid(thermostat=thermostat,
                             pump_valve_controller=self._pump_valve_controller)

    def test_basic(self):
        thermostat_pid = self._get_thermostat_pid()
        self.assertEqual([1, 2], thermostat_pid.valve_ids)
        self.assertEqual([1], thermostat_pid._heating_valve_ids)
        self.assertEqual([2], thermostat_pid._cooling_valve_ids)
        self.assertEqual(200, thermostat_pid.kp)
        self.assertEqual(100, thermostat_pid.ki)
        self.assertEqual(50, thermostat_pid.kd)

    def test_enabled(self):
        thermostat_pid = self._get_thermostat_pid()
        self.assertTrue(thermostat_pid.enabled)
        # No sensor configured
        sensor = thermostat_pid._thermostat.sensor
        thermostat_pid._thermostat.sensor = None
        self.assertFalse(thermostat_pid.enabled)
        thermostat_pid._thermostat.sensor = sensor
        self.assertTrue(thermostat_pid.enabled)
        # No valves
        heating_valve_ids = thermostat_pid._heating_valve_ids
        thermostat_pid._heating_valve_ids = []
        thermostat_pid._cooling_valve_ids = []
        self.assertFalse(thermostat_pid.enabled)
        thermostat_pid._heating_valve_ids = heating_valve_ids
        self.assertTrue(thermostat_pid.enabled)
        # The group is turned off
        self._thermostat_group.on = False
        self.assertFalse(thermostat_pid.enabled)
        self._thermostat_group.on = True
        self.assertTrue(thermostat_pid.enabled)
        # A high amount of errors
        thermostat_pid._errors = 10
        self.assertFalse(thermostat_pid.enabled)
        thermostat_pid._errors = 0
        self.assertTrue(thermostat_pid.enabled)

    def test_tick(self):
        thermostat_pid = self._get_thermostat_pid()
        thermostat_pid._pid = mock.Mock(PID)
        thermostat_pid._pid.setpoint = 0.0
        self.assertTrue(thermostat_pid.enabled)

        self._thermostat_group.on = False
        self._pump_valve_controller.set_valves.call_count = 0
        self._pump_valve_controller.set_valves.mock_calls = []
        self.assertFalse(thermostat_pid.tick())
        self._pump_valve_controller.steer.assert_called_once()
        self.assertEqual(
            sorted([
                mock.call(0, [1], mode='equal'),
                mock.call(0, [2], mode='equal')
            ]), sorted(self._pump_valve_controller.set_valves.mock_calls))
        self.assertEqual(2, self._pump_valve_controller.set_valves.call_count)
        self._thermostat_group.on = True

        for mode, output_power, heating_power, cooling_power in [
            (ThermostatGroup.Modes.HEATING, 100, 100, 0),
            (ThermostatGroup.Modes.HEATING, 50, 50, 0),
            (ThermostatGroup.Modes.HEATING, 0, 0, 0),
            (ThermostatGroup.Modes.HEATING, -50, 0, 0),
            (ThermostatGroup.Modes.COOLING, -100, 0, 100),
            (ThermostatGroup.Modes.COOLING, -50, 0, 50),
            (ThermostatGroup.Modes.COOLING, 0, 0, 0),
            (ThermostatGroup.Modes.COOLING, 50, 0, 0)
        ]:
            thermostat_pid._mode = mode
            thermostat_pid._pid.return_value = output_power
            self._pump_valve_controller.steer.call_count = 0
            self._pump_valve_controller.set_valves.call_count = 0
            self._pump_valve_controller.set_valves.mock_calls = []
            self.assertTrue(thermostat_pid.tick())
            self._pump_valve_controller.steer.assert_called_once()
            self.assertEqual(
                sorted([
                    mock.call(heating_power, [1], mode='equal'),
                    mock.call(cooling_power, [2], mode='equal')
                ]), sorted(self._pump_valve_controller.set_valves.mock_calls))
            self.assertEqual(2,
                             self._pump_valve_controller.set_valves.call_count)
Example #28
0
class TestBase(TestCase):
    """Setup the test cases for the base object attributes for the ORM."""

    obj_cls = PacificaModel
    # pylint: disable=no-member
    obj_id = PacificaModel.id

    # pylint: enable=no-member

    def setUp(self):
        """Setup the database with in memory sqlite."""
        self._test_db = SqliteDatabase(':memory:')
        self._models = self.dependent_cls()
        for model in self._models:
            model.bind(self._test_db, bind_refs=False, bind_backrefs=False)
        self._test_db.connect()
        self._test_db.create_tables(self._models)

    def tearDown(self):
        """Tear down the database."""
        self._test_db.drop_tables(self._models)
        self._test_db.close()
        self._test_db = None

    @staticmethod
    def dependent_cls():
        """Return dependent classes."""
        return ORM_OBJECTS

    @classmethod
    def base_create_dep_objs(cls):
        """Create dependent objects."""
        pass

    def base_create_obj(self, cls, obj_hash):
        """Create obj based on the class given."""
        self.base_create_dep_objs()
        obj = cls()
        if 'updated' not in obj_hash:
            change_date_chk = datetime.utcnow()
            obj.updated = change_date_chk
        obj.from_hash(obj_hash)
        obj.save(force_insert=True)
        if 'updated' not in obj_hash:
            self.assertEqual(obj.last_change_date(),
                             unicode_type(change_date_chk.isoformat(' ')))
        return obj

    def base_test_hash(self, obj_hash):
        """
        Base hash test.

        create a new object out of the hash
        save the object to the DB
        pull the object out of the DB using the obj_id column
        create a new hash from the new object
        check all keys in the new hash from the obj_hash passed
        """
        obj = self.base_create_obj(self.obj_cls, obj_hash)
        # pylint: disable=no-member
        new_obj = self.obj_cls.get(
            self.obj_id == getattr(obj, self.obj_id.column_name))
        # pylint: enable=no-member
        chk_obj_hash = new_obj.to_hash()
        self.assertTrue('_id' in chk_obj_hash)
        for key in obj_hash.keys():
            self.assertEqual(chk_obj_hash[key], obj_hash[key])

    def base_test_json(self, json_str):
        """
        Base test json.

        pass the json string to the objects from_json method
        save the object to the DB
        get the new object using column in obj_id
        convert the object to json
        """
        self.assertEqual(type(json_str), str)
        self.base_create_dep_objs()
        if not isinstance(loads(json_str), dict):
            raise ValueError('json_str not dict')
        obj = self.obj_cls()
        obj.from_hash(loads(json_str))
        obj.save(force_insert=True)
        # pylint: disable=no-member
        new_obj = self.obj_cls.get(
            self.obj_id == getattr(obj, self.obj_id.column_name))
        # pylint: enable=no-member
        chk_obj_json = dumps(new_obj.to_hash())
        self.assertEqual(type(chk_obj_json), str)

    @staticmethod
    def base_where_clause_search(obj, kwargs):
        """Use kwargs as options to where clause to search for obj and return."""
        expr = obj.where_clause(kwargs)
        return obj.select().where(expr)

    def base_where_clause_search_expr(self, obj_hash, **kwargs):
        """Search for a objects on single search parameters."""
        obj = self.base_create_obj(self.obj_cls, obj_hash)
        chk_obj = self.base_where_clause_search(obj, kwargs)[0]
        chk_obj_hash = chk_obj.to_hash()
        for key in obj_hash.keys():
            self.assertEqual(chk_obj_hash[key], obj_hash[key])

    def base_where_clause(self, obj_hash):
        """
        Base where clause checking.

        create a new object from the obj_hash
        save it to the database
        check all keys in obj_hash separately
        query a new object using that key and value in obj_hash
        compare the pulled object hash with obj_hash
        """
        obj = self.base_create_obj(self.obj_cls, obj_hash)
        for (key, val) in obj_hash.items():
            chk_obj = self.base_where_clause_search(obj, {key: val})[0]
            chk_obj_hash = chk_obj.to_hash()
            for chkkey in obj_hash.keys():
                self.assertEqual(chk_obj_hash[chkkey], obj_hash[chkkey])
Example #29
0
class TestArtworkDB(TestCase):
    def setUp(self):
        # Remove existing data from test database and recreate tables
        self.db = SqliteDatabase(db_path)
        self.db.drop_tables([Artist, Artwork])
        self.db.create_tables([Artist, Artwork])

    def add_generic_sample_data(
            self
    ):  # Adds sample data for my test methods to work with if needed
        artworkDB.add_artist('Bob', '*****@*****.**')
        artworkDB.add_artist('Maria', '*****@*****.**')

        artworkDB.add_artwork('Bob', 'Simplicity Defined', 3400.00, True)
        artworkDB.add_artwork('Bob', 'Life Without Entropy', 8200.00, True)
        artworkDB.add_artwork('Bob', 'Love in the Winter', 2200.00, False)

        artworkDB.add_artwork('Maria', 'Waves Abound', 6700.00, False)
        artworkDB.add_artwork('Maria', 'A Distant Mountain', 960.00, False)
        artworkDB.add_artwork('Maria', 'In the End', 7600.00, True)

    def test_add_artist(
        self
    ):  # Tests to see if it can retrieve an artists data after adding it to the database
        self.add_generic_sample_data()
        artworkDB.add_artist('Matthew', '*****@*****.**')

        artist = Artist.get_or_none(Artist.name == 'Matthew',
                                    Artist.email == '*****@*****.**')
        self.assertIsNotNone(artist)

    def test_add_artist_name_already_exists(
            self):  # Makes sure an artist can't be added twice to the database
        self.add_generic_sample_data()
        with self.assertRaises(IntegrityError):
            artworkDB.add_artist('Bob', '*****@*****.**')

    def test_add_artist_email_already_exists(
            self):  # Makes sure an artist's email can't be added twice
        self.add_generic_sample_data()
        with self.assertRaises(IntegrityError):
            artworkDB.add_artist('Bobby', '*****@*****.**')

    def test_add_artist_name_null(
            self):  # Make sure database won't accept a null artist name
        with self.assertRaises(IntegrityError):
            artworkDB.add_artist(None, '*****@*****.**')

    def test_add_artist_email_null(
            self):  # Makes sure database won't accept a null artist email
        with self.assertRaises(IntegrityError):
            artworkDB.add_artist('Harry', None)

    def test_add_artwork(
        self
    ):  # Try to retrieve data about an artwork after adding it to the database
        artworkDB.add_artist('Bob', '*****@*****.**')
        artworkDB.add_artwork('Bob', 'Air is Empathy', 6600, True)
        artwork = Artwork.get_or_none(Artwork.name == 'Air is Empathy',
                                      Artwork.price == 6600,
                                      Artwork.available == True)
        self.assertIsNotNone(artwork)

    def test_delete_artwork_by_name(
        self
    ):  # Makes sure artwork is gone after calling the method to delete it
        self.add_generic_sample_data()
        artworkDB.delete_artwork('Simplicity Defined')
        artwork = Artwork.get_or_none(Artwork.name == 'Simplicity Defined')
        self.assertIsNone(artwork)

    def test_change_artwork_availability(
            self
    ):  # Make sure availability status of artwork is changed correctly
        self.add_generic_sample_data()
        artworkDB.change_availability('Simplicity Defined', False)
        artwork = Artwork.get_or_none(Artwork.name == 'Simplicity Defined',
                                      Artwork.available == False)
        self.assertIsNotNone(artwork)

    def test_search_artwork_by_artist(
            self):  # Try pulling up all artwork for a given artist
        artworkDB.add_artist('Bob', '*****@*****.**')
        artworkDB.add_artwork('Bob', 'Life of Insanity', 90, False)
        artwork = artworkDB.search_artwork_by_artist('Bob')
        for art in artwork:
            self.assertEqual(art.name, 'Life of Insanity')

    def test_search_available_by_artist(
        self
    ):  # Makes sure only available artwork is returned for this function
        artworkDB.add_artist('Bob', '*****@*****.**')
        artworkDB.add_artwork('Bob', 'Life of Insanity', 90, True)
        artworkDB.add_artwork('Bob', 'Modern Age', 400, False)
        artworkDB.add_artwork('Bob', 'Rain and Snow', 448, False)
        artwork = artworkDB.search_available_by_artist('Bob')
        for art in artwork:
            self.assertEqual(art.name, 'Life of Insanity')
class ThermostatControllerTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        fakesleep.monkey_patch()
        SetTestMode()
        logger = logging.getLogger('openmotics')
        logger.setLevel(logging.DEBUG)
        logger.propagate = False
        handler = logging.StreamHandler()
        handler.setLevel(logging.DEBUG)
        handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
        logger.addHandler(handler)

    @classmethod
    def tearDownClass(cls):
        fakesleep.monkey_restore()

    def setUp(self):
        self.test_db = SqliteDatabase(':memory:')
        self.test_db.bind(MODELS)
        self.test_db.connect()
        self.test_db.create_tables(MODELS)
        self._gateway_api = mock.Mock(GatewayApi)
        self._gateway_api.get_timezone.return_value = 'Europe/Brussels'
        self._gateway_api.get_sensor_temperature_status.return_value = 10.0
        output_controller = mock.Mock(OutputController)
        output_controller.get_output_status.return_value = OutputStateDTO(id=0, status=False)
        SetUpTestInjections(gateway_api=self._gateway_api,
                            output_controller=output_controller,
                            pubsub=mock.Mock())
        self._thermostat_controller = ThermostatControllerGateway()
        SetUpTestInjections(thermostat_controller=self._thermostat_controller)
        self._thermostat_group = ThermostatGroup.create(number=0,
                                                        name='thermostat group',
                                                        on=True,
                                                        threshold_temperature=10.0,
                                                        sensor=Sensor.create(number=1),
                                                        mode='heating')

    def tearDown(self):
        self.test_db.drop_tables(MODELS)
        self.test_db.close()

    def test_save_pumpgroups(self):
        thermostat = Thermostat.create(number=1,
                                       name='thermostat 1',
                                       sensor=Sensor.create(number=10),
                                       pid_heating_p=200,
                                       pid_heating_i=100,
                                       pid_heating_d=50,
                                       pid_cooling_p=200,
                                       pid_cooling_i=100,
                                       pid_cooling_d=50,
                                       automatic=True,
                                       room=None,
                                       start=0,
                                       valve_config='equal',
                                       thermostat_group=self._thermostat_group)
        valve_1_output = Output.create(number=1)
        valve_1 = Valve.create(number=1,
                               name='valve 1',
                               output=valve_1_output)
        valve_2_output = Output.create(number=2)
        valve_2 = Valve.create(number=2,
                               name='valve 2',
                               output=valve_2_output)
        valve_3_output = Output.create(number=3)
        valve_3 = Valve.create(number=3,
                               name='valve 3',
                               output=valve_3_output)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=valve_1,
                                 mode=ThermostatGroup.Modes.HEATING,
                                 priority=0)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=valve_2,
                                 mode=ThermostatGroup.Modes.COOLING,
                                 priority=0)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=valve_3,
                                 mode=ThermostatGroup.Modes.HEATING,
                                 priority=0)
        Preset.create(type=Preset.Types.SCHEDULE,
                      heating_setpoint=20.0,
                      cooling_setpoint=25.0,
                      active=True,
                      thermostat=thermostat)
        pump_output = Output.create(number=4)
        pump = Pump.create(name='pump 1',
                           output=pump_output)

        heating_pump_groups = self._thermostat_controller.load_heating_pump_groups()
        self.assertEqual([PumpGroupDTO(id=pump.id,
                                       pump_output_id=pump_output.id,
                                       valve_output_ids=[],
                                       room_id=None)], heating_pump_groups)

        PumpToValve.create(pump=pump, valve=valve_1)
        PumpToValve.create(pump=pump, valve=valve_2)

        pump_groups = self._thermostat_controller.load_heating_pump_groups()
        self.assertEqual([PumpGroupDTO(id=pump.id,
                                       pump_output_id=pump_output.id,
                                       valve_output_ids=[valve_1_output.id],
                                       room_id=None)], pump_groups)
        pump_groups = self._thermostat_controller.load_cooling_pump_groups()
        self.assertEqual([PumpGroupDTO(id=pump.id,
                                       pump_output_id=pump_output.id,
                                       valve_output_ids=[valve_2_output.id],
                                       room_id=None)], pump_groups)

        self._thermostat_controller._save_pump_groups(ThermostatGroup.Modes.HEATING,
                                                      [(PumpGroupDTO(id=pump.id,
                                                                     pump_output_id=pump_output.id,
                                                                     valve_output_ids=[valve_1_output.id, valve_3_output.id]),
                                                        ['pump_output_id', 'valve_output_ids'])])
        pump_groups = self._thermostat_controller.load_heating_pump_groups()
        self.assertEqual([PumpGroupDTO(id=pump.id,
                                       pump_output_id=pump_output.id,
                                       valve_output_ids=[valve_1_output.id, valve_3_output.id],
                                       room_id=None)], pump_groups)
        pump_groups = self._thermostat_controller.load_cooling_pump_groups()
        self.assertEqual([PumpGroupDTO(id=pump.id,
                                       pump_output_id=pump_output.id,
                                       valve_output_ids=[valve_2_output.id],
                                       room_id=None)], pump_groups)

    def test_thermostat_group_crud(self):
        thermostat = Thermostat.create(number=1,
                                       name='thermostat 1',
                                       sensor=Sensor.create(number=10),
                                       pid_heating_p=200,
                                       pid_heating_i=100,
                                       pid_heating_d=50,
                                       pid_cooling_p=200,
                                       pid_cooling_i=100,
                                       pid_cooling_d=50,
                                       automatic=True,
                                       room=None,
                                       start=0,
                                       valve_config='equal',
                                       thermostat_group=self._thermostat_group)
        Output.create(number=1)
        Output.create(number=2)
        Output.create(number=3)
        valve_output = Output.create(number=4)
        valve = Valve.create(number=1,
                             name='valve 1',
                             output=valve_output)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=valve,
                                 mode=ThermostatGroup.Modes.HEATING,
                                 priority=0)
        thermostat_group = ThermostatGroup.get(number=0)  # type: ThermostatGroup
        self.assertEqual(10.0, thermostat_group.threshold_temperature)
        self.assertEqual(0, OutputToThermostatGroup.select()
                                                   .where(OutputToThermostatGroup.thermostat_group == thermostat_group)
                                                   .count())
        self._thermostat_controller.save_thermostat_group((ThermostatGroupDTO(id=0,
                                                                              outside_sensor_id=1,
                                                                              pump_delay=30,
                                                                              threshold_temperature=15,
                                                                              switch_to_heating_0=(1, 0),
                                                                              switch_to_heating_1=(2, 100),
                                                                              switch_to_cooling_0=(1, 100)),
                                                           ['outside_sensor_id', 'pump_delay', 'threshold_temperature',
                                                            'switch_to_heating_0', 'switch_to_heating_1',
                                                            'switch_to_cooling_0']))
        thermostat_group = ThermostatGroup.get(number=0)
        self.assertEqual(15.0, thermostat_group.threshold_temperature)
        links = [{'index': link.index, 'value': link.value, 'mode': link.mode, 'output': link.output_id}
                 for link in (OutputToThermostatGroup.select()
                                                     .where(OutputToThermostatGroup.thermostat_group == thermostat_group))]
        self.assertEqual(3, len(links))
        self.assertIn({'index': 0, 'value': 0, 'mode': 'heating', 'output': 1}, links)
        self.assertIn({'index': 1, 'value': 100, 'mode': 'heating', 'output': 2}, links)
        self.assertIn({'index': 0, 'value': 100, 'mode': 'cooling', 'output': 1}, links)

        new_thermostat_group_dto = ThermostatGroupDTO(id=0,
                                                      outside_sensor_id=1,
                                                      pump_delay=60,
                                                      threshold_temperature=10,
                                                      switch_to_heating_0=(1, 50),
                                                      switch_to_cooling_0=(2, 0))
        self._thermostat_controller.save_thermostat_group((new_thermostat_group_dto,
                                                           ['outside_sensor_id', 'pump_delay', 'threshold_temperature',
                                                            'switch_to_heating_0', 'switch_to_heating_1', 'switch_to_cooling_0']))
        thermostat_group = ThermostatGroup.get(number=0)
        self.assertEqual(10.0, thermostat_group.threshold_temperature)
        links = [{'index': link.index, 'value': link.value, 'mode': link.mode, 'output': link.output_id}
                 for link in (OutputToThermostatGroup.select()
                                                     .where(OutputToThermostatGroup.thermostat_group == thermostat_group))]
        self.assertEqual(2, len(links))
        self.assertIn({'index': 0, 'value': 50, 'mode': 'heating', 'output': 1}, links)
        self.assertIn({'index': 0, 'value': 0, 'mode': 'cooling', 'output': 2}, links)

        self.assertEqual(new_thermostat_group_dto, self._thermostat_controller.load_thermostat_group())

    def test_thermostat_control(self):
        thermostat = Thermostat.create(number=1,
                                       name='thermostat 1',
                                       sensor=Sensor.create(number=10),
                                       pid_heating_p=200,
                                       pid_heating_i=100,
                                       pid_heating_d=50,
                                       pid_cooling_p=200,
                                       pid_cooling_i=100,
                                       pid_cooling_d=50,
                                       automatic=True,
                                       room=None,
                                       start=0,
                                       valve_config='equal',
                                       thermostat_group=self._thermostat_group)
        Output.create(number=1)
        Output.create(number=2)
        Output.create(number=3)
        valve_output = Output.create(number=4)
        valve = Valve.create(number=1,
                             name='valve 1',
                             output=valve_output)
        ValveToThermostat.create(thermostat=thermostat,
                                 valve=valve,
                                 mode=ThermostatGroup.Modes.HEATING,
                                 priority=0)
        self._thermostat_controller.refresh_config_from_db()

        expected = ThermostatGroupStatusDTO(id=0,
                                            on=True,
                                            setpoint=0,
                                            cooling=False,
                                            automatic=True,
                                            statusses=[ThermostatStatusDTO(id=1,
                                                                           name='thermostat 1',
                                                                           automatic=True,
                                                                           setpoint=0,
                                                                           sensor_id=10,
                                                                           actual_temperature=10.0,
                                                                           setpoint_temperature=14.0,
                                                                           outside_temperature=10.0,
                                                                           output_0_level=0,
                                                                           output_1_level=0,
                                                                           mode=0,
                                                                           airco=0)])
        self.assertEqual(expected, self._thermostat_controller.get_thermostat_status())

        self._thermostat_controller.set_current_setpoint(thermostat_number=1, heating_temperature=15.0)
        expected.statusses[0].setpoint_temperature = 15.0
        self.assertEqual(expected, self._thermostat_controller.get_thermostat_status())

        self._thermostat_controller.set_per_thermostat_mode(thermostat_number=1,
                                                            automatic=True,
                                                            setpoint=16.0)
        expected.statusses[0].setpoint_temperature = 16.0
        self.assertEqual(expected, self._thermostat_controller.get_thermostat_status())

        preset = self._thermostat_controller.get_current_preset(thermostat_number=1)
        self.assertTrue(preset.active)
        self.assertEqual(30.0, preset.cooling_setpoint)
        self.assertEqual(16.0, preset.heating_setpoint)
        self.assertEqual(Preset.Types.SCHEDULE, preset.type)

        self._thermostat_controller.set_current_preset(thermostat_number=1, preset_type=Preset.Types.PARTY)
        expected.statusses[0].setpoint_temperature = 14.0
        expected.statusses[0].setpoint = expected.setpoint = 5  # PARTY = legacy `5` setpoint
        expected.statusses[0].automatic = expected.automatic = False
        self.assertEqual(expected, self._thermostat_controller.get_thermostat_status())

        self._thermostat_controller.set_thermostat_mode(thermostat_on=True, cooling_mode=True, cooling_on=True, automatic=False, setpoint=4)
        expected.statusses[0].setpoint_temperature = 30.0
        expected.statusses[0].setpoint = expected.setpoint = 4  # VACATION = legacy `4` setpoint
        expected.cooling = True
        self.assertEqual(expected, self._thermostat_controller.get_thermostat_status())

        self._thermostat_controller.set_thermostat_mode(thermostat_on=True, cooling_mode=False, cooling_on=True, automatic=True)
        expected.statusses[0].setpoint_temperature = 16.0
        expected.statusses[0].setpoint = expected.setpoint = 0  # AUTO = legacy `0/1/2` setpoint
        expected.statusses[0].automatic = expected.automatic = True
        expected.cooling = False
        self.assertEqual(expected, self._thermostat_controller.get_thermostat_status())
        super().save()

    # pylint: disable=too-few-public-methods,missing-class-docstring
    class Meta:
        database = database


#
# Now test the database for any issues by attempting to connect!
#

database.connect()

# For testing, we reset the table each time we start

database.drop_tables([Entry, User])

# If that was all fine, we can now create the model tables

database.create_tables([Entry, User])
database.close()


def add_initial_database_content():
    """
    Here we initialise the actual content in the database
    so that it doesn't start out empty
    """

    # We've simply pulled most of this content from the original
    # static web pages