<commit_before># -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`Bo Maryniuk <bo@suse.de>`
'''

# Import Python Libs
from __future__ import absolute_import

# Import Salt Testing Libs
from salttesting import TestCase, skipIf
from salttesting.mock import (
    MagicMock,
    patch,
    NO_MOCK,
    NO_MOCK_REASON
)
from salt.exceptions import CommandExecutionError

import os

from salttesting.helpers import ensure_in_syspath

ensure_in_syspath('../../')

def get_test_data(filename):
    '''
    Return static test data
    '''
    return open(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'zypp'), filename)).read()

# Import Salt Libs
from salt.modules import zypper

# Globals
zypper.__salt__ = {}

@skipIf(NO_MOCK, NO_MOCK_REASON)
class ZypperTestCase(TestCase):
    '''
    Test cases for salt.modules.zypper
    '''

    def test_list_upgrades(self):
        '''
        List package upgrades
        :return:
        '''
        ref_out = {
            'stdout': get_test_data('zypper-updates.xml'),
            'stderr': None,
            'retcode': 0
        }
        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
            upgrades = zypper.list_upgrades(refresh=False)
            assert(len(upgrades) == 3)
            for pkg, version in {'SUSEConnect': '0.2.33-7.1',
                                 'bind-utils': '9.9.6P1-35.1',
                                 'bind-libs': '9.9.6P1-35.1'}.items():
                assert(pkg in upgrades)
                assert(upgrades[pkg] == version)

    def test_list_upgrades_error_handling(self):
        '''
        Test error handling in the list package upgrades.
        :return:
        '''
        # Test handled errors
        ref_out = {
            'stderr': 'Some handled zypper internal error',
            'retcode': 1
        }
        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
            try:
                zypper.list_upgrades(refresh=False)
            except CommandExecutionError as error:
                assert (error.message == ref_out['stderr'])

        # Test unhandled error
        ref_out = {
            'retcode': 1
        }
        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
            try:
                zypper.list_upgrades(refresh=False)
            except CommandExecutionError as error:
                assert (error.message == 'Zypper returned non-zero system exit. See Zypper logs for more details.')

    def test_list_products(self):
        '''
        List products test.
        '''
        ref_out = get_test_data('zypper-products.xml')
        with patch.dict(zypper.__salt__, {'cmd.run': MagicMock(return_value=ref_out)}):
            products = zypper.list_products()
            assert(len(products) == 5)
            assert(['SLES', 'SLES', 'SUSE-Manager-Proxy', 'SUSE-Manager-Server', 'sle-manager-tools-beta'] ==
                   sorted([prod['name'] for prod in products]))
            assert('SUSE LLC <https://www.suse.com/>' in [product['vendor'] for product in products])
            assert([False, False, False, False, True] ==
                   sorted([product['isbase'] for product in products]))
            assert([False, False, False, False, True] ==
                   sorted([product['installed'] for product in products]))
            assert(['0', '0', '0', '0', '0'] ==
                   sorted([product['release'] for product in products]))
            assert([False, False, False, False, u'sles'] ==
                   sorted([product['productline'] for product in products]))
            assert([1509408000, 1522454400, 1522454400, 1730332800, 1730332800] ==
                   sorted([product['eol_t'] for product in products]))

    def test_refresh_db(self):
        '''
        Test if refresh DB handled correctly
        '''
        ref_out = [
            "Repository 'openSUSE-Leap-42.1-LATEST' is up to date.",
            "Repository 'openSUSE-Leap-42.1-Update' is up to date.",
            "Retrieving repository 'openSUSE-Leap-42.1-Update-Non-Oss' metadata",
            "Forcing building of repository cache",
            "Building repository 'openSUSE-Leap-42.1-Update-Non-Oss' cache ..........[done]",
            "Building repository 'salt-dev' cache",
            "All repositories have been refreshed."
        ]

        run_out = {
            'stderr': '', 'stdout': '\n'.join(ref_out), 'retcode': 0
        }

        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=run_out)}):
            result = zypper.refresh_db()
            self.assertEqual(result.get("openSUSE-Leap-42.1-LATEST"), False)
            self.assertEqual(result.get("openSUSE-Leap-42.1-Update"), False)
            self.assertEqual(result.get("openSUSE-Leap-42.1-Update-Non-Oss"), True)

    def test_info_installed(self):
        '''
        Test the return information of the named package(s), installed on the system.

        :return:
        '''
        run_out = {
            'virgo-dummy':
                {'build_date': '2015-07-09T10:55:19Z',
                 'vendor': 'openSUSE Build Service',
                 'description': 'This is the Virgo dummy package used for testing SUSE Manager',
                 'license': 'GPL-2.0', 'build_host': 'sheep05', 'url': 'http://www.suse.com',
                 'build_date_time_t': 1436432119, 'relocations': '(not relocatable)',
                 'source_rpm': 'virgo-dummy-1.0-1.1.src.rpm', 'install_date': '2016-02-23T16:31:57Z',
                 'install_date_time_t': 1456241517, 'summary': 'Virgo dummy package', 'version': '1.0',
                 'signature': 'DSA/SHA1, Thu Jul  9 08:55:33 2015, Key ID 27fa41bd8a7c64f9',
                 'release': '1.1', 'group': 'Applications/System', 'arch': 'noarch', 'size': '17992'},

            'libopenssl1_0_0':
                {'build_date': '2015-11-04T23:20:34Z', 'vendor': 'SUSE LLC <https://www.suse.com/>',
                 'description': 'The OpenSSL Project is a collaborative effort.',
                 'license': 'OpenSSL', 'build_host': 'sheep11', 'url': 'https://www.openssl.org/',
                 'build_date_time_t': 1446675634, 'relocations': '(not relocatable)',
                 'source_rpm': 'openssl-1.0.1i-34.1.src.rpm', 'install_date': '2016-02-23T16:31:35Z',
                 'install_date_time_t': 1456241495, 'summary': 'Secure Sockets and Transport Layer Security',
                 'version': '1.0.1i', 'signature': 'RSA/SHA256, Wed Nov  4 22:21:34 2015, Key ID 70af9e8139db7c82',
                 'release': '34.1', 'group': 'Productivity/Networking/Security', 'packager': 'https://www.suse.com/',
                 'arch': 'x86_64', 'size': '2576912'},
        }
        with patch.dict(zypper.__salt__, {'lowpkg.info': MagicMock(return_value=run_out)}):
            installed = zypper.info_installed()
            # Test overall products length
            assert(len(installed) == 2)

            # Test translated fields
            for pkg_name, pkg_info in installed.items():
                assert(installed[pkg_name].get('source') == run_out[pkg_name]['source_rpm'])

            # Test keys transition from the lowpkg.info
            for pn_key, pn_val in run_out['virgo-dummy'].items():
                if pn_key == 'source_rpm':
                    continue
                assert(installed['virgo-dummy'][pn_key] == pn_val)

if __name__ == '__main__':
    from integration import run_tests
    run_tests(ZypperTestCase, needs_daemon=False)
<commit_msg>Implement test for the info_available<commit_after># -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`Bo Maryniuk <bo@suse.de>`
'''

# Import Python Libs
from __future__ import absolute_import

# Import Salt Testing Libs
from salttesting import TestCase, skipIf
from salttesting.mock import (
    MagicMock,
    patch,
    NO_MOCK,
    NO_MOCK_REASON
)
from salt.exceptions import CommandExecutionError

import os

from salttesting.helpers import ensure_in_syspath

ensure_in_syspath('../../')

def get_test_data(filename):
    '''
    Return static test data
    '''
    return open(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'zypp'), filename)).read()

# Import Salt Libs
from salt.modules import zypper

# Globals
zypper.__salt__ = {}

@skipIf(NO_MOCK, NO_MOCK_REASON)
class ZypperTestCase(TestCase):
    '''
    Test cases for salt.modules.zypper
    '''

    def test_list_upgrades(self):
        '''
        List package upgrades
        :return:
        '''
        ref_out = {
            'stdout': get_test_data('zypper-updates.xml'),
            'stderr': None,
            'retcode': 0
        }
        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
            upgrades = zypper.list_upgrades(refresh=False)
            assert(len(upgrades) == 3)
            for pkg, version in {'SUSEConnect': '0.2.33-7.1',
                                 'bind-utils': '9.9.6P1-35.1',
                                 'bind-libs': '9.9.6P1-35.1'}.items():
                assert(pkg in upgrades)
                assert(upgrades[pkg] == version)

    def test_list_upgrades_error_handling(self):
        '''
        Test error handling in the list package upgrades.
        :return:
        '''
        # Test handled errors
        ref_out = {
            'stderr': 'Some handled zypper internal error',
            'retcode': 1
        }
        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
            try:
                zypper.list_upgrades(refresh=False)
            except CommandExecutionError as error:
                assert (error.message == ref_out['stderr'])

        # Test unhandled error
        ref_out = {
            'retcode': 1
        }
        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=ref_out)}):
            try:
                zypper.list_upgrades(refresh=False)
            except CommandExecutionError as error:
                assert (error.message == 'Zypper returned non-zero system exit. See Zypper logs for more details.')

    def test_list_products(self):
        '''
        List products test.
        '''
        ref_out = get_test_data('zypper-products.xml')
        with patch.dict(zypper.__salt__, {'cmd.run': MagicMock(return_value=ref_out)}):
            products = zypper.list_products()
            assert(len(products) == 5)
            assert(['SLES', 'SLES', 'SUSE-Manager-Proxy', 'SUSE-Manager-Server', 'sle-manager-tools-beta'] ==
                   sorted([prod['name'] for prod in products]))
            assert('SUSE LLC <https://www.suse.com/>' in [product['vendor'] for product in products])
            assert([False, False, False, False, True] ==
                   sorted([product['isbase'] for product in products]))
            assert([False, False, False, False, True] ==
                   sorted([product['installed'] for product in products]))
            assert(['0', '0', '0', '0', '0'] ==
                   sorted([product['release'] for product in products]))
            assert([False, False, False, False, u'sles'] ==
                   sorted([product['productline'] for product in products]))
            assert([1509408000, 1522454400, 1522454400, 1730332800, 1730332800] ==
                   sorted([product['eol_t'] for product in products]))

    def test_refresh_db(self):
        '''
        Test if refresh DB handled correctly
        '''
        ref_out = [
            "Repository 'openSUSE-Leap-42.1-LATEST' is up to date.",
            "Repository 'openSUSE-Leap-42.1-Update' is up to date.",
            "Retrieving repository 'openSUSE-Leap-42.1-Update-Non-Oss' metadata",
            "Forcing building of repository cache",
            "Building repository 'openSUSE-Leap-42.1-Update-Non-Oss' cache ..........[done]",
            "Building repository 'salt-dev' cache",
            "All repositories have been refreshed."
        ]

        run_out = {
            'stderr': '', 'stdout': '\n'.join(ref_out), 'retcode': 0
        }

        with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=run_out)}):
            result = zypper.refresh_db()
            self.assertEqual(result.get("openSUSE-Leap-42.1-LATEST"), False)
            self.assertEqual(result.get("openSUSE-Leap-42.1-Update"), False)
            self.assertEqual(result.get("openSUSE-Leap-42.1-Update-Non-Oss"), True)

    def test_info_installed(self):
        '''
        Test the return information of the named package(s), installed on the system.

        :return:
        '''
        run_out = {
            'virgo-dummy':
                {'build_date': '2015-07-09T10:55:19Z',
                 'vendor': 'openSUSE Build Service',
                 'description': 'This is the Virgo dummy package used for testing SUSE Manager',
                 'license': 'GPL-2.0', 'build_host': 'sheep05', 'url': 'http://www.suse.com',
                 'build_date_time_t': 1436432119, 'relocations': '(not relocatable)',
                 'source_rpm': 'virgo-dummy-1.0-1.1.src.rpm', 'install_date': '2016-02-23T16:31:57Z',
                 'install_date_time_t': 1456241517, 'summary': 'Virgo dummy package', 'version': '1.0',
                 'signature': 'DSA/SHA1, Thu Jul  9 08:55:33 2015, Key ID 27fa41bd8a7c64f9',
                 'release': '1.1', 'group': 'Applications/System', 'arch': 'noarch', 'size': '17992'},

            'libopenssl1_0_0':
                {'build_date': '2015-11-04T23:20:34Z', 'vendor': 'SUSE LLC <https://www.suse.com/>',
                 'description': 'The OpenSSL Project is a collaborative effort.',
                 'license': 'OpenSSL', 'build_host': 'sheep11', 'url': 'https://www.openssl.org/',
                 'build_date_time_t': 1446675634, 'relocations': '(not relocatable)',
                 'source_rpm': 'openssl-1.0.1i-34.1.src.rpm', 'install_date': '2016-02-23T16:31:35Z',
                 'install_date_time_t': 1456241495, 'summary': 'Secure Sockets and Transport Layer Security',
                 'version': '1.0.1i', 'signature': 'RSA/SHA256, Wed Nov  4 22:21:34 2015, Key ID 70af9e8139db7c82',
                 'release': '34.1', 'group': 'Productivity/Networking/Security', 'packager': 'https://www.suse.com/',
                 'arch': 'x86_64', 'size': '2576912'},
        }
        with patch.dict(zypper.__salt__, {'lowpkg.info': MagicMock(return_value=run_out)}):
            installed = zypper.info_installed()
            # Test overall products length
            assert(len(installed) == 2)

            # Test translated fields
            for pkg_name, pkg_info in installed.items():
                assert(installed[pkg_name].get('source') == run_out[pkg_name]['source_rpm'])

            # Test keys transition from the lowpkg.info
            for pn_key, pn_val in run_out['virgo-dummy'].items():
                if pn_key == 'source_rpm':
                    continue
                assert(installed['virgo-dummy'][pn_key] == pn_val)

    def test_info_available(self):
        '''
        Test return the information of the named package available for the system.

        :return:
        '''
        test_pkgs = ['vim', 'emacs']
        ref_out = get_test_data('zypper-available.txt')
        with patch.dict(zypper.__salt__, {'cmd.run_stdout': MagicMock(return_value=ref_out)}):
            available = zypper.info_available(*test_pkgs, refresh=False)
            assert (len(available) == 2)
            for pkg_name, pkg_info in available.items():
                assert(pkg_name in test_pkgs)

            assert(available['emacs']['status'] == 'up-to-date')
            assert(available['emacs']['installed'] == True)
            assert(available['emacs']['support level'] == 'Level 3')
            assert(available['emacs']['vendor'] == 'SUSE LLC <https://www.suse.com/>')
            assert(available['emacs']['summary'] == 'GNU Emacs Base Package')

            assert(available['vim']['status'] == 'not installed')
            assert(available['vim']['installed'] == False)
            assert(available['vim']['support level'] == 'Level 3')
            assert(available['vim']['vendor'] == 'SUSE LLC <https://www.suse.com/>')
            assert(available['vim']['summary'] == 'Vi IMproved')

if __name__ == '__main__':
    from integration import run_tests
    run_tests(ZypperTestCase, needs_daemon=False)
<|endoftext|>


<commit_before># -*- coding: UTF-8 -*-
# Copyright 2014-2017 Luc Saffre
# License: BSD (see file COPYING for details)
"""
Base Django settings for Lino Noi applications.

"""

from __future__ import print_function
from __future__ import unicode_literals

from lino.projects.std.settings import *
from lino.api.ad import _
from lino_noi import SETUP_INFO

class Site(Site):

    verbose_name = "Lino Noi"
    version = SETUP_INFO['version']
    url = "http://noi.lino-framework.org/"

    demo_fixtures = ['std', 'demo', 'demo2']
                     # 'linotickets',
                     # 'tractickets', 'luc']

    # project_model = 'tickets.Project'
    # project_model = 'deploy.Milestone'
    textfield_format = 'html'
    user_types_module = 'lino_noi.lib.noi.user_types'
    workflows_module = 'lino_noi.lib.noi.workflows'
    # custom_layouts_module = 'lino_noi.lib.noi.layouts'
    obj2text_template = "**{0}**"

    default_build_method = 'appyodt'

    # experimental use of rest_framework:
    # root_urlconf = 'lino_book.projects.team.urls'

    # TODO: move migrator to lino_noi.projects.team
    migration_class = 'lino_noi.lib.noi.migrate.Migrator'

    auto_configure_logger_names = "atelier django lino lino_xl lino_noi"

    def get_installed_apps(self):
        """Implements :meth:`lino.core.site.Site.get_installed_apps` for Lino
        Noi.

        """
        yield super(Site, self).get_installed_apps()
        # yield 'lino.modlib.extjs'
        # yield 'lino.modlib.bootstrap3'
        yield 'lino.modlib.gfks'
        # yield 'lino.modlib.system'
        # yield 'lino.modlib.users'
        yield 'lino_noi.lib.contacts'
        yield 'lino_noi.lib.users'
        yield 'lino_noi.lib.cal'
        yield 'lino_xl.lib.extensible'
        # yield 'lino_noi.lib.courses'
        # yield 'lino_noi.lib.products'

        yield 'lino_noi.lib.topics'
        # yield 'lino_xl.lib.votes'
        yield 'lino_xl.lib.stars'
        yield 'lino_noi.lib.tickets'
        # yield 'lino_xl.lib.faculties'
        yield 'lino_xl.lib.deploy'
        yield 'lino_noi.lib.clocking'
        yield 'lino_xl.lib.lists'
        yield 'lino_xl.lib.blogs'

        yield 'lino.modlib.changes'
        yield 'lino.modlib.notify'
        yield 'lino.modlib.uploads'
        # yield 'lino_xl.lib.outbox'
        # yield 'lino_xl.lib.excerpts'
        yield 'lino.modlib.export_excel'
        yield 'lino.modlib.tinymce'
        yield 'lino.modlib.smtpd'
        yield 'lino.modlib.weasyprint'
        yield 'lino_xl.lib.appypod'
        # yield 'lino.modlib.wkhtmltopdf'
        yield 'lino.modlib.dashboard'

        # yield 'lino.modlib.awesomeuploader'

        yield 'lino_noi.lib.noi'
        # yield 'lino_xl.lib.inbox'
        yield 'lino_xl.lib.mailbox'
        yield 'lino_xl.lib.meetings'
        yield 'lino_xl.lib.github'
        # yield 'lino.modlib.social_auth'

    # def setup_plugins(self):
    #     super(Site, self).setup_plugins()
        # self.plugins.comments.configure(
        #     commentable_model='tickets.Ticket')
        # self.plugins.faculties.configure(
        #     demander_model='tickets.Ticket')
        # self.plugins.tickets.configure(
        #     site_model='cal.Room',
        #     milestone_model='courses.Course')

    def get_default_required(self, **kw):
        # overrides the default behaviour which would add
        # `auth=True`. In Lino Noi everybody can see everything.
        return kw

    def setup_quicklinks(self, user, tb):
        super(Site, self).setup_quicklinks(user, tb)
        # tb.add_action(self.models.courses.MyActivities)
        tb.add_action(self.models.meetings.MyMeetings)
        # tb.add_action(self.modules.deploy.MyMilestones)
        # tb.add_action(self.models.tickets.MyTickets)
        # tb.add_action(self.models.tickets.TicketsToTriage)
        # tb.add_action(self.models.tickets.TicketsToTalk)
        # tb.add_action(self.modules.tickets.TicketsToDo)
        tb.add_action(self.modules.tickets.RefTickets)
        tb.add_action(self.models.tickets.AllTickets)
        tb.add_action(
            self.models.tickets.AllTickets.insert_action,
            label=_("Submit a ticket"))

        a = self.models.users.MySettings.default_action
        tb.add_instance_action(
            user, action=a, label=_("My settings"))
        # handler = self.action_call(None, a, dict(record_id=user.pk))
        # handler = "function(){%s}" % handler
        # mysettings = dict(text=_("My settings"),
        #                   handler=js_code(handler))

    def do_site_startup(self):
        super(Site, self).do_site_startup()

        from lino.utils.watch import watch_changes as wc

        wc(self.modules.tickets.Ticket, ignore=['_user_cache'])
        wc(self.modules.comments.Comment, master_key='owner')
        # wc(self.modules.clocking.Session, master_key='owner')

        if self.is_installed('votes'):
            wc(self.modules.votes.Vote, master_key='votable')

        if self.is_installed('deploy'):
            wc(self.modules.deploy.Deployment, master_key='ticket')

        if self.is_installed('extjs'):
            self.plugins.extjs.autorefresh_seconds = 0

        # from lino.core.merge import MergeAction
        # from lino_xl.lib.contacts.roles import ContactsStaff
        # lib = self.models
        # for m in (lib.contacts.Company, ):
        #     m.define_action(merge_row=MergeAction(
        #         m, required_roles=set([ContactsStaff])))

# the following line should not be active in a checked-in version
#~ DATABASES['default']['NAME'] = ':memory:'

USE_TZ = True
# TIME_ZONE = 'Europe/Brussels'
# TIME_ZONE = 'Europe/Tallinn'
TIME_ZONE = 'UTC'

<commit_msg>ActiveTickets now in quick links<commit_after># -*- coding: UTF-8 -*-
# Copyright 2014-2017 Luc Saffre
# License: BSD (see file COPYING for details)
"""
Base Django settings for Lino Noi applications.

"""

from __future__ import print_function
from __future__ import unicode_literals

from lino.projects.std.settings import *
from lino.api.ad import _
from lino_noi import SETUP_INFO

class Site(Site):

    verbose_name = "Lino Noi"
    version = SETUP_INFO['version']
    url = "http://noi.lino-framework.org/"

    demo_fixtures = ['std', 'demo', 'demo2']
                     # 'linotickets',
                     # 'tractickets', 'luc']

    # project_model = 'tickets.Project'
    # project_model = 'deploy.Milestone'
    textfield_format = 'html'
    user_types_module = 'lino_noi.lib.noi.user_types'
    workflows_module = 'lino_noi.lib.noi.workflows'
    # custom_layouts_module = 'lino_noi.lib.noi.layouts'
    obj2text_template = "**{0}**"

    default_build_method = 'appyodt'

    # experimental use of rest_framework:
    # root_urlconf = 'lino_book.projects.team.urls'

    # TODO: move migrator to lino_noi.projects.team
    migration_class = 'lino_noi.lib.noi.migrate.Migrator'

    auto_configure_logger_names = "atelier django lino lino_xl lino_noi"

    def get_installed_apps(self):
        """Implements :meth:`lino.core.site.Site.get_installed_apps` for Lino
        Noi.

        """
        yield super(Site, self).get_installed_apps()
        # yield 'lino.modlib.extjs'
        # yield 'lino.modlib.bootstrap3'
        yield 'lino.modlib.gfks'
        # yield 'lino.modlib.system'
        # yield 'lino.modlib.users'
        yield 'lino_noi.lib.contacts'
        yield 'lino_noi.lib.users'
        yield 'lino_noi.lib.cal'
        yield 'lino_xl.lib.extensible'
        # yield 'lino_noi.lib.courses'
        # yield 'lino_noi.lib.products'

        yield 'lino_noi.lib.topics'
        # yield 'lino_xl.lib.votes'
        yield 'lino_xl.lib.stars'
        yield 'lino_noi.lib.tickets'
        # yield 'lino_xl.lib.faculties'
        yield 'lino_xl.lib.deploy'
        yield 'lino_noi.lib.clocking'
        yield 'lino_xl.lib.lists'
        yield 'lino_xl.lib.blogs'

        yield 'lino.modlib.changes'
        yield 'lino.modlib.notify'
        yield 'lino.modlib.uploads'
        # yield 'lino_xl.lib.outbox'
        # yield 'lino_xl.lib.excerpts'
        yield 'lino.modlib.export_excel'
        yield 'lino.modlib.tinymce'
        yield 'lino.modlib.smtpd'
        yield 'lino.modlib.weasyprint'
        yield 'lino_xl.lib.appypod'
        # yield 'lino.modlib.wkhtmltopdf'
        yield 'lino.modlib.dashboard'

        # yield 'lino.modlib.awesomeuploader'

        yield 'lino_noi.lib.noi'
        # yield 'lino_xl.lib.inbox'
        yield 'lino_xl.lib.mailbox'
        yield 'lino_xl.lib.meetings'
        yield 'lino_xl.lib.github'
        # yield 'lino.modlib.social_auth'

    # def setup_plugins(self):
    #     super(Site, self).setup_plugins()
        # self.plugins.comments.configure(
        #     commentable_model='tickets.Ticket')
        # self.plugins.faculties.configure(
        #     demander_model='tickets.Ticket')
        # self.plugins.tickets.configure(
        #     site_model='cal.Room',
        #     milestone_model='courses.Course')

    def get_default_required(self, **kw):
        # overrides the default behaviour which would add
        # `auth=True`. In Lino Noi everybody can see everything.
        return kw

    def setup_quicklinks(self, user, tb):
        super(Site, self).setup_quicklinks(user, tb)
        # tb.add_action(self.models.courses.MyActivities)
        tb.add_action(self.models.meetings.MyMeetings)
        # tb.add_action(self.modules.deploy.MyMilestones)
        # tb.add_action(self.models.tickets.MyTickets)
        # tb.add_action(self.models.tickets.TicketsToTriage)
        # tb.add_action(self.models.tickets.TicketsToTalk)
        # tb.add_action(self.modules.tickets.TicketsToDo)
        tb.add_action(self.models.tickets.RefTickets)
        tb.add_action(self.models.tickets.ActiveTickets)
        tb.add_action(self.models.tickets.AllTickets)
        tb.add_action(
            self.models.tickets.AllTickets.insert_action,
            label=_("Submit a ticket"))

        a = self.models.users.MySettings.default_action
        tb.add_instance_action(
            user, action=a, label=_("My settings"))
        # handler = self.action_call(None, a, dict(record_id=user.pk))
        # handler = "function(){%s}" % handler
        # mysettings = dict(text=_("My settings"),
        #                   handler=js_code(handler))

    def do_site_startup(self):
        super(Site, self).do_site_startup()

        from lino.utils.watch import watch_changes as wc

        wc(self.modules.tickets.Ticket, ignore=['_user_cache'])
        wc(self.modules.comments.Comment, master_key='owner')
        # wc(self.modules.clocking.Session, master_key='owner')

        if self.is_installed('votes'):
            wc(self.modules.votes.Vote, master_key='votable')

        if self.is_installed('deploy'):
            wc(self.modules.deploy.Deployment, master_key='ticket')

        if self.is_installed('extjs'):
            self.plugins.extjs.autorefresh_seconds = 0

        # from lino.core.merge import MergeAction
        # from lino_xl.lib.contacts.roles import ContactsStaff
        # lib = self.models
        # for m in (lib.contacts.Company, ):
        #     m.define_action(merge_row=MergeAction(
        #         m, required_roles=set([ContactsStaff])))

# the following line should not be active in a checked-in version
#~ DATABASES['default']['NAME'] = ':memory:'

USE_TZ = True
# TIME_ZONE = 'Europe/Brussels'
# TIME_ZONE = 'Europe/Tallinn'
TIME_ZONE = 'UTC'

<|endoftext|>


<commit_before>#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")

import bcc
import ctypes
import os
import unittest

class TestUprobes(unittest.TestCase):
    def test_simple_library(self):
        text = """
#include <uapi/linux/ptrace.h>
BPF_TABLE("array", int, u64, stats, 1);
static void incr(int idx) {
    u64 *ptr = stats.lookup(&idx);
    if (ptr)
        ++(*ptr);
}
int count(struct pt_regs *ctx) {
    bpf_trace_printk("count() uprobe fired");
    u32 pid = bpf_get_current_pid_tgid();
    if (pid == PID)
        incr(0);
    return 0;
}"""
        text = text.replace("PID", "%d" % os.getpid())
        print text
        b = bcc.BPF(text=text)
        b.attach_uprobe(name="c", sym="malloc_stats", fn_name="count")
        b.attach_uretprobe(name="c", sym="malloc_stats", fn_name="count")
        libc = ctypes.CDLL("libc.so.6")
        libc.malloc_stats.restype = None
        libc.malloc_stats.argtypes = []
        libc.malloc_stats()
        self.assertEqual(b["stats"][ctypes.c_int(0)].value, 2)
        b.detach_uretprobe(name="c", sym="malloc_stats")
        b.detach_uprobe(name="c", sym="malloc_stats")

    def test_simple_binary(self):
        text = """
#include <uapi/linux/ptrace.h>
BPF_TABLE("array", int, u64, stats, 1);
static void incr(int idx) {
    u64 *ptr = stats.lookup(&idx);
    if (ptr)
        ++(*ptr);
}
int count(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid();
    incr(0);
    return 0;
}"""
        b = bcc.BPF(text=text)
        b.attach_uprobe(name="/usr/bin/python", sym="main", fn_name="count")
        b.attach_uretprobe(name="/usr/bin/python", sym="main", fn_name="count")
        with os.popen("/usr/bin/python -V") as f:
            pass
        self.assertGreater(b["stats"][ctypes.c_int(0)].value, 0)
        b.detach_uretprobe(name="/usr/bin/python", sym="main")
        b.detach_uprobe(name="/usr/bin/python", sym="main")

if __name__ == "__main__":
    unittest.main()
<commit_msg>Fixed failing test_simple_library() in test_uprobes.py<commit_after>#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")

import bcc
import ctypes
import os
import unittest

class TestUprobes(unittest.TestCase):
    def test_simple_library(self):
        text = """
#include <uapi/linux/ptrace.h>
BPF_TABLE("array", int, u64, stats, 1);
static void incr(int idx) {
    u64 *ptr = stats.lookup(&idx);
    if (ptr)
        ++(*ptr);
}
int count(struct pt_regs *ctx) {
    bpf_trace_printk("count() uprobe fired");
    u32 pid = bpf_get_current_pid_tgid();
    if (pid == PID)
        incr(0);
    return 0;
}"""
        test_pid = os.getpid()
        text = text.replace("PID", "%d" % test_pid)
        b = bcc.BPF(text=text)
        b.attach_uprobe(name="c", sym="malloc_stats", fn_name="count", pid=test_pid)
        b.attach_uretprobe(name="c", sym="malloc_stats", fn_name="count", pid=test_pid)
        libc = ctypes.CDLL("libc.so.6")
        libc.malloc_stats.restype = None
        libc.malloc_stats.argtypes = []
        libc.malloc_stats()
        self.assertEqual(b["stats"][ctypes.c_int(0)].value, 2)
        b.detach_uretprobe(name="c", sym="malloc_stats", pid=test_pid)
        b.detach_uprobe(name="c", sym="malloc_stats", pid=test_pid)

    def test_simple_binary(self):
        text = """
#include <uapi/linux/ptrace.h>
BPF_TABLE("array", int, u64, stats, 1);
static void incr(int idx) {
    u64 *ptr = stats.lookup(&idx);
    if (ptr)
        ++(*ptr);
}
int count(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid();
    incr(0);
    return 0;
}"""
        b = bcc.BPF(text=text)
        b.attach_uprobe(name="/usr/bin/python", sym="main", fn_name="count")
        b.attach_uretprobe(name="/usr/bin/python", sym="main", fn_name="count")
        with os.popen("/usr/bin/python -V") as f:
            pass
        self.assertGreater(b["stats"][ctypes.c_int(0)].value, 0)
        b.detach_uretprobe(name="/usr/bin/python", sym="main")
        b.detach_uprobe(name="/usr/bin/python", sym="main")

if __name__ == "__main__":
    unittest.main()
<|endoftext|>


<commit_before>from django.core.management.base import (BaseCommand,
                                         CommandError)
from django.db import transaction

from treeherder.perf.models import (PerformanceAlert,
                                    PerformanceDatum)

class Command(BaseCommand):
    help = """
    Moves performance data from an old signature to
    a new one.
    Useful when renaming perf tests, as it allows
    to combine old signature data with new one.
    """

    def add_arguments(self, parser):
        parser.add_argument(
            '--from',
            action='append',
            help='Original signature (specify multiple times to get multiple signatures)'
        )
        parser.add_argument(
            '--to',
            action='append',
            help='New signature we want to move performance data to '
                 '(specify multiple times to get multiple signature)'
        )

    def handle(self, *args, **options):
        from_signatures = options['from']
        to_signatures = options['to']

        if not (from_signatures and to_signatures):
            raise CommandError("Must specify both old and new signatures")
        if len(from_signatures) != len(to_signatures):
            raise CommandError("Each old signature must have a corresponding new one")

        for from_sign, to_sign in zip(from_signatures, to_signatures):
            self.atomically_reassign_rows(
                [PerformanceDatum, PerformanceAlert],
                from_sign,
                to_sign)

    def atomically_reassign_rows(self, models, from_sign, to_sign):
        """
        :param models: table from which to reassign rows
        """
        with transaction.atomic():
            for model in models:
                model.objects.filter(signature_id=from_sign).update(signature_id=to_sign)
<commit_msg>Bug 1523306 - Use correct field names<commit_after>from django.core.management.base import (BaseCommand,
                                         CommandError)
from django.db import transaction

from treeherder.perf.models import (PerformanceAlert,
                                    PerformanceDatum)

class Command(BaseCommand):
    help = """
    Moves performance data from an old signature to
    a new one.
    Useful when renaming perf tests, as it allows
    to combine old signature data with new one.
    """

    def add_arguments(self, parser):
        parser.add_argument(
            '--from',
            action='append',
            help='Original signature (specify multiple times to get multiple signatures)'
        )
        parser.add_argument(
            '--to',
            action='append',
            help='New signature we want to move performance data to '
                 '(specify multiple times to get multiple signature)'
        )

    def handle(self, *args, **options):
        from_signatures = options['from']
        to_signatures = options['to']

        if not (from_signatures and to_signatures):
            raise CommandError("Must specify both old and new signatures")
        if len(from_signatures) != len(to_signatures):
            raise CommandError("Each old signature must have a corresponding new one")

        with transaction.atomic():
            for from_sign, to_sign in zip(from_signatures, to_signatures):
                PerformanceDatum.objects.filter(signature_id=from_sign).update(signature_id=to_sign)
                PerformanceAlert.objects.filter(series_signature_id=from_sign).update(series_signature_id=to_sign)
<|endoftext|>


<commit_before>import stripe
from datetime import datetime
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings

class Sale(models.Model):
    sale_date   = models.DateTimeField(editable=False)
    charge_id   = models.CharField(max_length=32) # store the stripe charge id for this sale
    amount      = models.IntegerField(null=True, blank=True)
    currency    = models.CharField(max_length = 3, choices=(('gbp', 'GBP'), ('usd', 'USD'), ('eur', 'EUR')), default = 'gbp')
    livemode    = models.BooleanField()
    card        = models.CharField(blank=True, null=True, max_length=255)
    # also store the rider id
    rider       = models.ForeignKey(User)

    def __init__(self, *args, **kwargs):
        super(Sale, self).__init__(*args, **kwargs)

    def __unicode__(self):
        return self.charge_id

    @classmethod
    def charge(cls, token, key, price, currency, description, email):
        """
        Charges a users card using the Stripe token obtained and
        details of the transaction. If successful we pass back a
        sale object with the transaction details.

        price: to be sent through in cents/pennies
            i.e. for GBP 3 we pass through 300

        key: this is the private Stripe key

        currency: a string of the 3 letter ISO code
            e.g. gbp or eur

        description: this will be sent to the customer so they
            can identify the transaction

        Raises a stripe.CardError on errors.
        """

        instance = cls()
        stripe.api_key = key

        try:
            response = stripe.Charge.create(
                amount=price,
                currency=currency,
                source=token,
                description=description,
                receipt_email=email,
                sale_date=datetime.today())
        except Exception, e:
            raise e

        instance.charge_id = response.id
        instance.amount = response.amount
        instance.currency = response.currency
        instance.livemode = response.livemode
        instance.card = response.card.id

        return instance

    class Meta:
        db_table    = 'sales'<commit_msg>Fix bf9cc3e - actually capture sale date!<commit_after>import stripe
from datetime import datetime
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings

class Sale(models.Model):
    sale_date   = models.DateTimeField(editable=False)
    charge_id   = models.CharField(max_length=32) # store the stripe charge id for this sale
    amount      = models.IntegerField(null=True, blank=True)
    currency    = models.CharField(max_length = 3, choices=(('gbp', 'GBP'), ('usd', 'USD'), ('eur', 'EUR')), default = 'gbp')
    livemode    = models.BooleanField()
    card        = models.CharField(blank=True, null=True, max_length=255)
    # also store the rider id
    rider       = models.ForeignKey(User)

    def __init__(self, *args, **kwargs):
        super(Sale, self).__init__(*args, **kwargs)

    def __unicode__(self):
        return self.charge_id

    @classmethod
    def charge(cls, token, key, price, currency, description, email):
        """
        Charges a users card using the Stripe token obtained and
        details of the transaction. If successful we pass back a
        sale object with the transaction details.

        price: to be sent through in cents/pennies
            i.e. for GBP 3 we pass through 300

        key: this is the private Stripe key

        currency: a string of the 3 letter ISO code
            e.g. gbp or eur

        description: this will be sent to the customer so they
            can identify the transaction

        Raises a stripe.CardError on errors.
        """

        instance = cls()
        stripe.api_key = key

        try:
            response = stripe.Charge.create(
                amount=price,
                currency=currency,
                source=token,
                description=description,
                receipt_email=email)
        except Exception, e:
            raise e

        instance.charge_id = response.id
        instance.amount = response.amount
        instance.currency = response.currency
        instance.livemode = response.livemode
        instance.card = response.card.id
        instance.sale_date = datetime.fromtimestamp(response.created)

        return instance

    class Meta:
        db_table    = 'sales'<|endoftext|>


<commit_before>from copy import deepcopy
from unittest.mock import patch

from django.contrib.auth.models import User
from django.core.cache import cache
from django.test import override_settings
from django.urls import reverse

from constance.test import override_config
from jsonschema import validate
from rest_framework.test import APIClient, APITestCase

from kobo.apps.languages.models.language import Language, LanguageRegion
from kobo.apps.languages.models.transcription import (
    TranscriptionService, TranscriptionServiceLanguageM2M)
from kpi.models import Asset

from ..constants import GOOGLETS, make_async_cache_key
from ..models import SubmissionExtras
from .test_submission_extras_content import sample_asset

class ValidateSubmissionTest(APITestCase):
    def setUp(self):
        user = User.objects.create_user(username='someuser', email='user@example.com')

        self.asset = sample_asset(advanced_features={})
        self.asset.owner = user
        self.asset.save()
        self.asset.deploy(backend='mock', active=True)
        self.asset_uid = self.asset.uid
        self.asset_url = f'/api/v2/assets/{self.asset.uid}/?format=json'
        self.client.force_login(user)

    def set_asset_advanced_features(self, features):
        self.asset.advanced_features = features
        self.asset.save()

    def test_asset_post_submission_extra_with_transcript(self):
        self.set_asset_advanced_features({'transcript': {'values': ['q1']}})
        resp = self.client.get(self.asset_url)
        schema = resp.json()['advanced_submission_schema']
        package = {
            'submission': 'abc123-def456',
            'q1': {
              'transcript': {
                'value': 'they said hello',
              }
            }
        }

        validate(package, schema)
        rr = self.client.post(schema['url'], package, format='json')

        package['q1']['transcript'] = {'value': 'they said goodbye'}
        validate(package, schema)
        rr = self.client.post(schema['url'], package, format='json')
        q1transcript = rr.json()['q1']['transcript']
        assert q1transcript['value'] == 'they said goodbye'

    def test_translation_revisions_stored_properly(self):
        self.set_asset_advanced_features({
            'translation': {
                'values': ['q1'],
                'languages': ['tx1', 'tx2'],
            }
        })
        tx_instance = next(self.asset.get_advanced_feature_instances())
        first_post = {
            'q1': {
                'translation': {
                    'tx1': {
                        'value': 'VAL1'
                    }
                }
            }
        }
        summ = tx_instance.compile_revised_record({}, edits=first_post)
        assert summ['q1']['translation']['tx1']['value'] == 'VAL1'
        assert len(summ['q1']['translation']['tx1']['revisions']) == 0
        summ1 = deepcopy(summ)
        second_post = {
            'q1': {
                'translation': {
                    'tx1': {
                        'value': 'VAL2',
                    }
                }
            }
        }

class TranscriptFieldRevisionsOnlyTests(ValidateSubmissionTest):
    def setUp(self):
        ValidateSubmissionTest.setUp(self)
        self.set_asset_advanced_features({
            'transcript': {
                'values': ['q1'],
            }
        })
        self.act1 = next(self.asset.get_advanced_feature_instances())

    def test_simplest(self):
        field = self.act1.revise_field({
            'value': 'V1',
            'revisions': [],
            'dateCreated': '1',
            'dateModified': '1',
        }, {
            'value': 'V2',
        })
        assert field['value'] == 'V2'

    def test_send_delete_character(self):
        field = self.act1.revise_field({
            'value': 'V1',
            'revisions': [],
            'dateCreated': '1',
            'dateModified': '1',
        }, {
            'value': self.act1.DELETE,
        })
        assert field == {}

class TranslatedFieldRevisionsOnlyTests(ValidateSubmissionTest):
    def setUp(self):
        ValidateSubmissionTest.setUp(self)
        self.set_asset_advanced_features({
            'translation': {
                'values': ['q1'],
                'languages': ['tx1', 'tx2'],
            }
        })
        self.txi = next(self.asset.get_advanced_feature_instances())

    def test_simplest(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V1',
                'revisions': [],
                'dateCreated': '1',
                'dateModified': '1',
            }
        }, {
            'tx1': {
                'value': 'V2',
            }
        })

        assert 'tx1' in field
        assert field['tx1']['value'] == 'V2'
        assert len(field['tx1']['revisions']) == 1
        assert field['tx1']['dateCreated'] == '1'
        assert 'dateCreated' not in field['tx1']['revisions'][0]
        assert 'dateModified' in field['tx1']
        assert field['tx1']['dateCreated'] == '1'

    def test_append_empty_string(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V1',
                'revisions': [],
                'dateCreated': '1',
                'dateModified': '1',
            }
        }, {
            'tx1': {
                'value': '',
            }
        })

        assert 'tx1' in field
        assert field['tx1']['value'] == ''

    def test_send_delete_character(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V1',
                'revisions': [],
                'dateCreated': '1',
                'dateModified': '1',
            }
        }, {
            'tx1': {
                'value': self.txi.DELETE,
            }
        })
        assert 'tx1' not in field

    def test_date_created_is_pulled_from_last_revision(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V3',
                'revisions': [
                    {'value': 'V2', 'dateModified': 'B'},
                    {'value': 'V1', 'dateModified': 'A'},
                ]
            }
        }, {
            'tx1': {
                'value': 'V4',
            }
        })
        for revision in field['tx1']['revisions']:
            assert 'revisions' not in revision
        assert field['tx1']['dateCreated'] == 'A'

    def test_second_translation_comes_in(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'T1',
                'dateModified': 'A',
                'dateCreated': 'A',
                'revisions': []
            }
        }, {
            'tx2': {
                'value': 'T2',
            }
        })
        for tx in ['tx1', 'tx2']:
            fx = field[tx]
            assert 'dateCreated' in fx
            assert 'dateModified' in fx
            assert 'revisions' in fx
        assert field['tx1']['dateCreated'] == 'A'

    def test_change_language_list(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'T1',
                'dateModified': 'A',
                'dateCreated': 'A',
                'revisions': []
            }
        }, {
            'tx2': {
                'value': 'T2',
            }
        })
        self.set_asset_advanced_features({
            'translation': {
                'languages': [
                    'tx1', 'tx3'
                ]
            }
        })
        resp = self.client.get(self.asset_url)
        schema = resp.json()['advanced_submission_schema']
        package = {'submission': 'abc123-def456'}
        package['q1'] = {
            'transcript': {
                'value': 'they said hello',
            },
        }
        # validate(package, schema)

class GoogleTranscriptionSubmissionTest(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user(username='someuser', email='user@example.com')
        self.asset = sample_asset(advanced_features={'transcript': {'values': ['q1']}})
        self.asset.owner = self.user
        self.asset.save()
        self.asset.deploy(backend='mock', active=True)
        self.asset_url = f'/api/v2/assets/{self.asset.uid}/?format=json'
        self.client.force_login(self.user)
        service = TranscriptionService.objects.create(code='goog')
        language = Language.objects.create(name='', code='')
        language_region = LanguageRegion.objects.create(language=language, name='', code='')
        TranscriptionServiceLanguageM2M.objects.create(
            language=language,
            region=language_region,
            service=service
        )

    @override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}})
    @override_config(ASR_MT_INVITEE_USERNAMES='*')
    @patch('google.cloud.speech.SpeechClient')
    @patch('google.cloud.storage.Client')
    def test_google_transcript_post(self, m1, m2):
        url = reverse('advanced-submission-post', args=[self.asset.uid])
        submission_id = 'abc123-def456'
        submission = {
            '__version__': self.asset.latest_deployed_version.uid,
            'q1': 'audio_conversion_test_clip.mp4',
            '_uuid': submission_id,
            '_attachments': [
                {
                    'id': 1,
                    'filename': 'someuser/audio_conversion_test_clip.mp4',
                    'mimetype': 'video/mp4',
                },
            ],
            '_submitted_by': self.user.username
        }
        self.asset.deployment.mock_submissions([submission])

        data = {
            'submission': submission_id,
            'q1': {GOOGLETS: {'status': 'requested', 'languageCode': ''}}
        }
        with self.assertNumQueries(41):
            res = self.client.post(url, data, format='json')
        self.assertContains(res, 'complete')
        with self.assertNumQueries(16):
            self.client.post(url, data, format='json')

    @override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}})
    @override_config(ASR_MT_INVITEE_USERNAMES='*')
    @patch('google.cloud.storage.Client')
    @patch('googleapiclient.discovery.build')
    def test_google_transcript_slow_post(self, m1, m2):
        """Tests when slow running operation has already started"""
        url = reverse('advanced-submission-post', args=[self.asset.uid])
        submission_id = 'abc123-def456'
        xpath = 'q1'
        source = ''
        operation_name = 'testop'
        cache.set(make_async_cache_key(self.user.pk, submission_id, xpath, source), operation_name)
        submission = {
            '__version__': self.asset.latest_deployed_version.uid,
            'q1': 'audio_conversion_test_clip.mp4',
            '_uuid': submission_id,
            '_attachments': [],
            '_submitted_by': self.user.username
        }
        self.asset.deployment.mock_submissions([submission])

        data = {
            'submission': submission_id,
            'q1': {GOOGLETS: {'status': 'requested', 'languageCode': ''}}
        }
        res = self.client.post(url, data, format='json')
        self.assertContains(res, 'complete')

    @override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}})
    def test_google_transcript_permissions(self):
        url = reverse('advanced-submission-post', args=[self.asset.uid])
        submission_id = 'abc123-def456'
        submission = {
            '__version__': self.asset.latest_deployed_version.uid,
            'q1': 'audio_conversion_test_clip.mp4',
            '_uuid': submission_id,
            '_attachments': [],
            '_submitted_by': self.user.username
        }
        self.asset.deployment.mock_submissions([submission])
        SubmissionExtras.objects.create(
            submission_uuid=submission_id,
            content={'q1': {'transcript': {'value': 'hello'}}},
            asset=self.asset
        )

        with override_config(ASR_MT_INVITEE_USERNAMES='*'):
            res = self.client.post(url, {}, format='json')
            self.assertEqual(res.status_code, 400)

        self.asset.permissions.all().delete()
        self.asset.owner = None
        self.asset.save()
        res = self.client.get(url + '?submission=' + submission_id, format='json')
        self.assertEqual(res.status_code, 404)
<commit_msg>Update number of queries to match ad55d6436<commit_after>from copy import deepcopy
from unittest.mock import patch

from django.contrib.auth.models import User
from django.core.cache import cache
from django.test import override_settings
from django.urls import reverse

from constance.test import override_config
from jsonschema import validate
from rest_framework.test import APIClient, APITestCase

from kobo.apps.languages.models.language import Language, LanguageRegion
from kobo.apps.languages.models.transcription import (
    TranscriptionService, TranscriptionServiceLanguageM2M)
from kpi.models import Asset

from ..constants import GOOGLETS, make_async_cache_key
from ..models import SubmissionExtras
from .test_submission_extras_content import sample_asset

class ValidateSubmissionTest(APITestCase):
    def setUp(self):
        user = User.objects.create_user(username='someuser', email='user@example.com')

        self.asset = sample_asset(advanced_features={})
        self.asset.owner = user
        self.asset.save()
        self.asset.deploy(backend='mock', active=True)
        self.asset_uid = self.asset.uid
        self.asset_url = f'/api/v2/assets/{self.asset.uid}/?format=json'
        self.client.force_login(user)

    def set_asset_advanced_features(self, features):
        self.asset.advanced_features = features
        self.asset.save()

    def test_asset_post_submission_extra_with_transcript(self):
        self.set_asset_advanced_features({'transcript': {'values': ['q1']}})
        resp = self.client.get(self.asset_url)
        schema = resp.json()['advanced_submission_schema']
        package = {
            'submission': 'abc123-def456',
            'q1': {
              'transcript': {
                'value': 'they said hello',
              }
            }
        }

        validate(package, schema)
        rr = self.client.post(schema['url'], package, format='json')

        package['q1']['transcript'] = {'value': 'they said goodbye'}
        validate(package, schema)
        rr = self.client.post(schema['url'], package, format='json')
        q1transcript = rr.json()['q1']['transcript']
        assert q1transcript['value'] == 'they said goodbye'

    def test_translation_revisions_stored_properly(self):
        self.set_asset_advanced_features({
            'translation': {
                'values': ['q1'],
                'languages': ['tx1', 'tx2'],
            }
        })
        tx_instance = next(self.asset.get_advanced_feature_instances())
        first_post = {
            'q1': {
                'translation': {
                    'tx1': {
                        'value': 'VAL1'
                    }
                }
            }
        }
        summ = tx_instance.compile_revised_record({}, edits=first_post)
        assert summ['q1']['translation']['tx1']['value'] == 'VAL1'
        assert len(summ['q1']['translation']['tx1']['revisions']) == 0
        summ1 = deepcopy(summ)
        second_post = {
            'q1': {
                'translation': {
                    'tx1': {
                        'value': 'VAL2',
                    }
                }
            }
        }

class TranscriptFieldRevisionsOnlyTests(ValidateSubmissionTest):
    def setUp(self):
        ValidateSubmissionTest.setUp(self)
        self.set_asset_advanced_features({
            'transcript': {
                'values': ['q1'],
            }
        })
        self.act1 = next(self.asset.get_advanced_feature_instances())

    def test_simplest(self):
        field = self.act1.revise_field({
            'value': 'V1',
            'revisions': [],
            'dateCreated': '1',
            'dateModified': '1',
        }, {
            'value': 'V2',
        })
        assert field['value'] == 'V2'

    def test_send_delete_character(self):
        field = self.act1.revise_field({
            'value': 'V1',
            'revisions': [],
            'dateCreated': '1',
            'dateModified': '1',
        }, {
            'value': self.act1.DELETE,
        })
        assert field == {}

class TranslatedFieldRevisionsOnlyTests(ValidateSubmissionTest):
    def setUp(self):
        ValidateSubmissionTest.setUp(self)
        self.set_asset_advanced_features({
            'translation': {
                'values': ['q1'],
                'languages': ['tx1', 'tx2'],
            }
        })
        self.txi = next(self.asset.get_advanced_feature_instances())

    def test_simplest(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V1',
                'revisions': [],
                'dateCreated': '1',
                'dateModified': '1',
            }
        }, {
            'tx1': {
                'value': 'V2',
            }
        })

        assert 'tx1' in field
        assert field['tx1']['value'] == 'V2'
        assert len(field['tx1']['revisions']) == 1
        assert field['tx1']['dateCreated'] == '1'
        assert 'dateCreated' not in field['tx1']['revisions'][0]
        assert 'dateModified' in field['tx1']
        assert field['tx1']['dateCreated'] == '1'

    def test_append_empty_string(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V1',
                'revisions': [],
                'dateCreated': '1',
                'dateModified': '1',
            }
        }, {
            'tx1': {
                'value': '',
            }
        })

        assert 'tx1' in field
        assert field['tx1']['value'] == ''

    def test_send_delete_character(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V1',
                'revisions': [],
                'dateCreated': '1',
                'dateModified': '1',
            }
        }, {
            'tx1': {
                'value': self.txi.DELETE,
            }
        })
        assert 'tx1' not in field

    def test_date_created_is_pulled_from_last_revision(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'V3',
                'revisions': [
                    {'value': 'V2', 'dateModified': 'B'},
                    {'value': 'V1', 'dateModified': 'A'},
                ]
            }
        }, {
            'tx1': {
                'value': 'V4',
            }
        })
        for revision in field['tx1']['revisions']:
            assert 'revisions' not in revision
        assert field['tx1']['dateCreated'] == 'A'

    def test_second_translation_comes_in(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'T1',
                'dateModified': 'A',
                'dateCreated': 'A',
                'revisions': []
            }
        }, {
            'tx2': {
                'value': 'T2',
            }
        })
        for tx in ['tx1', 'tx2']:
            fx = field[tx]
            assert 'dateCreated' in fx
            assert 'dateModified' in fx
            assert 'revisions' in fx
        assert field['tx1']['dateCreated'] == 'A'

    def test_change_language_list(self):
        field = self.txi.revise_field({
            'tx1': {
                'value': 'T1',
                'dateModified': 'A',
                'dateCreated': 'A',
                'revisions': []
            }
        }, {
            'tx2': {
                'value': 'T2',
            }
        })
        self.set_asset_advanced_features({
            'translation': {
                'languages': [
                    'tx1', 'tx3'
                ]
            }
        })
        resp = self.client.get(self.asset_url)
        schema = resp.json()['advanced_submission_schema']
        package = {'submission': 'abc123-def456'}
        package['q1'] = {
            'transcript': {
                'value': 'they said hello',
            },
        }
        # validate(package, schema)

class GoogleTranscriptionSubmissionTest(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user(username='someuser', email='user@example.com')
        self.asset = sample_asset(advanced_features={'transcript': {'values': ['q1']}})
        self.asset.owner = self.user
        self.asset.save()
        self.asset.deploy(backend='mock', active=True)
        self.asset_url = f'/api/v2/assets/{self.asset.uid}/?format=json'
        self.client.force_login(self.user)
        service = TranscriptionService.objects.create(code='goog')
        language = Language.objects.create(name='', code='')
        language_region = LanguageRegion.objects.create(language=language, name='', code='')
        TranscriptionServiceLanguageM2M.objects.create(
            language=language,
            region=language_region,
            service=service
        )

    @override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}})
    @override_config(ASR_MT_INVITEE_USERNAMES='*')
    @patch('google.cloud.speech.SpeechClient')
    @patch('google.cloud.storage.Client')
    def test_google_transcript_post(self, m1, m2):
        url = reverse('advanced-submission-post', args=[self.asset.uid])
        submission_id = 'abc123-def456'
        submission = {
            '__version__': self.asset.latest_deployed_version.uid,
            'q1': 'audio_conversion_test_clip.mp4',
            '_uuid': submission_id,
            '_attachments': [
                {
                    'id': 1,
                    'filename': 'someuser/audio_conversion_test_clip.mp4',
                    'mimetype': 'video/mp4',
                },
            ],
            '_submitted_by': self.user.username
        }
        self.asset.deployment.mock_submissions([submission])

        data = {
            'submission': submission_id,
            'q1': {GOOGLETS: {'status': 'requested', 'languageCode': ''}}
        }
        with self.assertNumQueries(47):
            res = self.client.post(url, data, format='json')
        self.assertContains(res, 'complete')
        with self.assertNumQueries(19):
            self.client.post(url, data, format='json')

    @override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}})
    @override_config(ASR_MT_INVITEE_USERNAMES='*')
    @patch('google.cloud.storage.Client')
    @patch('googleapiclient.discovery.build')
    def test_google_transcript_slow_post(self, m1, m2):
        """Tests when slow running operation has already started"""
        url = reverse('advanced-submission-post', args=[self.asset.uid])
        submission_id = 'abc123-def456'
        xpath = 'q1'
        source = ''
        operation_name = 'testop'
        cache.set(make_async_cache_key(self.user.pk, submission_id, xpath, source), operation_name)
        submission = {
            '__version__': self.asset.latest_deployed_version.uid,
            'q1': 'audio_conversion_test_clip.mp4',
            '_uuid': submission_id,
            '_attachments': [],
            '_submitted_by': self.user.username
        }
        self.asset.deployment.mock_submissions([submission])

        data = {
            'submission': submission_id,
            'q1': {GOOGLETS: {'status': 'requested', 'languageCode': ''}}
        }
        res = self.client.post(url, data, format='json')
        self.assertContains(res, 'complete')

    @override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}})
    def test_google_transcript_permissions(self):
        url = reverse('advanced-submission-post', args=[self.asset.uid])
        submission_id = 'abc123-def456'
        submission = {
            '__version__': self.asset.latest_deployed_version.uid,
            'q1': 'audio_conversion_test_clip.mp4',
            '_uuid': submission_id,
            '_attachments': [],
            '_submitted_by': self.user.username
        }
        self.asset.deployment.mock_submissions([submission])
        SubmissionExtras.objects.create(
            submission_uuid=submission_id,
            content={'q1': {'transcript': {'value': 'hello'}}},
            asset=self.asset
        )

        with override_config(ASR_MT_INVITEE_USERNAMES='*'):
            res = self.client.post(url, {}, format='json')
            self.assertEqual(res.status_code, 400)

        self.asset.permissions.all().delete()
        self.asset.owner = None
        self.asset.save()
        res = self.client.get(url + '?submission=' + submission_id, format='json')
        self.assertEqual(res.status_code, 404)
<|endoftext|>


<commit_before>__license__ = """
Copyright 2012 DISQUS

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import logging
import mock

from itertools import islice
from kazoo.testing import KazooTestCase

from samsa.test.integration import KafkaIntegrationTestCase, polling_timeout
from samsa.test.case import TestCase
from samsa.cluster import Cluster
from samsa.config import ConsumerConfig
from samsa.topics import Topic
from samsa.partitions import Partition
from samsa.consumer.partitions import PartitionOwnerRegistry, OwnedPartition

logger = logging.getLogger(__name__)

class TestPartitionOwnerRegistry(KazooTestCase):
    """Test the methods of :class:`samsa.consumer.PartitionOwnerRegistry`.
    """

    def setUp(self):
        super(TestPartitionOwnerRegistry, self).setUp()
        self.c = Cluster(self.client)
        self.c.brokers = mock.MagicMock()
        broker = mock.Mock()
        broker.id = 1
        self.c.brokers.__getitem__.return_value = broker

        self.consumer = mock.Mock()
        self.consumer.id  = 1234
        self.topic = mock.Mock()
        self.topic.name = 'topic'

        self.por = PartitionOwnerRegistry(
            self.consumer,
            self.c,
            self.topic,
            'group'
        )

        # Create 5 partitions with on the same topic and broker
        self.partitions = []
        for i in xrange(5):
            self.partitions.append(
                Partition(self.c, self.topic, broker, i)
            )

    def run(self, *args, **kwargs):
        # Creating owned partitions should not cause them to start consuming.
        with mock.patch.object(OwnedPartition, '_create_thread'):
            return super(TestPartitionOwnerRegistry, self).run(*args, **kwargs)

    def test_crd(self):
        """Test partition *c*reate, *r*ead, and *d*elete.
        """

        # Add the first 3 partitions to the registry and see that they're set
        self.por.add(self.partitions[:3])
        self.assertEquals(
            self.por.get(),
            set(self.partitions[:3])
        )

        # Remove the first partition and see that only [1, 2] exist
        self.por.remove([self.partitions[0]])
        self.assertEquals(
            self.por.get(),
            set(self.partitions[1:3])
        )

    def test_grows(self):
        """Test that the reference returned by
        :func:`samsa.consumer.partitions.PartitionOwnerRegistry.get` reflects
        the latest state.

        """
        partitions = self.por.get()
        self.assertEquals(len(partitions), 0)

        self.por.add(self.partitions)
        self.assertEquals(len(partitions), len(self.partitions))

#@unittest.skip("Consumer has issues.")
class TestConsumer(KazooTestCase, TestCase):

    def setUp(self):
        super(TestConsumer, self).setUp()
        self.c = Cluster(self.client)

    def _register_fake_brokers(self, n=1):
        self.client.ensure_path("/brokers/ids")
        for i in xrange(n):
            path = "/brokers/ids/%d" % i
            data = "creator:127.0.0.1:%s" % (9092 + i)
            self.client.create(path, data)

    @mock.patch.object(OwnedPartition, '_fetch')
    def test_assigns_partitions(self, *args):
        """
        Test rebalance

        Adjust n_* to see how rebalancing performs.

        """
        n_partitions = 10
        n_consumers = 3
        self._register_fake_brokers(n_partitions)
        t = Topic(self.c, 'testtopic')

        consumers = [t.subscribe('group1') for i in xrange(n_consumers)]

        partitions = []
        for c in consumers:
            partitions.extend(c.partitions)

        # test that there are no duplicates.
        self.assertEquals(len(partitions), n_partitions)
        # test that every partitions is represented.
        self.assertEquals(len(set(partitions)), n_partitions)

    @mock.patch.object(Partition, 'fetch')
    def test_commits_offsets(self, fetch):
        """Test that message offsets are persisted to ZK.

        """
        self._register_fake_brokers(1)
        t = Topic(self.c, 'testtopic')

        c = t.subscribe('group')
        msgs = []
        for i in xrange(1, 10):
            msg = mock.Mock()
            msg.next_offset = 3 * i
            msg.payload = str(i) * 3
            msgs.append(msg)
        fetch.return_value = msgs

        c.next_message(10)
        self.assertEquals(len(c.partitions), 1)
        p = list(c.partitions)[0]

        self.assertEquals(p.offset, 3)
        c.commit_offsets()

        d, stat = self.client.get(p.path)
        self.assertEquals(d, '3')

    @mock.patch.object(Partition, 'fetch')
    def test_consumer_remembers_offset(self, fetch):
        """Test that offsets are successfully retrieved from zk.

        """
        topic = 'testtopic'
        group = 'testgroup'
        offset = 10

        fake_partition = mock.Mock()
        fake_partition.cluster = self.c
        fake_partition.topic.name = topic
        fake_partition.broker.id = 0
        fake_partition.number = 0
        fetch.return_value = ()

        op = OwnedPartition(fake_partition, group)
        op._current_offset = offset
        op.commit_offset()

        self._register_fake_brokers(1)
        t = Topic(self.c, topic)
        c = t.subscribe(group)

        self.assertEquals(len(c.partitions), 1)
        p = list(c.partitions)[0]
        self.assertEquals(p.offset, offset)

        self.assertEquals(None, p.next_message(0))
        fetch.assert_called_with(offset, ConsumerConfig.fetch_size)

class TestConsumerIntegration(KafkaIntegrationTestCase):

    def setUp(self):
        super(TestConsumerIntegration, self).setUp()
        self.kafka = self.kafka_broker.client

    def test_consumes(self):
        """Test that we can consume messages from kafka.

        """
        topic = 'topic'
        messages = ['hello world', 'foobar']

        # publish `messages` to `topic`
        self.kafka.produce(topic, 0, messages)

        t = Topic(self.kafka_cluster, topic)

        # subscribe to `topic`
        consumer = t.subscribe('group2')

        def test():
            """Test that `consumer` can see `messages`.

            catches exceptions so we can retry while we wait for kafka to
            coallesce.

            """
            logger.debug('Running `test`...')
            try:
                self.assertEquals(
                    list(islice(consumer, 0, len(messages))),
                    messages
                )
                return True
            except AssertionError as e:
                logger.exception('Caught exception: %s', e)
                return False

        # wait for one second for :func:`test` to return true or raise an error
        polling_timeout(test, 1)

        old_offset = [p.offset for p in consumer.partitions][0]
        # test that the offset of our 1 partition is not 0
        self.assertTrue(old_offset > 0)
        # and that consumer contains no more messages.
        self.assertTrue(consumer.empty())

        # repeat and see if offset grows.
        self.kafka.produce(topic, 0, messages)
        polling_timeout(test, 1)
        self.assertTrue([p.offset for p in consumer.partitions][0] > old_offset)

    def test_empty_topic(self):
        """Test that consuming an empty topic returns an empty list.

        """
        topic = 'topic'
        t = Topic(self.kafka_cluster, topic)

        consumer = t.subscribe('group2')
        self.assertTrue(consumer.empty())
<commit_msg>wait for fetch thread to get going.<commit_after>__license__ = """
Copyright 2012 DISQUS

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import logging
import mock

from itertools import islice
from kazoo.testing import KazooTestCase

from samsa.test.integration import KafkaIntegrationTestCase, polling_timeout
from samsa.test.case import TestCase
from samsa.cluster import Cluster
from samsa.config import ConsumerConfig
from samsa.topics import Topic
from samsa.partitions import Partition
from samsa.consumer.partitions import PartitionOwnerRegistry, OwnedPartition

logger = logging.getLogger(__name__)

class TestPartitionOwnerRegistry(KazooTestCase):
    """Test the methods of :class:`samsa.consumer.PartitionOwnerRegistry`.
    """

    def setUp(self):
        super(TestPartitionOwnerRegistry, self).setUp()
        self.c = Cluster(self.client)
        self.c.brokers = mock.MagicMock()
        broker = mock.Mock()
        broker.id = 1
        self.c.brokers.__getitem__.return_value = broker

        self.consumer = mock.Mock()
        self.consumer.id  = 1234
        self.topic = mock.Mock()
        self.topic.name = 'topic'

        self.por = PartitionOwnerRegistry(
            self.consumer,
            self.c,
            self.topic,
            'group'
        )

        # Create 5 partitions with on the same topic and broker
        self.partitions = []
        for i in xrange(5):
            self.partitions.append(
                Partition(self.c, self.topic, broker, i)
            )

    def run(self, *args, **kwargs):
        # Creating owned partitions should not cause them to start consuming.
        with mock.patch.object(OwnedPartition, '_create_thread'):
            return super(TestPartitionOwnerRegistry, self).run(*args, **kwargs)

    def test_crd(self):
        """Test partition *c*reate, *r*ead, and *d*elete.
        """

        # Add the first 3 partitions to the registry and see that they're set
        self.por.add(self.partitions[:3])
        self.assertEquals(
            self.por.get(),
            set(self.partitions[:3])
        )

        # Remove the first partition and see that only [1, 2] exist
        self.por.remove([self.partitions[0]])
        self.assertEquals(
            self.por.get(),
            set(self.partitions[1:3])
        )

    def test_grows(self):
        """Test that the reference returned by
        :func:`samsa.consumer.partitions.PartitionOwnerRegistry.get` reflects
        the latest state.

        """
        partitions = self.por.get()
        self.assertEquals(len(partitions), 0)

        self.por.add(self.partitions)
        self.assertEquals(len(partitions), len(self.partitions))

#@unittest.skip("Consumer has issues.")
class TestConsumer(KazooTestCase, TestCase):

    def setUp(self):
        super(TestConsumer, self).setUp()
        self.c = Cluster(self.client)

    def _register_fake_brokers(self, n=1):
        self.client.ensure_path("/brokers/ids")
        for i in xrange(n):
            path = "/brokers/ids/%d" % i
            data = "creator:127.0.0.1:%s" % (9092 + i)
            self.client.create(path, data)

    @mock.patch.object(OwnedPartition, '_fetch')
    def test_assigns_partitions(self, *args):
        """
        Test rebalance

        Adjust n_* to see how rebalancing performs.

        """
        n_partitions = 10
        n_consumers = 3
        self._register_fake_brokers(n_partitions)
        t = Topic(self.c, 'testtopic')

        consumers = [t.subscribe('group1') for i in xrange(n_consumers)]

        partitions = []
        for c in consumers:
            partitions.extend(c.partitions)

        # test that there are no duplicates.
        self.assertEquals(len(partitions), n_partitions)
        # test that every partitions is represented.
        self.assertEquals(len(set(partitions)), n_partitions)

    @mock.patch.object(Partition, 'fetch')
    def test_commits_offsets(self, fetch):
        """Test that message offsets are persisted to ZK.

        """
        self._register_fake_brokers(1)
        t = Topic(self.c, 'testtopic')

        c = t.subscribe('group')
        msgs = []
        for i in xrange(1, 10):
            msg = mock.Mock()
            msg.next_offset = 3 * i
            msg.payload = str(i) * 3
            msgs.append(msg)
        fetch.return_value = msgs

        self.assertPassesWithMultipleAttempts(
            lambda: self.assertTrue(c.next_message(10) is not None),
            5
        )
        self.assertEquals(len(c.partitions), 1)
        p = list(c.partitions)[0]

        self.assertEquals(p.offset, 3)
        c.commit_offsets()

        d, stat = self.client.get(p.path)
        self.assertEquals(d, '3')

    @mock.patch.object(Partition, 'fetch')
    def test_consumer_remembers_offset(self, fetch):
        """Test that offsets are successfully retrieved from zk.

        """
        topic = 'testtopic'
        group = 'testgroup'
        offset = 10

        fake_partition = mock.Mock()
        fake_partition.cluster = self.c
        fake_partition.topic.name = topic
        fake_partition.broker.id = 0
        fake_partition.number = 0
        fetch.return_value = ()

        op = OwnedPartition(fake_partition, group)
        op._current_offset = offset
        op.commit_offset()

        self._register_fake_brokers(1)
        t = Topic(self.c, topic)
        c = t.subscribe(group)

        self.assertEquals(len(c.partitions), 1)
        p = list(c.partitions)[0]
        self.assertEquals(p.offset, offset)

        self.assertEquals(None, p.next_message(0))
        fetch.assert_called_with(offset, ConsumerConfig.fetch_size)

class TestConsumerIntegration(KafkaIntegrationTestCase):

    def setUp(self):
        super(TestConsumerIntegration, self).setUp()
        self.kafka = self.kafka_broker.client

    def test_consumes(self):
        """Test that we can consume messages from kafka.

        """
        topic = 'topic'
        messages = ['hello world', 'foobar']

        # publish `messages` to `topic`
        self.kafka.produce(topic, 0, messages)

        t = Topic(self.kafka_cluster, topic)

        # subscribe to `topic`
        consumer = t.subscribe('group2')

        def test():
            """Test that `consumer` can see `messages`.

            catches exceptions so we can retry while we wait for kafka to
            coallesce.

            """
            logger.debug('Running `test`...')
            try:
                self.assertEquals(
                    list(islice(consumer, 0, len(messages))),
                    messages
                )
                return True
            except AssertionError as e:
                logger.exception('Caught exception: %s', e)
                return False

        # wait for one second for :func:`test` to return true or raise an error
        polling_timeout(test, 1)

        old_offset = [p.offset for p in consumer.partitions][0]
        # test that the offset of our 1 partition is not 0
        self.assertTrue(old_offset > 0)
        # and that consumer contains no more messages.
        self.assertTrue(consumer.empty())

        # repeat and see if offset grows.
        self.kafka.produce(topic, 0, messages)
        polling_timeout(test, 1)
        self.assertTrue([p.offset for p in consumer.partitions][0] > old_offset)

    def test_empty_topic(self):
        """Test that consuming an empty topic returns an empty list.

        """
        topic = 'topic'
        t = Topic(self.kafka_cluster, topic)

        consumer = t.subscribe('group2')
        self.assertTrue(consumer.empty())
<|endoftext|>