text:
from datetime import datetime, timedelta

from django.core import mail
from django.core.files.storage import default_storage as storage

import pytest
from mock import Mock, patch
from nose.tools import eq_
from pyquery import PyQuery as pq

import amo
import amo.tests
from addons.models import Addon
from amo.urlresolvers import reverse
from devhub.models import ActivityLog
from editors import helpers
from editors.models import ReviewerScore
from files.models import File
from translations.models import Translation
from users.models import UserProfile
from versions.models import Version

from . test_models import create_addon_file

pytestmark = pytest.mark.django_db

REVIEW_ADDON_STATUSES = (amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED,
                         amo.STATUS_UNREVIEWED)
REVIEW_FILES_STATUSES = (amo.STATUS_PUBLIC,
                         amo.STATUS_DISABLED, amo.STATUS_LITE)

class TestViewPendingQueueTable(amo.tests.TestCase):

    def setUp(self):
        super(TestViewPendingQueueTable, self).setUp()
        qs = Mock()
        self.table = helpers.ViewPendingQueueTable(qs)

    def test_addon_name(self):
        row = Mock()
        page = Mock()
        page.start_index = Mock()
        page.start_index.return_value = 1
        row.addon_name = 'フォクすけといっしょ'.decode('utf8')
        row.addon_slug = 'test'
        row.latest_version = u'0.12'
        self.table.set_page(page)
        a = pq(self.table.render_addon_name(row))

        eq_(a.attr('href'),
            reverse('editors.review', args=[str(row.addon_slug)]))
        eq_(a.text(), "フォクすけといっしょ 0.12".decode('utf8'))

    def test_addon_type_id(self):
        row = Mock()
        row.addon_type_id = amo.ADDON_THEME
        eq_(unicode(self.table.render_addon_type_id(row)), u'Complete Theme')

    def test_applications(self):
        row = Mock()
        row.application_ids = [amo.FIREFOX.id, amo.THUNDERBIRD.id]
        doc = pq(self.table.render_applications(row))
        eq_(sorted(a.attrib['class'] for a in doc('div div')),
            ['app-icon ed-sprite-firefox', 'app-icon ed-sprite-thunderbird'])

    def test_waiting_time_in_days(self):
        row = Mock()
        row.waiting_time_days = 10
        row.waiting_time_hours = 10 * 24
        eq_(self.table.render_waiting_time_min(row), u'10 days')

    def test_waiting_time_one_day(self):
        row = Mock()
        row.waiting_time_days = 1
        row.waiting_time_hours = 24
        row.waiting_time_min = 60 * 24
        eq_(self.table.render_waiting_time_min(row), u'1 day')

    def test_waiting_time_in_hours(self):
        row = Mock()
        row.waiting_time_days = 0
        row.waiting_time_hours = 22
        row.waiting_time_min = 60 * 22
        eq_(self.table.render_waiting_time_min(row), u'22 hours')

    def test_waiting_time_in_min(self):
        row = Mock()
        row.waiting_time_days = 0
        row.waiting_time_hours = 0
        row.waiting_time_min = 11
        eq_(self.table.render_waiting_time_min(row), u'11 minutes')

    def test_waiting_time_in_secs(self):
        row = Mock()
        row.waiting_time_days = 0
        row.waiting_time_hours = 0
        row.waiting_time_min = 0
        eq_(self.table.render_waiting_time_min(row), u'moments ago')

    def test_flags(self):
        row = Mock()
        row.flags = [('admin-review', 'Admin Review')]
        doc = pq(self.table.render_flags(row))
        assert doc('div.ed-sprite-admin-review').length

class TestAdditionalInfoInQueue(amo.tests.TestCase):

    def setUp(self):
        super(TestAdditionalInfoInQueue, self).setUp()
        qs = Mock()
        self.table = helpers.ViewPendingQueueTable(qs)
        self.row = Mock()
        self.row.is_site_specific = False
        self.row.file_platform_ids = [amo.PLATFORM_ALL.id]
        self.row.external_software = False
        self.row.binary = False
        self.row.binary_components = False

    def test_no_info(self):
        eq_(self.table.render_additional_info(self.row), '')

    def test_site_specific(self):
        self.row.is_site_specific = True
        eq_(self.table.render_additional_info(self.row), u'Site Specific')

    def test_platform(self):
        self.row.file_platform_ids = [amo.PLATFORM_LINUX.id]
        assert "plat-sprite-linux" in self.table.render_platforms(self.row)

    def test_combo(self):
        self.row.is_site_specific = True
        self.row.external_software = True
        eq_(self.table.render_additional_info(self.row),
            u'Site Specific, Requires External Software')

    def test_all_platforms(self):
        self.row.file_platform_ids = [amo.PLATFORM_ALL.id]
        assert "plat-sprite-all" in self.table.render_platforms(self.row)

    def test_mixed_platforms(self):
        self.row.file_platform_ids = [amo.PLATFORM_ALL.id,
                                      amo.PLATFORM_LINUX.id]
        assert "plat-sprite-linux" in self.table.render_platforms(self.row)
        assert "plat-sprite-all" in self.table.render_platforms(self.row)

    def test_external_software(self):
        self.row.external_software = True
        eq_(self.table.render_additional_info(self.row),
            u'Requires External Software')

    def test_binary(self):
        self.row.binary = True
        eq_(self.table.render_additional_info(self.row), u'Binary Components')

yesterday = datetime.today() - timedelta(days=1)

class TestReviewHelper(amo.tests.TestCase):
    fixtures = ['base/addon_3615', 'base/users']
    preamble = 'Mozilla Add-ons: Delicious Bookmarks 2.1.072'

    def setUp(self):
        super(TestReviewHelper, self).setUp()

        class FakeRequest:
            amo_user = UserProfile.objects.get(pk=10482)
            user = amo_user

        self.request = FakeRequest()
        self.addon = Addon.objects.get(pk=3615)
        self.version = self.addon.versions.all()[0]
        self.helper = self.get_helper()
        self.file = self.version.files.all()[0]

        self.create_paths()

    def _check_score(self, reviewed_type):
        scores = ReviewerScore.objects.all()
        assert len(scores) > 0
        eq_(scores[0].score, amo.REVIEWED_SCORES[reviewed_type])
        eq_(scores[0].note_key, reviewed_type)

    def create_paths(self):
        if not storage.exists(self.file.file_path):
            with storage.open(self.file.file_path, 'w') as f:
                f.write('test data\n')

    def get_data(self):
        return {'comments': 'foo', 'addon_files': self.version.files.all(),
                'action': 'prelim', 'operating_systems': 'osx',
                'applications': 'Firefox'}

    def get_helper(self):
        return helpers.ReviewHelper(request=self.request, addon=self.addon,
                                    version=self.version)

    def setup_type(self, status):
        self.addon.update(status=status)
        return self.get_helper().review_type

    def check_log_count(self, id):
        return (ActivityLog.objects.for_addons(self.helper.addon)
                                   .filter(action=id).count())

    def test_type_nominated(self):
        eq_(self.setup_type(amo.STATUS_NOMINATED), 'nominated')
        eq_(self.setup_type(amo.STATUS_LITE_AND_NOMINATED), 'nominated')

    def test_type_preliminary(self):
        eq_(self.setup_type(amo.STATUS_UNREVIEWED), 'preliminary')
        eq_(self.setup_type(amo.STATUS_LITE), 'preliminary')

    def test_type_pending(self):
        eq_(self.setup_type(amo.STATUS_PENDING), 'pending')
        eq_(self.setup_type(amo.STATUS_NULL), 'pending')
        eq_(self.setup_type(amo.STATUS_PUBLIC), 'pending')
        eq_(self.setup_type(amo.STATUS_DISABLED), 'pending')
        eq_(self.setup_type(amo.STATUS_BETA), 'pending')
        eq_(self.setup_type(amo.STATUS_PURGATORY), 'pending')

    def test_no_version(self):
        helper = helpers.ReviewHelper(request=self.request, addon=self.addon,
                                      version=None)
        eq_(helper.review_type, 'pending')

    def test_review_files(self):
        for status in REVIEW_FILES_STATUSES:
            self.setup_data(status=status)
            eq_(self.helper.handler.__class__, helpers.ReviewFiles)

    def test_review_addon(self):
        for status in REVIEW_ADDON_STATUSES:
            self.setup_data(status=status)
            eq_(self.helper.handler.__class__, helpers.ReviewAddon)

    def test_process_action_none(self):
        self.helper.set_data({'action': 'foo'})
        self.assertRaises(self.helper.process)

    def test_process_action_good(self):
        self.helper.set_data({'action': 'info', 'comments': 'foo'})
        self.helper.process()
        eq_(len(mail.outbox), 1)

    def test_clear_has_info_request(self):
        self.version.update(has_info_request=True)
        assert self.version.has_info_request
        self.helper.set_data({'action': 'comment', 'comments': 'foo',
                              'clear_info_request': True})
        self.helper.process()
        assert not self.version.has_info_request

    def test_do_not_clear_has_info_request(self):
        self.version.update(has_info_request=True)
        assert self.version.has_info_request
        self.helper.set_data({'action': 'comment', 'comments': 'foo'})
        self.helper.process()
        assert self.version.has_info_request

    def test_action_details(self):
        for status in Addon.STATUS_CHOICES:
            self.addon.update(status=status)
            helper = self.get_helper()
            actions = helper.actions
            for k, v in actions.items():
                assert unicode(v['details']), "Missing details for: %s" % k

    def get_action(self, status, action):
        self.addon.update(status=status)
        return unicode(self.get_helper().actions[action]['details'])

    def test_action_changes(self):
        eq_(self.get_action(amo.STATUS_LITE, 'reject')[:26],
            'This will reject the files')
        eq_(self.get_action(amo.STATUS_UNREVIEWED, 'reject')[:27],
            'This will reject the add-on')
        eq_(self.get_action(amo.STATUS_UNREVIEWED, 'prelim')[:25],
            'This will mark the add-on')
        eq_(self.get_action(amo.STATUS_NOMINATED, 'prelim')[:25],
            'This will mark the add-on')
        eq_(self.get_action(amo.STATUS_LITE, 'prelim')[:24],
            'This will mark the files')
        eq_(self.get_action(amo.STATUS_LITE_AND_NOMINATED, 'prelim')[:27],
            'This will retain the add-on')
        eq_(self.get_action(amo.STATUS_NULL, 'reject')[:26],
            'This will reject a version')
        eq_(self.get_action(amo.STATUS_NOMINATED, 'public')[-31:],
            'they are reviewed by an editor.')
        eq_(self.get_action(amo.STATUS_PUBLIC, 'public')[-29:],
            'to appear on the public side.')

    def test_set_files(self):
        self.file.update(datestatuschanged=yesterday)
        self.helper.set_data({'addon_files': self.version.files.all()})
        self.helper.handler.set_files(amo.STATUS_PUBLIC,
                                      self.helper.handler.data['addon_files'])

        self.file = self.version.files.all()[0]
        eq_(self.file.status, amo.STATUS_PUBLIC)
        assert self.file.datestatuschanged.date() > yesterday.date()

    def test_set_files_copy(self):
        self.helper.set_data({'addon_files': self.version.files.all()})
        self.helper.handler.set_files(amo.STATUS_PUBLIC,
                                      self.helper.handler.data['addon_files'],
                                      copy_to_mirror=True)

        assert storage.exists(self.file.mirror_file_path)

    def test_set_files_remove(self):
        with storage.open(self.file.mirror_file_path, 'wb') as f:
            f.write('test data\n')
        self.helper.set_data({'addon_files': self.version.files.all()})
        self.helper.handler.set_files(amo.STATUS_PUBLIC,
                                      self.helper.handler.data['addon_files'],
                                      hide_disabled_file=True)

        assert not storage.exists(self.file.mirror_file_path)

    def test_logs(self):
        self.helper.set_data({'comments': 'something'})
        self.helper.handler.log_action(amo.LOG.APPROVE_VERSION)
        eq_(self.check_log_count(amo.LOG.APPROVE_VERSION.id), 1)

    def test_notify_email(self):
        self.helper.set_data(self.get_data())
        for template in ['nominated_to_nominated', 'nominated_to_preliminary',
                         'nominated_to_public', 'nominated_to_sandbox',
                         'pending_to_preliminary', 'pending_to_public',
                         'pending_to_sandbox', 'preliminary_to_preliminary',
                         'author_super_review', 'unlisted_to_reviewed',
                         'unlisted_to_reviewed_auto',
                         'unlisted_to_sandbox']:
            mail.outbox = []
            self.helper.handler.notify_email(template, 'Sample subject %s, %s')
            eq_(len(mail.outbox), 1)
            assert mail.outbox[0].body, 'Expected a message'

    def setup_data(self, status, delete=[], is_listed=True):
        mail.outbox = []
        ActivityLog.objects.for_addons(self.helper.addon).delete()
        self.addon.update(status=status, is_listed=is_listed)
        self.file.update(status=status)
        self.helper = self.get_helper()
        data = self.get_data().copy()
        for key in delete:
            del data[key]
        self.helper.set_data(data)

    def test_request_more_information(self):
        self.setup_data(amo.STATUS_PUBLIC, ['addon_files'])
        self.helper.handler.request_information()

        eq_(self.version.has_info_request, True)

        eq_(len(mail.outbox), 1)
        eq_(mail.outbox[0].subject, self.preamble)

        eq_(self.check_log_count(amo.LOG.REQUEST_INFORMATION.id), 1)

    def test_email_no_locale(self):
        self.setup_data(amo.STATUS_NOMINATED, ['addon_files'])
        self.helper.handler.process_public()

        eq_(len(mail.outbox), 1)
        assert '/en-US/firefox/addon/a3615' not in mail.outbox[0].body
        assert '/addon/a3615' in mail.outbox[0].body

    def test_nomination_to_public_no_files(self):
        for status in helpers.NOMINATED_STATUSES:
            self.setup_data(status, ['addon_files'])
            self.helper.handler.process_public()

            eq_(self.addon.versions.all()[0].files.all()[0].status,
                amo.STATUS_PUBLIC)

    def test_nomination_to_public_and_current_version(self):
        for status in helpers.NOMINATED_STATUSES:
            self.setup_data(status, ['addon_files'])
            self.addon = Addon.objects.get(pk=3615)
            self.addon.update(_current_version=None)
            assert not self.addon.current_version

            self.helper.handler.process_public()
            self.addon = Addon.objects.get(pk=3615)
            assert self.addon.current_version

    def test_nomination_to_public_new_addon(self):
        """ Make sure new add-ons can be made public (bug 637959) """
        status = amo.STATUS_NOMINATED
        self.setup_data(status)

        # Make sure we have no public files
        for i in self.addon.versions.all():
            i.files.update(status=amo.STATUS_UNREVIEWED)

        self.helper.handler.process_public()

        # Re-fetch the add-on
        addon = Addon.objects.get(pk=3615)

        eq_(addon.status, amo.STATUS_PUBLIC)
        eq_(addon.highest_status, amo.STATUS_PUBLIC)

        eq_(addon.versions.all()[0].files.all()[0].status,
            amo.STATUS_PUBLIC)

        eq_(len(mail.outbox), 1)
        eq_(mail.outbox[0].subject, '%s Fully Reviewed' % self.preamble)

        assert storage.exists(self.file.mirror_file_path)

        eq_(self.check_log_count(amo.LOG.APPROVE_VERSION.id), 1)

        self._check_score(amo.REVIEWED_ADDON_FULL)

    @patch('editors.helpers.sign_file')
    def test_nomination_to_public(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status)
            with self.settings(SIGNING_SERVER='full'):
                self.helper.handler.process_public()

            assert self.addon.status == amo.STATUS_PUBLIC
            assert self.addon.highest_status == amo.STATUS_PUBLIC
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_PUBLIC)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s Fully Reviewed' % self.preamble)
            assert 'has been fully reviewed' in mail.outbox[0].body

            sign_mock.assert_called_with(self.file, 'full')
            assert storage.exists(self.file.mirror_file_path)

            assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1

            self._check_score(amo.REVIEWED_ADDON_FULL)

    @patch('editors.helpers.sign_file')
    def test_nomination_to_public_unlisted(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status, is_listed=False)
            with self.settings(SIGNING_SERVER='full'):
                self.helper.handler.process_public()

            assert self.addon.status == amo.STATUS_PUBLIC
            assert self.addon.highest_status == amo.STATUS_PUBLIC
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_PUBLIC)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s signed and ready to download' % self.preamble)
            assert 'has been reviewed and is now signed' in mail.outbox[0].body

            sign_mock.assert_called_with(self.file, 'full')
            assert storage.exists(self.file.mirror_file_path)

            assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1

            self._check_score(amo.REVIEWED_ADDON_FULL)

    @patch('editors.helpers.sign_file')
    def test_nomination_to_public_failed_signing(self, sign_mock):
        sign_mock.side_effect = Exception
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status)
            with self.settings(SIGNING_SERVER='full'):
                with self.assertRaises(Exception):
                    self.helper.handler.process_public()

            # Status unchanged.
            assert self.addon.status == status
            assert self.addon.versions.all()[0].files.all()[0].status == status

            assert len(mail.outbox) == 0
            assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 0

    @patch('editors.helpers.sign_file')
    def test_nomination_to_preliminary(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status)
            with self.settings(PRELIMINARY_SIGNING_SERVER='prelim'):
                self.helper.handler.process_preliminary()

            assert self.addon.status == amo.STATUS_LITE
            if status == amo.STATUS_LITE_AND_NOMINATED:
                assert self.addon.highest_status == amo.STATUS_LITE
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_LITE)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s Preliminary Reviewed' % self.preamble)
            assert 'has been granted preliminary review' in mail.outbox[0].body

            sign_mock.assert_called_with(self.file, 'prelim')
            assert storage.exists(self.file.mirror_file_path)

            assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1

            self._check_score(amo.REVIEWED_ADDON_FULL)

    @patch('editors.helpers.sign_file')
    def test_nomination_to_preliminary_unlisted(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status, is_listed=False)
            with self.settings(PRELIMINARY_SIGNING_SERVER='prelim'):
                self.helper.handler.process_preliminary()

            assert self.addon.status == amo.STATUS_LITE
            if status == amo.STATUS_LITE_AND_NOMINATED:
                assert self.addon.highest_status == amo.STATUS_LITE
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_LITE)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s signed and ready to download' % self.preamble)
            assert 'has been reviewed and is now signed' in mail.outbox[0].body

            sign_mock.assert_called_with(self.file, 'prelim')
            assert storage.exists(self.file.mirror_file_path)

            assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1

            self._check_score(amo.REVIEWED_ADDON_FULL)

    @patch('editors.helpers.sign_file')
    def test_nomination_to_preliminary_unlisted_auto(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status, is_listed=False)
            with self.settings(PRELIMINARY_SIGNING_SERVER='prelim'):
                self.helper.handler.process_preliminary(auto_validation=True)

            assert self.addon.status == amo.STATUS_LITE
            if status == amo.STATUS_LITE_AND_NOMINATED:
                assert self.addon.highest_status == amo.STATUS_LITE
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_LITE)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s signed and ready to download' % self.preamble)
            assert 'has passed our automatic tests' in mail.outbox[0].body

            sign_mock.assert_called_with(self.file, 'prelim')
            assert storage.exists(self.file.mirror_file_path)

            assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1

            assert not ReviewerScore.objects.all()

    @patch('editors.helpers.sign_file')
    def test_nomination_to_preliminary_failed_signing(self, sign_mock):
        sign_mock.side_effect = Exception
        for status in helpers.NOMINATED_STATUSES:
            sign_mock.reset()
            self.setup_data(status)
            with self.assertRaises(Exception):
                self.helper.handler.process_preliminary()

            # Status unchanged.
            assert self.addon.status == status
            assert self.addon.versions.all()[0].files.all()[0].status == status

            assert len(mail.outbox) == 0
            assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 0

    @patch('editors.helpers.sign_file')
    def test_nomination_to_sandbox(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            self.setup_data(status)
            self.helper.handler.process_sandbox()

            assert self.addon.highest_status == amo.STATUS_PUBLIC
            assert self.addon.status == amo.STATUS_NULL
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_DISABLED)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == '%s Rejected' % self.preamble
            assert 'did not meet the criteria' in mail.outbox[0].body

            assert not sign_mock.called
            assert not storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1

    @patch('editors.helpers.sign_file')
    def test_nomination_to_sandbox_unlisted(self, sign_mock):
        for status in helpers.NOMINATED_STATUSES:
            self.setup_data(status, is_listed=False)
            self.helper.handler.process_sandbox()

            assert self.addon.highest_status == amo.STATUS_PUBLIC
            assert self.addon.status == amo.STATUS_NULL
            assert self.addon.versions.all()[0].files.all()[0].status == (
                amo.STATUS_DISABLED)

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s didn\'t pass review' % self.preamble)
            assert 'didn\'t pass review' in mail.outbox[0].body

            assert not sign_mock.called
            assert not storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1

    def test_email_unicode_monster(self):
        self.addon.name = u'TaobaoShopping淘宝网导航按钮'
        self.addon.save()
        self.setup_data(helpers.NOMINATED_STATUSES[0])
        self.helper.handler.process_sandbox()
        assert u'TaobaoShopping淘宝网导航按钮' in mail.outbox[0].subject

    def test_super_review_email(self):
        self.setup_data(amo.STATUS_NULL)
        self.helper.handler.process_super_review()
        url = reverse('editors.review', args=[self.addon.pk], add_prefix=False)
        assert url in mail.outbox[1].body

    def test_nomination_to_super_review(self):
        for status in helpers.NOMINATED_STATUSES:
            self.setup_data(status)
            self.helper.handler.process_super_review()

            eq_(self.addon.admin_review, True)

            eq_(len(mail.outbox), 2)
            eq_(mail.outbox[1].subject,
                'Super review requested: Delicious Bookmarks')
            eq_(mail.outbox[0].subject,
                ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
                 'Admin Review'))
            eq_(self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id), 1)

    def test_unreviewed_to_public(self):
        self.setup_data(amo.STATUS_UNREVIEWED)
        self.assertRaises(AssertionError,
                          self.helper.handler.process_public)

    def test_lite_to_public(self):
        self.setup_data(amo.STATUS_LITE)
        self.assertRaises(AssertionError,
                          self.helper.handler.process_public)

    @patch('editors.helpers.sign_file')
    def test_preliminary_to_preliminary(self, sign_mock):
        for status in helpers.PRELIMINARY_STATUSES:
            self.setup_data(status)
            self.helper.handler.process_preliminary()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_LITE

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s Preliminary Reviewed' % self.preamble)
            assert 'has been preliminarily reviewed' in mail.outbox[0].body

            assert sign_mock.called
            assert storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1

            self._check_score(amo.REVIEWED_ADDON_PRELIM)

    @patch('editors.helpers.sign_file')
    def test_preliminary_to_preliminary_unlisted(self, sign_mock):
        for status in helpers.PRELIMINARY_STATUSES:
            self.setup_data(status, is_listed=False)
            self.helper.handler.process_preliminary()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_LITE

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s signed and ready to download' % self.preamble)
            assert 'has been reviewed and is now signed' in mail.outbox[0].body

            assert sign_mock.called
            assert storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1

            self._check_score(amo.REVIEWED_ADDON_PRELIM)

    @patch('editors.helpers.sign_file')
    def test_preliminary_to_preliminary_unlisted_auto(self, sign_mock):
        for status in helpers.PRELIMINARY_STATUSES:
            self.setup_data(status, is_listed=False)
            self.helper.handler.process_preliminary(auto_validation=True)

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_LITE

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s signed and ready to download' % self.preamble)
            assert 'has passed our automatic tests' in mail.outbox[0].body

            assert sign_mock.called
            assert storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.PRELIMINARY_VERSION.id) == 1

            assert not ReviewerScore.objects.all()

    @patch('editors.helpers.sign_file')
    def test_preliminary_to_sandbox(self, sign_mock):
        for status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE_AND_NOMINATED]:
            self.setup_data(status)
            self.helper.handler.process_sandbox()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_DISABLED

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == '%s Rejected' % self.preamble
            assert 'did not meet the criteria' in mail.outbox[0].body

            assert not sign_mock.called
            assert not storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1

    @patch('editors.helpers.sign_file')
    def test_preliminary_to_sandbox_unlisted(self, sign_mock):
        for status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE_AND_NOMINATED]:
            self.setup_data(status, is_listed=False)
            self.helper.handler.process_sandbox()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_DISABLED

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s didn\'t pass review' % self.preamble)
            assert 'didn\'t pass review' in mail.outbox[0].body

            assert not sign_mock.called
            assert not storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1

    def test_preliminary_upgrade_to_sandbox(self):
        self.setup_data(amo.STATUS_LITE)
        eq_(self.addon.status, amo.STATUS_LITE)
        eq_(self.file.status, amo.STATUS_LITE)

        a = create_addon_file(self.addon.name, '2.2', amo.STATUS_LITE,
                              amo.STATUS_UNREVIEWED)
        self.version = a['version']

        self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED)
        self.helper = self.get_helper()
        self.helper.set_data(self.get_data())

        self.helper.handler.process_sandbox()
        eq_(self.addon.status, amo.STATUS_LITE)
        eq_(self.file.status, amo.STATUS_LITE)
        f = File.objects.get(pk=a['file'].id)
        eq_(f.status, amo.STATUS_DISABLED)

    def test_preliminary_to_super_review(self):
        for status in helpers.PRELIMINARY_STATUSES:
            self.setup_data(status)
            self.helper.handler.process_super_review()

            eq_(self.addon.admin_review, True)

            eq_(len(mail.outbox), 2)
            eq_(mail.outbox[1].subject,
                'Super review requested: Delicious Bookmarks')
            eq_(mail.outbox[0].subject,
                ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
                 'Admin Review'))
            eq_(self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id), 1)

    def test_nomination_to_super_review_and_escalate(self):
        # Note we are changing the file status here.
        for file_status in (amo.STATUS_PENDING, amo.STATUS_UNREVIEWED):
            self.setup_data(amo.STATUS_LITE)
            self.file.update(status=file_status)
            self.helper.handler.process_super_review()

            eq_(self.addon.admin_review, True)

            eq_(len(mail.outbox), 2)
            eq_(mail.outbox[1].subject,
                'Super review requested: Delicious Bookmarks')
            eq_(mail.outbox[0].subject,
                ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
                 'Admin Review'))

            eq_(self.check_log_count(amo.LOG.REQUEST_SUPER_REVIEW.id), 1)

    @patch('editors.helpers.sign_file')
    def test_pending_to_public(self, sign_mock):
        for status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED]:
            self.setup_data(status)
            self.create_paths()
            self.helper.handler.process_public()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_PUBLIC

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s Fully Reviewed' % self.preamble)
            assert 'has been fully reviewed' in mail.outbox[0].body

            assert sign_mock.called
            assert storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1

            if status == amo.STATUS_PUBLIC:
                self._check_score(amo.REVIEWED_ADDON_UPDATE)

    @patch('editors.helpers.sign_file')
    def test_pending_to_public_unlisted(self, sign_mock):
        for status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED]:
            self.setup_data(status, is_listed=False)
            self.create_paths()
            self.helper.handler.process_public()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_PUBLIC

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s signed and ready to download' % self.preamble)
            assert 'has been reviewed and is now signed' in mail.outbox[0].body

            assert sign_mock.called
            assert storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1

            if status == amo.STATUS_PUBLIC:
                self._check_score(amo.REVIEWED_ADDON_UPDATE)

    @patch('editors.helpers.sign_file')
    def test_pending_to_sandbox(self, sign_mock):
        for status in amo.UNDER_REVIEW_STATUSES:
            self.setup_data(status)
            self.helper.handler.process_sandbox()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_DISABLED

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == '%s Rejected' % self.preamble
            assert 'did not meet the criteria' in mail.outbox[0].body

            assert not sign_mock.called
            assert not storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1

    @patch('editors.helpers.sign_file')
    def test_pending_to_sandbox_unlisted(self, sign_mock):
        for status in amo.UNDER_REVIEW_STATUSES:
            self.setup_data(status, is_listed=False)
            self.helper.handler.process_sandbox()

            for file in self.helper.handler.data['addon_files']:
                assert file.status == amo.STATUS_DISABLED

            assert len(mail.outbox) == 1
            assert mail.outbox[0].subject == (
                '%s didn\'t pass review' % self.preamble)
            assert 'didn\'t pass review' in mail.outbox[0].body

            assert not sign_mock.called
            assert not storage.exists(self.file.mirror_file_path)
            assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 1

    def test_operating_system_present(self):
        self.setup_data(amo.STATUS_BETA)
        self.helper.handler.process_sandbox()

        assert 'Tested on osx with Firefox' in mail.outbox[0].body

    def test_operating_system_not_present(self):
        self.setup_data(amo.STATUS_BETA)
        data = self.get_data().copy()
        data['operating_systems'] = ''
        self.helper.set_data(data)
        self.helper.handler.process_sandbox()

        assert 'Tested with Firefox' in mail.outbox[0].body

    def test_application_not_present(self):
        self.setup_data(amo.STATUS_BETA)
        data = self.get_data().copy()
        data['applications'] = ''
        self.helper.set_data(data)
        self.helper.handler.process_sandbox()

        assert 'Tested on osx' in mail.outbox[0].body

    def test_both_not_present(self):
        self.setup_data(amo.STATUS_BETA)
        data = self.get_data().copy()
        data['applications'] = ''
        data['operating_systems'] = ''
        self.helper.set_data(data)
        self.helper.handler.process_sandbox()

        assert 'Tested' not in mail.outbox[0].body

    def test_pending_to_super_review(self):
        for status in helpers.PENDING_STATUSES:
            self.setup_data(status)
            self.helper.handler.process_super_review()

            eq_(self.addon.admin_review, True)

            eq_(len(mail.outbox), 2)
            eq_(mail.outbox[1].subject,
                'Super review requested: Delicious Bookmarks')
            eq_(mail.outbox[0].subject,
                ('Mozilla Add-ons: Delicious Bookmarks 2.1.072 flagged for '
                 'Admin Review'))

    def test_nominated_review_time_set(self):
        for status in REVIEW_ADDON_STATUSES:
            for process in ['process_sandbox', 'process_preliminary',
                            'process_public']:
                if (status == amo.STATUS_UNREVIEWED and
                        process == 'process_public'):
                    continue
                self.version.update(reviewed=None)
                self.setup_data(status)
                getattr(self.helper.handler, process)()
                assert self.version.reviewed, ('Reviewed for status %r, %s()'
                                               % (status, process))

    def test_preliminary_review_time_set(self):
        for status in amo.UNDER_REVIEW_STATUSES:
            for process in ['process_sandbox', 'process_preliminary']:
                self.file.update(reviewed=None)
                self.setup_data(status)
                getattr(self.helper.handler, process)()
                assert File.objects.get(pk=self.file.pk).reviewed, (
                    'Reviewed for status %r, %s()' % (status, process))

def test_page_title_unicode():
    t = Translation(localized_string=u'\u30de\u30eb\u30c1\u30d712\u30eb')
    request = Mock()
    request.APP = amo.FIREFOX
    helpers.editor_page_title({'request': request}, title=t)

def test_send_email_autoescape():
    # Make sure HTML is not auto-escaped.
    s = 'woo&&<>\'""'
    ctx = dict(name=s, review_url=s, reviewer=s, comments=s, SITE_URL=s)
    helpers.send_mail('editors/emails/super_review.ltxt',
                      'aww yeah', ['xx'], ctx)
    eq_(len(mail.outbox), 1)
    eq_(mail.outbox[0].body.count(s), len(ctx))

class TestCompareLink(amo.tests.TestCase):
    fixtures = ['base/addon_3615']

    def setUp(self):
        super(TestCompareLink, self).setUp()
        self.addon = Addon.objects.get(pk=3615)
        self.current = File.objects.get(pk=67442)
        self.version = Version.objects.create(addon=self.addon)

    def test_same_platform(self):
        file = File.objects.create(version=self.version,
                                   platform=self.current.platform)
        eq_(file.pk, helpers.file_compare(self.current, self.version).pk)

    def test_different_platform(self):
        file = File.objects.create(version=self.version,
                                   platform=self.current.platform)
        File.objects.create(version=self.version,
                            platform=amo.PLATFORM_LINUX.id)
        eq_(file.pk, helpers.file_compare(self.current, self.version).pk)

    def test_specific_platform(self):
        self.current.platform_id = amo.PLATFORM_LINUX.id
        self.current.save()

        linux = File.objects.create(version=self.version,
                                    platform=amo.PLATFORM_LINUX.id)
        eq_(linux.pk, helpers.file_compare(self.current, self.version).pk)

    def test_no_platform(self):
        self.current.platform_id = amo.PLATFORM_LINUX.id
        self.current.save()
        file = File.objects.create(version=self.version,
                                   platform=amo.PLATFORM_WIN.id)
        eq_(file.pk, helpers.file_compare(self.current, self.version).pk)

def test_version_status():
    addon = Addon()
    version = Version()
    version.all_files = [File(status=amo.STATUS_PUBLIC),
                         File(status=amo.STATUS_UNREVIEWED)]
    eq_(u'Fully Reviewed,Awaiting Review',
        helpers.version_status(addon, version))

    version.all_files = [File(status=amo.STATUS_UNREVIEWED)]
    eq_(u'Awaiting Review', helpers.version_status(addon, version))


text:
#pragma once

#include <quic/QuicConstants.h>
#include <quic/QuicException.h>
#include <quic/api/QuicSocket.h>
#include <quic/common/FunctionLooper.h>
#include <quic/common/Timers.h>
#include <quic/congestion_control/CongestionControllerFactory.h>
#include <quic/congestion_control/Copa.h>
#include <quic/congestion_control/NewReno.h>
#include <quic/congestion_control/QuicCubic.h>
#include <quic/state/StateData.h>

#include <folly/ExceptionWrapper.h>
#include <folly/io/async/AsyncUDPSocket.h>
#include <folly/io/async/HHWheelTimer.h>

namespace quic {

enum class CloseState { OPEN, GRACEFUL_CLOSING, CLOSED };

/**
 * Base class for the QUIC Transport. Implements common behavior for both
 * clients and servers. QuicTransportBase assumes the following:
 * 1. It is intended to be sub-classed and used via the subclass directly.
 * 2. Assumes that the sub-class manages its ownership via a shared_ptr.
 *    This is needed in order for QUIC to be able to live beyond the lifetime
 *    of the object that holds it to send graceful close messages to the peer.
 */
class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver {
 public:
  QuicTransportBase(
      folly::EventBase* evb,
      std::unique_ptr<folly::AsyncUDPSocket> socket,
      bool useConnectionEndWithErrorCallback = false);

  ~QuicTransportBase() override;

  void setPacingTimer(TimerHighRes::SharedPtr pacingTimer) noexcept;

  folly::EventBase* getEventBase() const override;

  folly::Optional<ConnectionId> getClientConnectionId() const override;

  folly::Optional<ConnectionId> getServerConnectionId() const override;

  folly::Optional<ConnectionId> getClientChosenDestConnectionId()
      const override;

  const folly::SocketAddress& getPeerAddress() const override;

  const folly::SocketAddress& getOriginalPeerAddress() const override;

  const folly::SocketAddress& getLocalAddress() const override;

  const std::shared_ptr<QLogger> getQLogger() const;

  // QuicSocket interface
  bool good() const override;

  bool replaySafe() const override;

  bool error() const override;

  void close(folly::Optional<QuicError> error) override;

  void closeGracefully() override;

  void closeNow(folly::Optional<QuicError> error) override;

  folly::Expected<size_t, LocalErrorCode> getStreamReadOffset(
      StreamId id) const override;
  folly::Expected<size_t, LocalErrorCode> getStreamWriteOffset(
      StreamId id) const override;
  folly::Expected<size_t, LocalErrorCode> getStreamWriteBufferedBytes(
      StreamId id) const override;

  TransportInfo getTransportInfo() const override;

  folly::Expected<StreamTransportInfo, LocalErrorCode> getStreamTransportInfo(
      StreamId id) const override;

  folly::Optional<std::string> getAppProtocol() const override;

  void setReceiveWindow(StreamId id, size_t recvWindowSize) override;

  void setSendBuffer(StreamId id, size_t maxUnacked, size_t maxUnsent) override;

  uint64_t getConnectionBufferAvailable() const override;

  uint64_t bufferSpaceAvailable() const;

  folly::Expected<QuicSocket::FlowControlState, LocalErrorCode>
  getConnectionFlowControl() const override;

  folly::Expected<QuicSocket::FlowControlState, LocalErrorCode>
  getStreamFlowControl(StreamId id) const override;

  folly::Expected<uint64_t, LocalErrorCode> getMaxWritableOnStream(
      StreamId id) const override;

  folly::Expected<folly::Unit, LocalErrorCode> setConnectionFlowControlWindow(
      uint64_t windowSize) override;

  folly::Expected<folly::Unit, LocalErrorCode> setStreamFlowControlWindow(
      StreamId id,
      uint64_t windowSize) override;

  folly::Expected<folly::Unit, LocalErrorCode> setReadCallback(
      StreamId id,
      ReadCallback* cb,
      folly::Optional<ApplicationErrorCode> err =
          GenericApplicationErrorCode::NO_ERROR) override;
  void unsetAllReadCallbacks() override;
  void unsetAllPeekCallbacks() override;
  void unsetAllDeliveryCallbacks() override;
  folly::Expected<folly::Unit, LocalErrorCode> pauseRead(StreamId id) override;
  folly::Expected<folly::Unit, LocalErrorCode> resumeRead(StreamId id) override;
  folly::Expected<folly::Unit, LocalErrorCode> stopSending(
      StreamId id,
      ApplicationErrorCode error) override;

  folly::Expected<std::pair<Buf, bool>, LocalErrorCode> read(
      StreamId id,
      size_t maxLen) override;

  folly::Expected<folly::Unit, LocalErrorCode> setPeekCallback(
      StreamId id,
      PeekCallback* cb) override;

  folly::Expected<folly::Unit, LocalErrorCode> pausePeek(StreamId id) override;
  folly::Expected<folly::Unit, LocalErrorCode> resumePeek(StreamId id) override;

  folly::Expected<folly::Unit, LocalErrorCode> peek(
      StreamId id,
      const folly::Function<void(StreamId id, const folly::Range<PeekIterator>&)
                                const>& peekCallback) override;

  folly::Expected<folly::Unit, LocalErrorCode> consume(
      StreamId id,
      size_t amount) override;

  folly::Expected<
      folly::Unit,
      std::pair<LocalErrorCode, folly::Optional<uint64_t>>>
  consume(StreamId id, uint64_t offset, size_t amount) override;

  folly::Expected<StreamId, LocalErrorCode> createBidirectionalStream(
      bool replaySafe = true) override;
  folly::Expected<StreamId, LocalErrorCode> createUnidirectionalStream(
      bool replaySafe = true) override;
  folly::Expected<StreamGroupId, LocalErrorCode>
  createBidirectionalStreamGroup() override;
  folly::Expected<StreamGroupId, LocalErrorCode>
  createUnidirectionalStreamGroup() override;
  folly::Expected<StreamId, LocalErrorCode> createBidirectionalStreamInGroup(
      StreamGroupId groupId) override;
  folly::Expected<StreamId, LocalErrorCode> createUnidirectionalStreamInGroup(
      StreamGroupId groupId) override;
  uint64_t getNumOpenableBidirectionalStreams() const override;
  uint64_t getNumOpenableUnidirectionalStreams() const override;
  bool isClientStream(StreamId stream) noexcept override;
  bool isServerStream(StreamId stream) noexcept override;
  StreamInitiator getStreamInitiator(StreamId stream) noexcept override;
  bool isUnidirectionalStream(StreamId stream) noexcept override;
  bool isBidirectionalStream(StreamId stream) noexcept override;
  StreamDirectionality getStreamDirectionality(
      StreamId stream) noexcept override;

  folly::Expected<folly::Unit, LocalErrorCode> notifyPendingWriteOnStream(
      StreamId id,
      WriteCallback* wcb) override;

  folly::Expected<folly::Unit, LocalErrorCode> notifyPendingWriteOnConnection(
      WriteCallback* wcb) override;

  folly::Expected<folly::Unit, LocalErrorCode> unregisterStreamWriteCallback(
      StreamId id) override;

  WriteResult writeChain(
      StreamId id,
      Buf data,
      bool eof,
      ByteEventCallback* cb = nullptr) override;

  // TODO: Maybe I should virtualize DSR related APIs and only implement in
  // QuicServerTransport
  WriteResult writeBufMeta(
      StreamId id,
      const BufferMeta& data,
      bool eof,
      ByteEventCallback* cb = nullptr) override;

  WriteResult setDSRPacketizationRequestSender(
      StreamId id,
      std::unique_ptr<DSRPacketizationRequestSender> sender) override;

  folly::Expected<folly::Unit, LocalErrorCode> registerDeliveryCallback(
      StreamId id,
      uint64_t offset,
      ByteEventCallback* cb) override;

  folly::Optional<LocalErrorCode> shutdownWrite(StreamId id) override;

  folly::Expected<folly::Unit, LocalErrorCode> resetStream(
      StreamId id,
      ApplicationErrorCode errorCode) override;

  folly::Expected<folly::Unit, LocalErrorCode> maybeResetStreamFromReadError(
      StreamId id,
      QuicErrorCode error) override;

  folly::Expected<folly::Unit, LocalErrorCode> setPingCallback(
      PingCallback* cb) override;

  void sendPing(std::chrono::milliseconds pingTimeout) override;

  const QuicConnectionStateBase* getState() const override {
    return conn_.get();
  }

  // Interface with the Transport layer when data is available.
  // This is invoked when new data is received from the UDP socket.
  virtual void onNetworkData(
      const folly::SocketAddress& peer,
      NetworkData&& data) noexcept;

  virtual void setSupportedVersions(const std::vector<QuicVersion>& versions);

  void setConnectionSetupCallback(ConnectionSetupCallback* callback) final;

  void setConnectionCallback(ConnectionCallback* callback) final;

  void setEarlyDataAppParamsFunctions(
      folly::Function<bool(const folly::Optional<std::string>&, const Buf&)
                          const> validator,
      folly::Function<Buf()> getter) final;

  bool isDetachable() override;

  void detachEventBase() override;

  void attachEventBase(folly::EventBase* evb) override;

  folly::Optional<LocalErrorCode> setControlStream(StreamId id) override;

  /**
   * Set the initial flow control window for the connection.
   */
  void setTransportSettings(TransportSettings transportSettings) override;

  /**
   * Sets the maximum pacing rate in Bytes per second to be used
   * if pacing is enabled.
   */
  folly::Expected<folly::Unit, LocalErrorCode> setMaxPacingRate(
      uint64_t maxRateBytesPerSec) override;

  /**
   * Set a "knob". This will emit a knob frame to the peer, which the peer
   * application can act on by e.g. changing transport settings during the
   * connection.
   */
  folly::Expected<folly::Unit, LocalErrorCode>
  setKnob(uint64_t knobSpace, uint64_t knobId, Buf knobBlob) override;

  /**
   * Can Knob Frames be exchanged with the peer on this connection?
   */
  FOLLY_NODISCARD bool isKnobSupported() const override;

  /**
   * Set factory to create specific congestion controller instances
   * for a given connection.
   * Deletes current congestion controller instance, to create new controller
   * call setCongestionControl() or setTransportSettings().
   */
  virtual void setCongestionControllerFactory(
      std::shared_ptr<CongestionControllerFactory> factory);

  /**
   * Retrieve the transport settings
   */
  const TransportSettings& getTransportSettings() const override;

  // Subclass API.

  /**
   * Invoked when a new packet is read from the network.
   * peer is the address of the peer that was in the packet.
   * The sub-class may throw an exception if there was an error in processing
   * the packet in which case the connection will be closed.
   */
  virtual void onReadData(
      const folly::SocketAddress& peer,
      NetworkDataSingle&& networkData) = 0;

  /**
   * Invoked when we have to write some data to the wire.
   * The subclass may use this to start writing data to the socket.
   * It may also throw an exception in case of an error in which case the
   * connection will be closed.
   */
  virtual void writeData() = 0;

  /**
   * closeTransport is invoked on the sub-class when the transport is closed.
   * The sub-class may clean up any state during this call. The transport
   * may still be draining after this call.
   */
  virtual void closeTransport() = 0;

  /**
   * Invoked after the drain timeout has exceeded and the connection state will
   * be destroyed.
   */
  virtual void unbindConnection() = 0;

  /**
   * Returns whether or not the connection has a write cipher. This will be used
   * to decide to return the onTransportReady() callbacks.
   */
  virtual bool hasWriteCipher() const = 0;

  /**
   * Returns a shared_ptr which can be used as a guard to keep this
   * object alive.
   */
  virtual std::shared_ptr<QuicTransportBase> sharedGuard() = 0;

  folly::Expected<folly::Unit, LocalErrorCode> setStreamPriority(
      StreamId id,
      PriorityLevel level,
      bool incremental) override;

  folly::Expected<Priority, LocalErrorCode> getStreamPriority(
      StreamId id) override;

  /**
   * Invoke onCanceled on all the delivery callbacks registered for streamId.
   */
  void cancelDeliveryCallbacksForStream(StreamId id) override;

  /**
   * Invoke onCanceled on all the delivery callbacks registered for streamId for
   * offsets lower than the offset provided.
   */
  void cancelDeliveryCallbacksForStream(StreamId id, uint64_t offset) override;

  /**
   * Register a callback to be invoked when the stream offset was transmitted.
   *
   * Currently, an offset is considered "transmitted" if it has been written to
   * to the underlying UDP socket, indicating that it has passed through
   * congestion control and pacing. In the future, this callback may be
   * triggered by socket/NIC software or hardware timestamps.
   */
  folly::Expected<folly::Unit, LocalErrorCode> registerTxCallback(
      const StreamId id,
      const uint64_t offset,
      ByteEventCallback* cb) override;

  /**
   * Register a byte event to be triggered when specified event type occurs for
   * the specified stream and offset.
   */
  folly::Expected<folly::Unit, LocalErrorCode> registerByteEventCallback(
      const ByteEvent::Type type,
      const StreamId id,
      const uint64_t offset,
      ByteEventCallback* cb) override;

  /**
   * Cancel byte event callbacks for given stream.
   *
   * If an offset is provided, cancels only callbacks with an offset less than
   * or equal to the provided offset, otherwise cancels all callbacks.
   */
  void cancelByteEventCallbacksForStream(
      const StreamId id,
      const folly::Optional<uint64_t>& offset = folly::none) override;

  /**
   * Cancel byte event callbacks for given type and stream.
   *
   * If an offset is provided, cancels only callbacks with an offset less than
   * or equal to the provided offset, otherwise cancels all callbacks.
   */
  void cancelByteEventCallbacksForStream(
      const ByteEvent::Type type,
      const StreamId id,
      const folly::Optional<uint64_t>& offset = folly::none) override;

  /**
   * Cancel all byte event callbacks of all streams.
   */
  void cancelAllByteEventCallbacks() override;

  /**
   * Cancel all byte event callbacks of all streams of the given type.
   */
  void cancelByteEventCallbacks(const ByteEvent::Type type) override;

  /**
   * Reset or send a stop sending on all non-control streams. Leaves the
   * connection otherwise unmodified. Note this will also trigger the
   * onStreamWriteError and readError callbacks immediately.
   */
  void resetNonControlStreams(
      ApplicationErrorCode error,
      folly::StringPiece errorMsg) override;

  /**
   * Get the number of pending byte events for the given stream.
   */
  FOLLY_NODISCARD size_t
  getNumByteEventCallbacksForStream(const StreamId id) const override;

  /**
   * Get the number of pending byte events of specified type for given stream.
   */
  FOLLY_NODISCARD size_t getNumByteEventCallbacksForStream(
      const ByteEvent::Type type,
      const StreamId id) const override;

  /*
   * Set the background mode priority threshold and the target bw utilization
   * factor to use when in background mode.
   *
   * If all streams have equal or lower priority compares to the threshold
   * (value >= threshold), the connection is considered to be in backround mode.
   */
  void setBackgroundModeParameters(
      PriorityLevel maxBackgroundPriority,
      float backgroundUtilizationFactor);

  /*
   * Disable background mode by clearing all related parameters.
   */
  void clearBackgroundModeParameters();

  // Timeout functions
  class LossTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~LossTimeout() override = default;

    explicit LossTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->lossTimeoutExpired();
    }

    virtual void callbackCanceled() noexcept override {
      // ignore. this usually means that the eventbase is dying, so we will be
      // canceled anyway
      return;
    }

   private:
    QuicTransportBase* transport_;
  };

  class AckTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~AckTimeout() override = default;

    explicit AckTimeout(QuicTransportBase* transport) : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->ackTimeoutExpired();
    }

    virtual void callbackCanceled() noexcept override {
      // ignore. this usually means that the eventbase is dying, so we will be
      // canceled anyway
      return;
    }

   private:
    QuicTransportBase* transport_;
  };

  class PingTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~PingTimeout() override = default;

    explicit PingTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->pingTimeoutExpired();
    }

    void callbackCanceled() noexcept override {
      // ignore, as this happens only when event  base dies
      return;
    }

   private:
    QuicTransportBase* transport_;
  };

  class PathValidationTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~PathValidationTimeout() override = default;

    explicit PathValidationTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->pathValidationTimeoutExpired();
    }

    virtual void callbackCanceled() noexcept override {
      // ignore. this usually means that the eventbase is dying, so we will be
      // canceled anyway
      return;
    }

   private:
    QuicTransportBase* transport_;
  };

  class IdleTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~IdleTimeout() override = default;

    explicit IdleTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->idleTimeoutExpired(true /* drain */);
    }

    void callbackCanceled() noexcept override {
      // skip drain when canceling the timeout, to avoid scheduling a new
      // drain timeout
      transport_->idleTimeoutExpired(false /* drain */);
    }

   private:
    QuicTransportBase* transport_;
  };

  class KeepaliveTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~KeepaliveTimeout() override = default;

    explicit KeepaliveTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->keepaliveTimeoutExpired();
    }
    void callbackCanceled() noexcept override {
      // Specifically do nothing since if we got canceled we shouldn't write.
    }

   private:
    QuicTransportBase* transport_;
  };

  // DrainTimeout is a bit different from other timeouts. It needs to hold a
  // shared_ptr to the transport, since if a DrainTimeout is scheduled,
  // transport cannot die.
  class DrainTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~DrainTimeout() override = default;

    explicit DrainTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->drainTimeoutExpired();
    }

   private:
    QuicTransportBase* transport_;
  };

  class D6DProbeTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~D6DProbeTimeout() override = default;

    explicit D6DProbeTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->d6dProbeTimeoutExpired();
    }

   private:
    QuicTransportBase* transport_;
  };

  class D6DRaiseTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~D6DRaiseTimeout() override = default;

    explicit D6DRaiseTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->d6dRaiseTimeoutExpired();
    }

   private:
    QuicTransportBase* transport_;
  };

  class D6DTxTimeout : public folly::HHWheelTimer::Callback {
   public:
    ~D6DTxTimeout() override = default;

    explicit D6DTxTimeout(QuicTransportBase* transport)
        : transport_(transport) {}

    void timeoutExpired() noexcept override {
      transport_->d6dTxTimeoutExpired();
    }

   private:
    QuicTransportBase* transport_;
  };

  void scheduleLossTimeout(std::chrono::milliseconds timeout);
  void cancelLossTimeout();
  bool isLossTimeoutScheduled() const;

  // If you don't set it, the default is Cubic
  void setCongestionControl(CongestionControlType type) override;

  void addPacketProcessor(
      std::shared_ptr<PacketProcessor> packetProcessor) override;

  void describe(std::ostream& os) const;

  void setLogger(std::shared_ptr<Logger> logger) {
    conn_->logger = std::move(logger);
  }

  virtual void setQLogger(std::shared_ptr<QLogger> qLogger);

  void setLoopDetectorCallback(std::shared_ptr<LoopDetectorCallback> callback) {
    conn_->loopDetectorCallback = std::move(callback);
  }

  virtual void cancelAllAppCallbacks(const QuicError& error) noexcept;

  FOLLY_NODISCARD QuicConnectionStats getConnectionsStats() const override;

  /**
   * Set the read callback for Datagrams
   */
  folly::Expected<folly::Unit, LocalErrorCode> setDatagramCallback(
      DatagramCallback* cb) override;

  /**
   * Returns the maximum allowed Datagram payload size.
   * 0 means Datagram is not supported
   */
  FOLLY_NODISCARD uint16_t getDatagramSizeLimit() const override;

  /**
   * Writes a Datagram frame. If buf is larger than the size limit returned by
   * getDatagramSizeLimit(), or if the write buffer is full, buf will simply be
   * dropped, and a LocalErrorCode will be returned to caller.
   */
  folly::Expected<folly::Unit, LocalErrorCode> writeDatagram(Buf buf) override;

  /**
   * Returns the currently available received Datagrams.
   * Returns all datagrams if atMost is 0.
   */
  folly::Expected<std::vector<ReadDatagram>, LocalErrorCode> readDatagrams(
      size_t atMost = 0) override;

  /**
   * Returns the currently available received Datagram IOBufs.
   * Returns all datagrams if atMost is 0.
   */
  folly::Expected<std::vector<Buf>, LocalErrorCode> readDatagramBufs(
      size_t atMost = 0) override;

  /**
   * Set control messages to be sent for socket_ write, note that it's for this
   * specific transport and does not change the other sockets sharing the same
   * fd.
   */
  void setCmsgs(const folly::SocketOptionMap& options);

  void appendCmsgs(const folly::SocketOptionMap& options);

 protected:
  void updateCongestionControlSettings(
      const TransportSettings& transportSettings);
  void processCallbacksAfterWriteData();
  void processCallbacksAfterNetworkData();
  void invokeReadDataAndCallbacks();
  void invokePeekDataAndCallbacks();
  void invokeStreamsAvailableCallbacks();
  void updateReadLooper();
  void updatePeekLooper();
  void updateWriteLooper(bool thisIteration);
  void handlePingCallbacks();
  void handleKnobCallbacks();
  void handleAckEventCallbacks();
  void handleCancelByteEventCallbacks();
  void handleNewStreamCallbacks(std::vector<StreamId>& newPeerStreams);
  void handleNewGroupedStreamCallbacks(std::vector<StreamId>& newPeerStreams);
  void handleDeliveryCallbacks();
  void handleStreamFlowControlUpdatedCallbacks(
      std::vector<StreamId>& streamStorage);
  void handleStreamStopSendingCallbacks();
  void handleConnWritable();

  /*
   * Observe changes in stream priorities and handle background mode.
   *
   * Implements the QuicStreamPrioritiesObserver interface
   */
  void onStreamPrioritiesChange() override;

  void cleanupAckEventState();

  void runOnEvbAsync(
      folly::Function<void(std::shared_ptr<QuicTransportBase>)> func);

  void closeImpl(
      folly::Optional<QuicError> error,
      bool drainConnection = true,
      bool sendCloseImmediately = true);
  void closeUdpSocket();
  folly::Expected<folly::Unit, LocalErrorCode> pauseOrResumeRead(
      StreamId id,
      bool resume);
  folly::Expected<folly::Unit, LocalErrorCode> pauseOrResumePeek(
      StreamId id,
      bool resume);
  void checkForClosedStream();
  folly::Expected<folly::Unit, LocalErrorCode> setReadCallbackInternal(
      StreamId id,
      ReadCallback* cb,
      folly::Optional<ApplicationErrorCode> err) noexcept;
  folly::Expected<folly::Unit, LocalErrorCode> setPeekCallbackInternal(
      StreamId id,
      PeekCallback* cb) noexcept;
  folly::Expected<StreamId, LocalErrorCode> createStreamInternal(
      bool bidirectional,
      const folly::Optional<StreamGroupId>& streamGroupId = folly::none);

  /**
   * Helper function - if given error is not set, returns a generic app error.
   * Used by close() and closeNow().
   */
  QuicError maybeSetGenericAppError(folly::Optional<QuicError> error);

  /**
   * write data to socket
   *
   * At transport layer, this is the simplest form of write. It writes data
   * out to the network, and schedule necessary timers (ack, idle, loss). It is
   * both pacing oblivious and writeLooper oblivious. Caller needs to explicitly
   * invoke updateWriteLooper afterwards if that's desired.
   */
  void writeSocketData();

  /**
   * A wrapper around writeSocketData
   *
   * writeSocketDataAndCatch protects writeSocketData in a try-catch. It also
   * dispatch the next write loop.
   */
  void writeSocketDataAndCatch();

  /**
   * Paced write data to socket when connection is paced.
   *
   * Whether connection is based will be decided by TransportSettings and
   * congection controller. When the connection is paced, this function writes
   * out a burst size of packets and let the writeLooper schedule a callback to
   * write another burst after a pacing interval if there are more data to
   * write. When the connection isn't paced, this function do a normal write.
   */
  void pacedWriteDataToSocket(bool fromTimer);

  uint64_t maxWritableOnStream(const QuicStreamState&) const;
  uint64_t maxWritableOnConn() const;

  void lossTimeoutExpired() noexcept;
  void ackTimeoutExpired() noexcept;
  void pathValidationTimeoutExpired() noexcept;
  void idleTimeoutExpired(bool drain) noexcept;
  void keepaliveTimeoutExpired() noexcept;
  void drainTimeoutExpired() noexcept;
  void pingTimeoutExpired() noexcept;
  void d6dProbeTimeoutExpired() noexcept;
  void d6dRaiseTimeoutExpired() noexcept;
  void d6dTxTimeoutExpired() noexcept;

  void setIdleTimer();
  void scheduleAckTimeout();
  void schedulePathValidationTimeout();
  void schedulePingTimeout(
      PingCallback* callback,
      std::chrono::milliseconds pingTimeout);
  void scheduleD6DRaiseTimeout();
  void scheduleD6DProbeTimeout();
  void scheduleD6DTxTimeout();

  void validateCongestionAndPacing(CongestionControlType& type);

  // Helpers to notify all registered observers about specific events during
  // socket write (if enabled in the observer's config).
  void notifyStartWritingFromAppRateLimited();
  void notifyPacketsWritten(
      const uint64_t numPacketsWritten,
      const uint64_t numAckElicitingPacketsWritten,
      const uint64_t numBytesWritten);
  void notifyAppRateLimited();

  /**
   * Callback when we receive a transport knob
   */
  virtual void onTransportKnobs(Buf knobBlob);

  struct ByteEventDetail {
    ByteEventDetail(uint64_t offsetIn, ByteEventCallback* callbackIn)
        : offset(offsetIn), callback(callbackIn) {}
    uint64_t offset;
    ByteEventCallback* callback;
  };

  using ByteEventMap = folly::F14FastMap<StreamId, std::deque<ByteEventDetail>>;
  ByteEventMap& getByteEventMap(const ByteEvent::Type type);
  FOLLY_NODISCARD const ByteEventMap& getByteEventMapConst(
      const ByteEvent::Type type) const;

  /**
   * Helper function that calls passed function for each ByteEvent type.
   *
   * Removes number of locations to update when a byte event is added.
   */
  void invokeForEachByteEventType(
      const std::function<void(const ByteEvent::Type)>& fn) {
    for (const auto& type : ByteEvent::kByteEventTypes) {
      fn(type);
    }
  }

  void invokeForEachByteEventTypeConst(
      const std::function<void(const ByteEvent::Type)>& fn) const {
    for (const auto& type : ByteEvent::kByteEventTypes) {
      fn(type);
    }
  }

  void resetConnectionCallbacks() {
    connSetupCallback_ = nullptr;
    connCallback_ = nullptr;
  }

  bool processCancelCode(const QuicError& cancelCode);
  void processConnectionSetupCallbacks(const QuicError& cancelCode);
  void processConnectionCallbacks(const QuicError& cancelCode);

  std::atomic<folly::EventBase*> evb_;
  std::unique_ptr<folly::AsyncUDPSocket> socket_;
  ConnectionSetupCallback* connSetupCallback_{nullptr};
  ConnectionCallback* connCallback_{nullptr};
  // A flag telling transport if the new onConnectionEnd(error) cb must be used.
  bool useConnectionEndWithErrorCallback_{false};

  std::
      unique_ptr<QuicConnectionStateBase, folly::DelayedDestruction::Destructor>
          conn_;

  struct ReadCallbackData {
    ReadCallback* readCb;
    bool resumed{true};
    bool deliveredEOM{false};

    ReadCallbackData(ReadCallback* readCallback) : readCb(readCallback) {}
  };

  struct PeekCallbackData {
    PeekCallback* peekCb;
    bool resumed{true};

    PeekCallbackData(PeekCallback* peekCallback) : peekCb(peekCallback) {}
  };

  folly::F14FastMap<StreamId, ReadCallbackData> readCallbacks_;
  folly::F14FastMap<StreamId, PeekCallbackData> peekCallbacks_;

  ByteEventMap deliveryCallbacks_;
  ByteEventMap txCallbacks_;

  DatagramCallback* datagramCallback_{nullptr};
  PingCallback* pingCallback_{nullptr};

  WriteCallback* connWriteCallback_{nullptr};
  std::map<StreamId, WriteCallback*> pendingWriteCallbacks_;
  CloseState closeState_{CloseState::OPEN};
  bool transportReadyNotified_{false};
  bool handshakeDoneNotified_{false};
  bool d6dProbingStarted_{false};

  LossTimeout lossTimeout_;
  AckTimeout ackTimeout_;
  PathValidationTimeout pathValidationTimeout_;
  IdleTimeout idleTimeout_;
  KeepaliveTimeout keepaliveTimeout_;
  DrainTimeout drainTimeout_;
  PingTimeout pingTimeout_;
  D6DProbeTimeout d6dProbeTimeout_;
  D6DRaiseTimeout d6dRaiseTimeout_;
  D6DTxTimeout d6dTxTimeout_;
  FunctionLooper::Ptr readLooper_;
  FunctionLooper::Ptr peekLooper_;
  FunctionLooper::Ptr writeLooper_;

  // TODO: This is silly. We need a better solution.
  // Uninitialied local address as a fallback answer when socket isn't bound.
  folly::SocketAddress localFallbackAddress;

  folly::Optional<std::string> exceptionCloseWhat_;

  uint64_t qlogRefcnt_{0};

  // Priority level threshold for background streams
  // If all streams have equal or lower priority to the threshold
  // (value >= threshold), the connection is considered to be in backround mode.
  folly::Optional<PriorityLevel> backgroundPriorityThreshold_;
  folly::Optional<float> backgroundUtilizationFactor_;

 private:
  /**
   * Helper funtions to handle new streams.
   */
  void handleNewStreams(std::vector<StreamId>& newPeerStreams);
  void handleNewGroupedStreams(std::vector<StreamId>& newPeerStreams);

  /**
   * Helper to log new stream event to observer.
   */
  void logStreamOpenEvent(StreamId streamId);
};

std::ostream& operator<<(std::ostream& os, const QuicTransportBase& qt);
} // namespace quic

redpajama_set_name: RedPajamaGithub


text:
<?php
namespace backend\utility\Excel;

use backend\models\Customer;
use Yii;
use yii\db\Exception;

class PartnerExcelFile extends ExcelFileInfo implements IExcelFile
{
    private $typePartner;
    public function __construct($params, $files)
    {
        parent::__construct($files);
        $this->getFileColumn($params);
        $this->row_begin = $params['row_header'] + 1;
        $this->sheetData($params['sheet_name']);
        $this->option = $params['option'];
        $this->restrictColumn = $params['restrict_column'];
        $this->typePartner = $params['type_partner'];
    }

    public function getFileColumn($params)
    {
        $name = strtoupper($params['name_column']);
        $website = strtoupper($params['website_column']);
        $address = strtoupper($params['address_column']);
        $fax = strtoupper($params['fax_column']);
        $code = strtoupper($params['post_code_column']);
        $phone = strtoupper($params['phone_column']);
        $this->columns = [
            'name' => $name,
            'phone' => $phone,
            'address' => $address,
            'code' => $code,
            'fax' => $fax,
            'website' => $website,
        ];
    }

    public function importData()
    {
        $sheetData = $this->data;
        $rowBegin = $this->row_begin;
        $option = $this->option;
        $columns = $this->columns;
        $restrictColumn = $this->restrictColumn;
        $count = count($sheetData);
        //1: đè lại dữ liệu cũ, 0: ghi thêm
        for (; $rowBegin <= $count; $rowBegin++) {
            $customer = Customer::find()
                ->where([
                    'is_delete' => 0,
                    $restrictColumn => $sheetData[$rowBegin][$columns[$restrictColumn]]
                ])
                ->one();
            $customer = ($customer !== null && $option == 1) ? $customer : new Customer();
            $customer->phone = $sheetData[$rowBegin][$columns['phone']];
            $customer->name = $sheetData[$rowBegin][$columns['name']];
            $customer->website = (!empty($sheetData[$rowBegin][$columns['website']])) ? $sheetData[$rowBegin][$columns['website']] : '';
            $customer->address = (!empty($sheetData[$rowBegin][$columns['address']])) ? $sheetData[$rowBegin][$columns['address']] : '';
            $customer->fax = (!empty($sheetData[$rowBegin][$columns['fax']])) ? $sheetData[$rowBegin][$columns['fax']] : '';
            $customer->code = (!empty($sheetData[$rowBegin][$columns['code']])) ? $sheetData[$rowBegin][$columns['code']] : '';
            $customer->type_customer_id = $this->typePartner;
            $customer->created_user = Yii::$app->user->id;
            try {
                $customer->save(false);
                $this->success++;
            } catch (Exception $e) {
                $this->error++;
                array_merge($this->exceptions, ['row' => $rowBegin, 'message' => $e->getName()]);
            }
        }
    }
}

?>


text:
{% load reviewtags i18n %}

<form action="{% review_form_target %}" method="post">{% csrf_token %}
  {% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
  {% for field in form %}
    {% if field.is_hidden %}

{{ field }}

    {% else %}
      {% if field.errors %}{{ field.errors }}{% endif %}

        {{ field.label_tag }} {{ field }}

    {% endif %}
  {% endfor %}

  {{ form.formset.management_form }}

  {% for subForm in form.formset %}
    Titel: {{ subForm.get_categorysegment.title }}

    {% for field in subForm %}
      {% if field.is_hidden %}

{{ field }}

      {% else %}
        {% if field.errors %}{{ field.errors }}{% endif %}

          {{ field.label_tag }} {{ field }}

      {% endif %}
    {% endfor %}
  {% endfor %}

    <input type="submit" name="post" class="submit-post" value="{% trans "Post" %}" />
    <input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}" />

</form>


text:
from utils.functions.models.dictlist import dictlist_lower

def get_ob(cursor, os):
    sql = f"""
        SELECT
          b.ORDEM_PRODUCAO OB
        , b.OBSERVACAO
        FROM PCPB_010 b
        WHERE b.OBSERVACAO LIKE '{os}.%'
    """
    cursor.execute(sql)
    return dictlist_lower(cursor)


text:
<?php

require_once 'phing/Task.php';
include_once 'phing/tasks/system/condition/Condition.php';
include_once 'phing/tasks/system/PropertyTask.php';
include_once 'phing/util/DirectoryScanner.php';
include_once 'phing/util/SourceFileScanner.php';
include_once 'phing/mappers/MergeMapper.php';

/**
 * Sets the given property if the specified target has a timestamp
 * greater than all of the source files.
 *
 * @author    Hans Lellelid <hans@xmpl.org> (Phing)
 * @author    William Ferguson <williamf@mincom.com> (Ant)
 * @author    Hiroaki Nakamura <hnakamur@mc.neweb.ne.jp> (Ant)
 * @author    Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
 * @version   $Id: 0941011292b768158652a316b80a9829705c9862 $
 * @package   phing.tasks.system
 */
class UpToDateTask extends Task implements Condition {

    private $_property;
    private $_value;
    private $_sourceFile;
    private $_targetFile;
    private $sourceFileSets = array();
    private $_filelists = array();

    protected $mapperElement = null;

    /**
     * The property to set if the target file is more up-to-date than
     * (each of) the source file(s).
     *
     * @param property the name of the property to set if Target is up-to-date.
     */
    public function setProperty($property) {
        $this->_property = $property;
    }

    /**
     * Get property name
     * @param property the name of the property to set if Target is up-to-date.
     */
    public function getProperty() {
        return $this->_property;
    }

    /**
     * The value to set the named property to if the target file is more
     * up-to-date than (each of) the source file(s). Defaults to 'true'.
     *
     * @param value the value to set the property to if Target is up-to-date
     */
    public function setValue($value) {
        $this->_value = $value;
    }

    /**
     * Returns the value, or "true" if a specific value wasn't provided.
     */
    private function getValue() {
        return ($this->_value !== null) ? $this->_value : "true";
    }

    /**
     * The file which must be more up-to-date than (each of) the source file(s)
     * if the property is to be set.
     *
     * @param file the file we are checking against.
     */
    public function setTargetFile($file) {
        if (is_string($file)) {
            $file = new PhingFile($file);
        }
        $this->_targetFile = $file;
    }

    /**
     * The file that must be older than the target file
     * if the property is to be set.
     *
     * @param file the file we are checking against the target file.
     */
    public function setSrcfile($file) {
        if (is_string($file)) {
            $file = new PhingFile($file);
        }
        $this->_sourceFile = $file;
    }

    /**
     * Nested <srcfiles> element.
     *
     * @deprecated Deprecated since Phing 2.4.0
     */
    public function createSrcfiles() {
        $fs = new FileSet();
        $this->sourceFileSets[] = $fs;
        return $fs;
    }

    /**
     * Nested <fileset> element.
     */
    public function addFileset(FileSet $fs) {
        $this->sourceFileSets[] = $fs;
    }

    /**
     * Supports embedded <filelist> element.
     * @return FileList
     */
    public function createFileList() {
        $num = array_push($this->_filelists, new FileList());
        return $this->_filelists[$num-1];
    }

    /**
     * Defines the FileNameMapper to use (nested mapper element).
     */
    public function createMapper() {
        if ($this->mapperElement !== null) {
            throw new BuildException("Cannot define more than one mapper",
                                     $this->location);
        }
        $this->mapperElement = new Mapper($this->getProject());
        return $this->mapperElement;
    }

    /**
     * Evaluate (all) target and source file(s) to
     * see if the target(s) is/are up-to-date.
     * @return boolean
     */
    public function evaluate() {
        if (count($this->sourceFileSets) == 0 && count($this->_filelists) == 0 && $this->_sourceFile === null) {
            throw new BuildException("At least one srcfile or a nested "
                                     . "<fileset> or <filelist> element must be set.");
        }

        if ((count($this->sourceFileSets) > 0 || count($this->_filelists) > 0) && $this->_sourceFile !== null) {
            throw new BuildException("Cannot specify both the srcfile "
                                     . "attribute and a nested <fileset> "
                                     . "or <filelist> element.");
        }

        if ($this->_targetFile === null && $this->mapperElement === null) {
            throw new BuildException("The targetfile attribute or a nested "
                                     . "mapper element must be set.");
        }

        // if the target file is not there, then it can't be up-to-date
        if ($this->_targetFile !== null && !$this->_targetFile->exists()) {
            return false;
        }

        // if the source file isn't there, throw an exception
        if ($this->_sourceFile !== null && !$this->_sourceFile->exists()) {
            throw new BuildException($this->_sourceFile->getAbsolutePath()
                                     . " not found.");
        }

        $upToDate = true;
        for($i=0,$size=count($this->sourceFileSets); $i < $size && $upToDate; $i++) {
            $fs = $this->sourceFileSets[$i];
            $ds = $fs->getDirectoryScanner($this->project);
            $upToDate = $upToDate && $this->scanDir($fs->getDir($this->project),
                                           $ds->getIncludedFiles());
        }

        for($i=0,$size=count($this->_filelists); $i < $size && $upToDate; $i++) {
            $fl = $this->_filelists[$i];
            $srcFiles = $fl->getFiles($this->project);
            $upToDate = $upToDate && $this->scanDir($fs->getDir($this->project),
                                           $srcFiles);
        }

        if ($this->_sourceFile !== null) {
            if ($this->mapperElement === null) {
                $upToDate = $upToDate &&
                    ($this->_targetFile->lastModified() >= $this->_sourceFile->lastModified());
            } else {
                $sfs = new SourceFileScanner($this);
                $upToDate = $upToDate &&
                    count($sfs->restrict($this->_sourceFile->getAbsolutePath(),
                                  null, null,
                                  $this->mapperElement->getImplementation())) === 0;
            }
        }
        return $upToDate;
    }

    /**
     * Sets property to true if target file(s) have a more recent timestamp
     * than (each of) the corresponding source file(s).
     * @throws BuildException
     */
    public function main() {
        if ($this->_property === null) {
            throw new BuildException("property attribute is required.",
                                     $this->location);
        }
        $upToDate = $this->evaluate();
        if ($upToDate) {
            $property = $this->project->createTask('property');
            $property->setName($this->getProperty());
            $property->setValue($this->getValue());
            $property->setOverride(true);
            $property->main(); // execute

            if ($this->mapperElement === null) {
                $this->log("File \"" . $this->_targetFile->getAbsolutePath()
                    . "\" is up-to-date.", Project::MSG_VERBOSE);
            } else {
                $this->log("All target files are up-to-date.",
                    Project::MSG_VERBOSE);
            }
        }
    }

    protected function scanDir(PhingFile $srcDir, $files) {
        $sfs = new SourceFileScanner($this);
        $mapper = null;
        $dir = $srcDir;
        if ($this->mapperElement === null) {
            $mm = new MergeMapper();
            $mm->setTo($this->_targetFile->getAbsolutePath());
            $mapper = $mm;
            $dir = null;
        } else {
            $mapper = $this->mapperElement->getImplementation();
        }
        return (count($sfs->restrict($files, $srcDir, $dir, $mapper)) === 0);
    }
}


text:
<?php

/**
 * @group properties
 */
class Papi_Property_Checkbox_Test extends Papi_Property_Test_Case {

	public $slug = 'checkbox_test';

	public function get_value() {
		return '#ffffff';
	}

	public function get_expected() {
		return ['#ffffff'];
	}

	public function test_property_convert_type() {
		$this->assertSame( 'array', $this->property->convert_type );
	}

	public function test_property_default_value() {
		$this->assertSame( [], $this->property->default_value );
	}

	public function test_property_format_value() {
		$this->assertSame( ['hello'], $this->property->format_value( 'hello', '', 0 ) );
		$this->assertSame( ['hello'], $this->property->format_value( ['hello'], '', 0 ) );
		$this->assertSame( [2014], $this->property->format_value( ['2014'], '', 0 ) );
		$this->assertSame( [12.3], $this->property->format_value( ['12.3'], '', 0 ) );
		$this->assertSame( [true], $this->property->format_value( ['true'], '', 0 ) );
		$this->assertSame( [false], $this->property->format_value( ['false'], '', 0 ) );
		$this->assertSame( [2014], $this->property->format_value( '2014', '', 0 ) );
		$this->assertSame( [12.3], $this->property->format_value( '12.3', '', 0 ) );
		$this->assertSame( [true], $this->property->format_value( 'true', '', 0 ) );
		$this->assertSame( [false], $this->property->format_value( 'false', '', 0 ) );
		$this->assertEmpty( $this->property->format_value( null, '', 0 ) );
	}

	public function test_property_import_value() {
		$this->assertSame( ['hello'], $this->property->import_value( 'hello', '', 0 ) );
		$this->assertSame( ['hello'], $this->property->import_value( ['hello'], '', 0 ) );
		$this->assertNull( $this->property->import_value( null, '', 0 ) );
		$this->assertNull( $this->property->import_value( true, '', 0 ) );
		$this->assertNull( $this->property->import_value( false, '', 0 ) );
		$this->assertNull( $this->property->import_value( (object) [], '', 0 ) );
		$this->assertNull( $this->property->import_value( 1, '', 0 ) );
	}

	public function test_property_options() {
		$this->assertSame( 'checkbox', $this->property->get_option( 'type' ) );
		$this->assertSame( 'Checkbox test', $this->property->get_option( 'title' ) );
		$this->assertSame( 'papi_checkbox_test', $this->property->get_option( 'slug' ) );
	}

	public function test_property_settings() {
		$this->assertNotEmpty( $this->property->get_setting( 'items' ) );
	}
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.latencyutils">
  <properties>
    <property name="jboss.api" value="private" />
  </properties>
  <resources>
    <artifact name="${org.latencyutils:LatencyUtils}" />
  </resources>
  <dependencies />
</module>


text:
description: This template creates an AKS compute target in given Azure Machine Learning service workspace with a private IP address.
page_type: sample
products:
- azure
- azure-resource-manager
urlFragment: machine-learning-private-ip
languages:
- json
---
# Create an AKS compute target with a Private IP address.

![Azure Public Test Date](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.machinelearningservices/machine-learning-private-ip/PublicLastTestDate.svg)
![Azure Public Test Result](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.machinelearningservices/machine-learning-private-ip/PublicDeployment.svg)

![Azure US Gov Last Test Date](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.machinelearningservices/machine-learning-private-ip/FairfaxLastTestDate.svg)
![Azure US Gov Last Test Result](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.machinelearningservices/machine-learning-private-ip/FairfaxDeployment.svg)

![Best Practice Check](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.machinelearningservices/machine-learning-private-ip/BestPracticeResult.svg)
![Cred Scan Check](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.machinelearningservices/machine-learning-private-ip/CredScanResult.svg)

[![Deploy To Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Fquickstarts%2Fmicrosoft.machinelearningservices%2Fmachine-learning-private-ip%2Fazuredeploy.json)  [![Visualize](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/visualizebutton.svg?sanitize=true)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Fquickstarts%2Fmicrosoft.machinelearningservices%2Fmachine-learning-private-ip%2Fazuredeploy.json)

This template creates an AKS compute target with a Private IP address.

If you are new to Azure Machine Learning, see:

- [Azure Machine Learning service](https://azure.microsoft.com/services/machine-learning-service/)
- [Azure Machine Learning documentation](https://docs.microsoft.com/azure/machine-learning/)
- [Azure Machine Learning template reference](https://docs.microsoft.com/azure/templates/microsoft.machinelearningservices/allversions)
- [Quickstart templates](https://azure.microsoft.com/resources/templates/)

If you are new to template development, see:

- [Azure Resource Manager documentation](https://docs.microsoft.com/azure/azure-resource-manager/)
- [Create an Azure Machine Learning service workspace by using a template](https://docs.microsoft.com/azure/machine-learning/service/how-to-create-workspace-template)

Tags: Azure Machine Learning, Machine Learning, Secrets, Resource Manager, Resource Manager templates, ARM templates

`Tags: Microsoft.Storage/storageAccounts, Microsoft.KeyVault/vaults, Microsoft.Insights/components, Microsoft.ContainerRegistry/registries, Microsoft.MachineLearningServices/workspaces, systemAssigned, Microsoft.MachineLearningServices/workspaces/computes`


text:
Status and availability let your teammates know roughly how quickly you'll
be responding to messages.

A **status** is a customizable message visible to all team members. A
typical status might be "in a meeting", "on vacation", or "visiting SF next week".

Your **availability** is a colored dot (like )
that indicates if you're currently active on Zulip, idle,
offline, or unavailable. If you're not current active, Zulip also lets your
teammates know when you were last active.

## Set a status

{start_tabs}

1. Hover over your name in the right sidebar.

1. Click the ellipsis () to the right.

1. Click **Set a status message**.

1. Set a status messages and click **Save**.

{end_tabs}

You can view anyone else's status by hovering over their name in the left or
right sidebar, or by clicking their name or avatar in the main message feed. If
they haven't set a status, no status will appear.

## About availability

There are four possible availabilities:

* **Active** (): Zulip is
  open and in focus on web, desktop or mobile, or was in the last 140
  seconds.

* **Idle** (): Zulip is open on
  your computer (either desktop or web), but you are not active.

* **Offline** (): Zulip is not
  open on your computer.

* **Unavailable** (): You can
  always manually set your availability to unavailable.

For [Group PMs](/help/private-messages), a green circle
()
means all users in the group are active. A pale green circle () means that some are active and some are
not. A white circle () means that none
are active.

You can see when someone was last recorded as active by hovering over
their name in the left or right sidebar (even if the user is marked as
unavailable).

## Set yourself as unavailable

{start_tabs}

1. Hover over your name in the right sidebar.

1. Click the ellipsis () to the right.

1. Click **Set yourself as unavailable**.

{end_tabs}

## Disable updating availability

Zulip supports the privacy option of never updating the availability
information for your account.  The result is that you will always
appear to other users as **Offline** (or **Unavailable**, if you've
set an appropriate status), regardless of your activity in Zulip.

With this setting, your "Last active" time displayed to other users in
the UI will be frozen as the time you enabled this setting.

{start_tabs}

{settings_tab|notifications}

1. Under **Other notification settings**, in the **Presence**
   subsection, toggle **Display my availability to other users**.

{end_tabs}

Note that because this setting works by making your availability stop
updating, you'll still appear to other users as active for a few
minutes after disabling updates to your availability.


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>br.com.minitwitter Class Hierarchy</title>
<meta name="date" content="2016-12-29">
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev

Next

Frames

No Frames

All Classes

Hierarchy For Package br.com.minitwitter

Package Hierarchies:

All Packages

Class Hierarchy

java.lang.Object

br.com.minitwitter.MinitwitterApplication

br.com.minitwitter.MinitwitterApplicationTests

org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter (implements org.springframework.security.config.annotation.web.WebSecurityConfigurer<T>)

br.com.minitwitter.WebSecurityConfig

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev

Next

Frames

No Frames

All Classes


text:
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import unittest

import mock

from dashboard.services import gerrit_service

class _SwarmingTest(unittest.TestCase):

  def setUp(self):
    patcher = mock.patch('dashboard.services.request.RequestJson')
    self._request_json = patcher.start()
    self.addCleanup(patcher.stop)
    patcher2 = mock.patch('dashboard.services.request.Request')
    self._request = patcher2.start()
    self.addCleanup(patcher2.stop)

    self._request_json.return_value = {'content': {}}

  def _AssertCorrectResponse(self, content):
    self.assertEqual(content, {'content': {}})

  def _AssertRequestMadeOnce(self, url, *args, **kwargs):
    self._request_json.assert_called_once_with(url, *args, **kwargs)

  def testGetChange(self):
    server = 'https://chromium-review.googlesource.com'
    response = gerrit_service.GetChange(server, 672011)
    self._AssertCorrectResponse(response)
    self._AssertRequestMadeOnce(
        server + '/changes/672011',
        use_auth=True,
        scope=gerrit_service.GERRIT_SCOPE,
        o=None)

  def testGetChangeWithFields(self):
    server = 'https://chromium-review.googlesource.com'
    response = gerrit_service.GetChange(server, 672011, fields=('FIELD_NAME',))
    self._AssertCorrectResponse(response)
    self._AssertRequestMadeOnce(
        server + '/changes/672011',
        use_auth=True,
        scope=gerrit_service.GERRIT_SCOPE,
        o=('FIELD_NAME',))

  def testPostChangeComment(self):
    server = 'https://chromium-review.googlesource.com'
    gerrit_service.PostChangeComment(server, 12334, 'hello!')
    self._request.assert_called_once_with(
        'https://chromium-review.googlesource.com/a/changes/12334'
        '/revisions/current/review',
        body='hello!',
        scope=gerrit_service.GERRIT_SCOPE,
        use_cache=False,
        method='POST',
        use_auth=True)


text:
name: Android Basics: Preference Datastore
about: Report problems with the Android Basics Unit 3 codelabs
title: 'Android Basics: Preference Datastore'
labels: ''
assignees: ''

---

**URL of codelab**

**In which task and step of the codelab can this issue be found?**

**Describe the problem**

**Steps to reproduce?**
1. Go to...
2. Click on...
3. See error...

**Versions**
_Android Studio version:_
_API version of the emulator:_

**Additional information**
_Include screenshots if they would be useful in clarifying the problem._


text:
require 'intercom/service/base_service'
require 'intercom/api_operations/find_all'
require 'intercom/api_operations/find'
require 'intercom/api_operations/load'
require 'intercom/api_operations/save'

module Intercom
  module Service
    class Conversation < BaseService
      include ApiOperations::FindAll
      include ApiOperations::Find
      include ApiOperations::Load
      include ApiOperations::Save

      def collection_class
        Intercom::Conversation
      end

      def mark_read(id)
        @client.put("/conversations/#{id}", read: true)
      end

      def reply(reply_data)
        id = reply_data.delete(:id)
        collection_name = Utils.resource_class_to_collection_name(collection_class)
        response = @client.post("/#{collection_name}/#{id}/reply", reply_data.merge(:conversation_id => id))
        collection_class.new.from_response(response)
      end

      def open(reply_data)
        reply reply_data.merge(message_type: 'open', type: 'admin')
      end

      def close(reply_data)
        reply reply_data.merge(message_type: 'close', type: 'admin')
      end

      def assign(reply_data)
        assignee_id = reply_data.fetch(:assignee_id) { fail 'assignee_id is required' }
        reply reply_data.merge(message_type: 'assignment', assignee_id: assignee_id, type: 'admin')
      end
    end
  end
end