Exemplo n.º 1
0
def test_queue_limit(app, queue, queue_manager, tracks):
    """
    Users should not be able to queue over xx minuets of tracks (settable in config)
    Users trying to add tracks after this time have a 'window period of priority'
    where they have first dibs.
    The user should be informed by the status flash message how long before they
    should retry there selection.
    """
    # Ensure we don't have an existing priority token
    assert not get_cookie(app, 'priority_token')

    # Fill the Queue
    response = queue_manager.add_queue_item(
        track_id='t1', performer_name='bob1')  # total_duration = 0sec
    response = queue_manager.add_queue_item(
        track_id='t1',
        performer_name='bob2')  #  90sec (1min track + 30sec padding)
    response = queue_manager.add_queue_item(
        track_id='t1', performer_name='bob3'
    )  # 180sec (1min track + 30sec padding) - by adding this track we will be at 180sec, that is now OVER 150sec, the next addition will error

    # Fail quque add, get priority token
    response = queue_manager.add_queue_item(track_id='t1',
                                            performer_name='bob4',
                                            expect_errors=True)
    assert response.status_code == 400
    cookie_priority_token = get_cookie(app, 'priority_token')
    assert cookie_priority_token.get('valid_start')
    assert cookie_priority_token.get('server_datetime')

    # Try queue add again and not get priority token give as we already have one
    response = queue_manager.add_queue_item(track_id='t1',
                                            performer_name='bob4',
                                            expect_errors=True)
    #assert 'already have' in response.json['messages'][0]
    assert 'view.queue_item.add.priority_token_already_issued' in response.text

    # Shift server time forward - simulate waiting 5 minuets - we should be in our priority token range
    now(now() + datetime.timedelta(minutes=5))

    # Add the track using the power of the priority token
    response = queue_manager.add_queue_item(track_id='t1',
                                            performer_name='bob4')
    assert 'bob4' in [q['performer_name'] for q in queue_manager.items]
    assert not get_cookie(
        app, 'priority_token'
    )  # The priority token should be consumed and removed from the client

    # Tidyup after test
    now(datetime.datetime.now())
Exemplo n.º 2
0
def priority_tokens(request):
    # TODO: karakara.queue.add.duplicate.time_limit is the wrong value to use here
    priority_tokens = DBSession.query(PriorityToken)\
        .filter(PriorityToken.valid_start >= now() - request.queue.settings.get('karakara.queue.add.duplicate.time_limit')) \
        .order_by(PriorityToken.valid_start)
    return action_ok(data={
        'priority_tokens': tuple(priority_token.to_dict('full') for priority_token in priority_tokens),
    })
Exemplo n.º 3
0
def priority_tokens(request):
    # TODO: karakara.queue.add.duplicate.time_limit is the wrong value to use here
    priority_tokens = DBSession.query(PriorityToken)\
        .filter(PriorityToken.valid_start >= now() - request.queue.settings.get('karakara.queue.add.duplicate.time_limit')) \
        .order_by(PriorityToken.valid_start)
    return action_ok(
        data={
            'priority_tokens':
            tuple(
                priority_token.to_dict('full')
                for priority_token in priority_tokens),
        })
Exemplo n.º 4
0
 def consume(self):
     try:
         token = DBSession.query(PriorityToken) \
             .filter(PriorityToken.used == False) \
             .filter(PriorityToken.session_owner == self.user_id) \
             .filter(PriorityToken.valid_start <= now(), PriorityToken.valid_end > now()) \
             .one()
         token.used = True
         self.request.response.delete_cookie('priority_token')
         log.debug('priority_token consumed')
         return True
     except NoResultFound:
         return False
Exemplo n.º 5
0
def test_queue_limit(app, queue, queue_manager, tracks):
    """
    Users should not be able to queue over xx minuets of tracks (settable in config)
    Users trying to add tracks after this time have a 'window period of priority'
    where they have first dibs.
    The user should be informed by the status flash message how long before they
    should retry there selection.
    """
    # Ensure we don't have an existing priority token
    assert not get_cookie(app, 'priority_token')

    # Fill the Queue
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob1')  # total_duration = 0sec
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob2')  #  90sec (1min track + 30sec padding)
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob3')  # 180sec (1min track + 30sec padding) - by adding this track we will be at 180sec, that is now OVER 150sec, the next addition will error

    # Fail quque add, get priority token
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob4', expect_errors=True)
    assert response.status_code == 400
    cookie_priority_token = get_cookie(app, 'priority_token')
    assert cookie_priority_token.get('valid_start')
    assert cookie_priority_token.get('server_datetime')

    # Try queue add again and not get priority token give as we already have one
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob4', expect_errors=True)
    #assert 'already have' in response.json['messages'][0]
    assert 'view.queue_item.add.priority_token_already_issued' in response.text

    # Shift server time forward - simulate waiting 5 minuets - we should be in our priority token range
    now(now() + datetime.timedelta(minutes=5))

    # Add the track using the power of the priority token
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob4')
    assert 'bob4' in [q['performer_name'] for q in queue_manager.items]
    assert not get_cookie(app, 'priority_token')  # The priority token should be consumed and removed from the client

    # Tidyup after test
    now(datetime.datetime.now())
Exemplo n.º 6
0
    def _queue_item_for(self, queue_items_query):
        """
            TODO:
                Get some unit tests around this functionality
                Ensure that the time_limit takes into account the current length of the queue as well
                Separate out the duplicate 'track' and 'performer' times rather than just 'duplicate.time_limit'
                Renamed 'duplicate.track_limit' to 'duplicate.limit.track.count'
                Consider better variable name for 'latest_queue_item' - it's the oldest know instance of that occurrence.
        """
        time_limit = self.request.queue.settings.get('karakara.queue.add.duplicate.time_limit')
        track_limit = self.request.queue.settings.get('karakara.queue.add.duplicate.track_limit')
        performer_limit = self.request.queue.settings.get('karakara.queue.add.duplicate.performer_limit')

        queue_items = queue_items_query.all()

        played = [q for q in queue_items if q.status == 'played']
        pending = [q for q in queue_items if q.status == 'pending']
        track_count = len(played+pending)
        latest_queue_item = queue_items[0] if len(queue_items) else None

        track_status = QUEUE_DUPLICATE.NONE
        if track_limit and track_count >= track_limit:
            track_status = QUEUE_DUPLICATE.THRESHOLD
        elif pending:
            track_status = QUEUE_DUPLICATE.PENDING
        elif played:
            track_status = QUEUE_DUPLICATE.PLAYED

        performer_status = QUEUE_DUPLICATE.NONE
        if performer_limit and track_count >= performer_limit:
            performer_status = QUEUE_DUPLICATE.THRESHOLD

        estimated_next_add_time = datetime.timedelta(0)
        if time_limit and latest_queue_item:
            estimated_next_add_time = time_limit - (now() - latest_queue_item.time_touched)  # time_touched is NOT an acceptable way of measuring this. We need to calculate the estimated track time, but that is really expensive

        return {
            'queue_items': queue_items,
            'played': played,
            'pending': pending,
            'track_status': track_status,
            'track_limit': track_limit,
            'performer_status': performer_status,
            'performer_limit': performer_limit,
            'estimated_next_add_time': estimated_next_add_time,
            'track_count': track_count,
        }
Exemplo n.º 7
0
 def log_event(request, **data):
     """
     It is expected that python's logging framework is used to output these
     events to the correct destination.
     Logstash can then read/process this log output for overview/stats
     """
     event = data.get('event')
     try:
         event = request.matched_route.name
     except Exception:
         pass
     try:
         event = request.context.__name__
     except Exception:
         pass
     data.update({
         'event': event,
         'session_id': request.session.get('id'),
         'ip': request.environ.get('REMOTE_ADDR'),
         'timestamp': now(),
     })
     log_event_logger.info(json_string(data))
Exemplo n.º 8
0
def queue_item_add(request):
    """
    Add items to end of queue
    """
    _ = request.translate
    _log_event = partial(request.log_event, method='add')

    # Validation
    for field in ['track_id', 'performer_name']:
        if not request.params.get(field):
            raise action_error(message='no {0}'.format(field), code=400)
    track_id = request.params.get('track_id')
    try:
        track = DBSession.query(Track).get(track_id)
        assert track
    except AssertionError:
        raise action_error(message=_('view.queue_item.add.error.track_id ${track_id}', mapping={'track_id': track_id}), code=400)

    # If not admin, check additional restrictions
    if not is_admin(request):
        performer_name = request.params.get('performer_name').strip()  # TODO: It would be good to ensure this value is writen to the db. However we cant modify the request.param dict directly. See creation of queueitem below

        # Valid performer name
        valid_performer_names = request.queue.settings.get('karakara.queue.add.valid_performer_names')
        if valid_performer_names and performer_name.lower() not in map(lambda name: name.lower(), valid_performer_names):
            message = _('view.queue_item.add.invalid_performer_name ${performer_name}', mapping=dict(
                performer_name=performer_name
            ))
            raise action_error(message, code=400)

        # TODO: Unify and tidy this shit .. Duplicate messages are very similat and can offload they db access to the model_logic.

        # Duplicate performer retractions
        queue_item_performed_tracks = request.queue.for_performer(performer_name)
        if queue_item_performed_tracks['performer_status'] == QUEUE_DUPLICATE.THRESHOLD:
            try:
                latest_track_title = get_track(queue_item_performed_tracks['queue_items'][0].track_id).title
            except Exception:
                latest_track_title = ''
            message = _('view.queue_item.add.dupicate_performer_limit ${performer_name} ${estimated_next_add_time} ${track_count} ${latest_queue_item_title}', mapping=dict(
                performer_name=performer_name,
                latest_queue_item_title=latest_track_title,
                **subdict(queue_item_performed_tracks, {
                    'estimated_next_add_time',
                    'track_count',
                })
            ))
            _log_event(status='reject', reason='dupicate.performer', message=message)
            raise action_error(message=message, code=400)

        # Duplicate Addition Restrictions
        queue_item_tracks_queued = request.queue.for_track(track.id)
        if queue_item_tracks_queued['track_status'] == QUEUE_DUPLICATE.THRESHOLD:
            try:
                latest_track_title = get_track(queue_item_tracks_queued['queue_items'][0].track_id).title
            except Exception:
                latest_track_title = ''
            message = _('view.queue_item.add.dupicate_track_limit ${track_id} ${estimated_next_add_time} ${track_count} ${latest_queue_item_title}', mapping=dict(
                track_id=track.id,
                latest_queue_item_title=latest_track_title,
                **subdict(queue_item_tracks_queued, {
                    'estimated_next_add_time',
                    'track_count',
                })
            ))
            _log_event(status='reject', reason='duplicate.track', message=message)
            raise action_error(message=message, code=400)

        # Event start time
        event_start = request.queue.settings.get('karakara.event.start')
        if event_start and now() < event_start:
            log.debug('event start restricted')
            _log_event(status='reject', reason='event_start')
            raise action_error(message=_('view.queue_item.add.event_start ${event_start}', mapping={'event_start': event_start}), code=400)

        # Event end time
        event_end = request.queue.settings.get('karakara.event.end')
        if event_end and now() + request.queue.duration > event_end:
            log.debug('event end restricted')
            _log_event(status='reject', reason='event_end')
            raise action_error(message=_('view.queue_item.add.event_end ${event_end}', mapping={'event_end': event_end}), code=400)

        # Queue time limit
        queue_limit = request.queue.settings.get('karakara.queue.add.limit')
        if queue_limit and request.queue.duration > queue_limit:
            # If no device priority token - issue token and abort
            # else consume the token and proceed with addition
            priority_token_manager = PriorityTokenManager(request)
            if not priority_token_manager.consume():
                # Issue a priority token
                priority_token = priority_token_manager.issue()
                if isinstance(priority_token, PriorityToken):
                    _log_event(status='reject', reason='token.issued')
                    raise action_error(message=_('view.queue_item.add.priority_token_issued'), code=400)
                if priority_token == TOKEN_ISSUE_ERROR.EVENT_END:
                    _log_event(status='reject', reason='event_end')
                    raise action_error(message=_('view.queue_item.add.event_end ${event_end}', mapping={'event_end': event_end}), code=400)
                if priority_token == TOKEN_ISSUE_ERROR.TOKEN_ISSUED:
                    _log_event(status='reject', reason='token.already_issued')
                    raise action_error(message=_('view.queue_item.add.priority_token_already_issued'), code=400)
                _log_event(status='reject', reason='token.limit')
                raise action_error(message=_('view.queue_item.add.token_limit'), code=400)

    queue_item = QueueItem()
    for key, value in request.params.items():  # TODO: strip() the performer_name?
        if hasattr(queue_item, key):
            setattr(queue_item, key, value)
    queue_item.queue_id = request.context.queue_id

    # Set session owner - if admin allow manual setting of session_owner via params
    if is_admin(request) and queue_item.session_owner:
        pass
    else:
        queue_item.session_owner = request.session_identity['id']

    DBSession.add(queue_item)
    _log_event(status='ok', queue_id=queue_item.queue_id, track_id=queue_item.track_id, performer_name=queue_item.performer_name)
    #log.info('add - %s to queue by %s' % (queue_item.track_id, queue_item.performer_name))

    message_data = {'track_id': queue_item.track_id, 'performer_name': queue_item.performer_name}
    invalidate_cache(request, track_id)

    return action_ok(
        message=_('view.queue_item.add.ok ${track_id} ${performer_name}', mapping=message_data),
        data={'queue_item.id': ''},
        code=201,
    )  # TODO: should return 201 and have id of newly created object. data={'track':{'id':}}
Exemplo n.º 9
0
    # Add the track using the power of the priority token
    response = queue_manager.add_queue_item(track_id='t1',
                                            performer_name='bob4')
    assert 'bob4' in [q['performer_name'] for q in queue_manager.items]
    assert not get_cookie(
        app, 'priority_token'
    )  # The priority token should be consumed and removed from the client

    # Tidyup after test
    now(datetime.datetime.now())


@with_settings(settings={
    'karakara.event.end':
    str(now() + datetime.timedelta(minutes=0, seconds=30)),
})
def test_event_end(app, queue, queue_manager, tracks):
    response = queue_manager.add_queue_item(track_id='t1',
                                            performer_name='bob1')
    response = queue_manager.add_queue_item(track_id='t2',
                                            performer_name='bob2',
                                            expect_errors=True)
    assert response.status_code == 400
    assert 'view.queue_item.add.event_end' in response.text


@with_settings(
    settings={
        'karakara.event.start':
        str(now() + datetime.timedelta(minutes=0, seconds=30)),
Exemplo n.º 10
0
    def issue(self):
        priority_window = self.settings.get(
            'karakara.queue.add.limit.priority_window')
        # TODO: Depreciate this priority_window settings
        #  This can be auto-calculated from the current average track length in the queue

        # Aquire most recent priority token - if most recent token in past, set recent token to now
        try:
            latest_token = DBSession.query(PriorityToken).filter(
                PriorityToken.used == False).order_by(
                    PriorityToken.valid_end.desc()).limit(1).one()
            latest_token_end = latest_token.valid_end
        except NoResultFound:
            latest_token_end = None
        if not latest_token_end or latest_token_end < now():
            # When issueing the first priority token
            latest_token_end = now(
            ) + priority_window  # get_queue_duration(request) # Adding entire queue here was unnessisary.

        # Do not issue tokens past the end of the event
        event_end = self.settings.get('karakara.event.end')
        if event_end and latest_token_end > event_end:
            # Unable to issue token as event end
            log.debug('priority_token rejected - event end')
            return TOKEN_ISSUE_ERROR.EVENT_END

        # TODO: possibly depricate this - we can just keep staking tokens until the end of the event
        priority_token_limit = self.settings.get(
            'karakara.queue.add.limit.priority_token')
        if priority_token_limit and latest_token_end > now(
        ) + priority_token_limit:
            # Unable to issue token as priority tokens are time limited
            log.debug('priority_token rejected - token limit')
            return TOKEN_ISSUE_ERROR.TOKEN_LIMIT

        # TODO: Look at the last priority tokens created and raise a warning if the token is likely to pass beyond the end of the event.

        # Do not issue another priority_token if current user already has a priority_token
        try:
            priority_token = DBSession.query(PriorityToken) \
                                .filter(PriorityToken.used==False) \
                                .filter(PriorityToken.session_owner==self.user_id) \
                                .filter(PriorityToken.valid_end>now()) \
                                .one()
            if priority_token:
                log.debug('priority_token rejected - existing token')
                return TOKEN_ISSUE_ERROR.TOKEN_ISSUED
        except NoResultFound:
            pass

        # Issue the new token
        priority_token = PriorityToken()
        priority_token.session_owner = self.user_id
        priority_token.valid_start = latest_token_end
        priority_token.valid_end = latest_token_end + priority_window
        DBSession.add(priority_token)

        # TODO: replace with new one in lib
        #request.response.set_cookie('priority_token', json_cookie);  # WebOb.set_cookie mangles the cookie with m.serialize() - so I rolled my own set_cookie
        priority_token_dict = priority_token.to_dict()
        priority_token_dict.update({
            'server_datetime': now(
            ),  # The client datetime and server datetime may be out. we need to return the server time so the client can calculate the difference
        })
        json_cookie = json.dumps(priority_token_dict,
                                 default=json_object_handler)
        self.request.response.headerlist.append(
            ('Set-Cookie', 'priority_token={0}; Path=/'.format(json_cookie)))
        #self.request.response.set_cookie(name='priority_token', value=json_cookie, path='/', overwrite=True)  # This method butchers the json and cannot be used

        log.debug('priority_token issued')
        return priority_token
Exemplo n.º 11
0
def queue_item_add(request):
    """
    Add items to end of queue
    """
    _ = request.translate
    _log_event = partial(request.log_event, method='add')

    # Validation
    for field in ['track_id', 'performer_name']:
        if not request.params.get(field):
            raise action_error(message='no {0}'.format(field), code=400)
    track_id = request.params.get('track_id')
    try:
        track = DBSession.query(Track).get(track_id)
        assert track
    except AssertionError:
        raise action_error(message=_(
            'view.queue_item.add.error.track_id ${track_id}',
            mapping={'track_id': track_id}),
                           code=400)

    # If not admin, check additional restrictions
    if not is_admin(request):
        performer_name = request.params.get('performer_name').strip(
        )  # TODO: It would be good to ensure this value is writen to the db. However we cant modify the request.param dict directly. See creation of queueitem below

        # Valid performer name
        valid_performer_names = request.queue.settings.get(
            'karakara.queue.add.valid_performer_names')
        if valid_performer_names and performer_name.lower() not in map(
                lambda name: name.lower(), valid_performer_names):
            message = _(
                'view.queue_item.add.invalid_performer_name ${performer_name}',
                mapping=dict(performer_name=performer_name))
            raise action_error(message, code=400)

        # TODO: Unify and tidy this shit .. Duplicate messages are very similat and can offload they db access to the model_logic.

        # Duplicate performer retractions
        queue_item_performed_tracks = request.queue.for_performer(
            performer_name)
        if queue_item_performed_tracks[
                'performer_status'] == QUEUE_DUPLICATE.THRESHOLD:
            try:
                latest_track_title = get_track(
                    queue_item_performed_tracks['queue_items']
                    [0].track_id).title
            except Exception:
                latest_track_title = ''
            message = _(
                'view.queue_item.add.dupicate_performer_limit ${performer_name} ${estimated_next_add_time} ${track_count} ${latest_queue_item_title}',
                mapping=dict(performer_name=performer_name,
                             latest_queue_item_title=latest_track_title,
                             **subdict(queue_item_performed_tracks, {
                                 'estimated_next_add_time',
                                 'track_count',
                             })))
            _log_event(status='reject',
                       reason='dupicate.performer',
                       message=message)
            raise action_error(message=message, code=400)

        # Duplicate Addition Restrictions
        queue_item_tracks_queued = request.queue.for_track(track.id)
        if queue_item_tracks_queued[
                'track_status'] == QUEUE_DUPLICATE.THRESHOLD:
            try:
                latest_track_title = get_track(
                    queue_item_tracks_queued['queue_items'][0].track_id).title
            except Exception:
                latest_track_title = ''
            message = _(
                'view.queue_item.add.dupicate_track_limit ${track_id} ${estimated_next_add_time} ${track_count} ${latest_queue_item_title}',
                mapping=dict(track_id=track.id,
                             latest_queue_item_title=latest_track_title,
                             **subdict(queue_item_tracks_queued, {
                                 'estimated_next_add_time',
                                 'track_count',
                             })))
            _log_event(status='reject',
                       reason='duplicate.track',
                       message=message)
            raise action_error(message=message, code=400)

        # Event start time
        event_start = request.queue.settings.get('karakara.event.start')
        if event_start and now() < event_start:
            log.debug('event start restricted')
            _log_event(status='reject', reason='event_start')
            raise action_error(message=_(
                'view.queue_item.add.event_start ${event_start}',
                mapping={'event_start': event_start}),
                               code=400)

        # Event end time
        event_end = request.queue.settings.get('karakara.event.end')
        if event_end and now() + request.queue.duration > event_end:
            log.debug('event end restricted')
            _log_event(status='reject', reason='event_end')
            raise action_error(message=_(
                'view.queue_item.add.event_end ${event_end}',
                mapping={'event_end': event_end}),
                               code=400)

        # Queue time limit
        queue_limit = request.queue.settings.get('karakara.queue.add.limit')
        if queue_limit and request.queue.duration > queue_limit:
            # If no device priority token - issue token and abort
            # else consume the token and proceed with addition
            priority_token_manager = PriorityTokenManager(request)
            if not priority_token_manager.consume():
                # Issue a priority token
                priority_token = priority_token_manager.issue()
                if isinstance(priority_token, PriorityToken):
                    _log_event(status='reject', reason='token.issued')
                    raise action_error(
                        message=_('view.queue_item.add.priority_token_issued'),
                        code=400)
                if priority_token == TOKEN_ISSUE_ERROR.EVENT_END:
                    _log_event(status='reject', reason='event_end')
                    raise action_error(message=_(
                        'view.queue_item.add.event_end ${event_end}',
                        mapping={'event_end': event_end}),
                                       code=400)
                if priority_token == TOKEN_ISSUE_ERROR.TOKEN_ISSUED:
                    _log_event(status='reject', reason='token.already_issued')
                    raise action_error(message=_(
                        'view.queue_item.add.priority_token_already_issued'),
                                       code=400)
                _log_event(status='reject', reason='token.limit')
                raise action_error(
                    message=_('view.queue_item.add.token_limit'), code=400)

    queue_item = QueueItem()
    for key, value in request.params.items(
    ):  # TODO: strip() the performer_name?
        if hasattr(queue_item, key):
            setattr(queue_item, key, value)
    queue_item.queue_id = request.context.queue_id

    # Set session owner - if admin allow manual setting of session_owner via params
    if is_admin(request) and queue_item.session_owner:
        pass
    else:
        queue_item.session_owner = request.session['id']

    DBSession.add(queue_item)
    _log_event(status='ok',
               queue_id=queue_item.queue_id,
               track_id=queue_item.track_id,
               performer_name=queue_item.performer_name)
    #log.info('add - %s to queue by %s' % (queue_item.track_id, queue_item.performer_name))

    message_data = {
        'track_id': queue_item.track_id,
        'performer_name': queue_item.performer_name
    }
    invalidate_cache(request, track_id)

    return action_ok(
        message=_('view.queue_item.add.ok ${track_id} ${performer_name}',
                  mapping=message_data),
        data={'queue_item.id': ''},
        code=201,
    )  # TODO: should return 201 and have id of newly created object. data={'track':{'id':}}
Exemplo n.º 12
0
    assert 'view.queue_item.add.priority_token_already_issued' in response.text

    # Shift server time forward - simulate waiting 5 minuets - we should be in our priority token range
    now(now() + datetime.timedelta(minutes=5))

    # Add the track using the power of the priority token
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob4')
    assert 'bob4' in [q['performer_name'] for q in queue_manager.items]
    assert not get_cookie(app, 'priority_token')  # The priority token should be consumed and removed from the client

    # Tidyup after test
    now(datetime.datetime.now())


@with_settings(settings={
    'karakara.event.end': str(now() + datetime.timedelta(minutes=0, seconds=30)),
})
def test_event_end(app, queue, queue_manager, tracks):
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob1')
    response = queue_manager.add_queue_item(track_id='t2', performer_name='bob2', expect_errors=True)
    assert response.status_code == 400
    assert 'view.queue_item.add.event_end' in response.text


@with_settings(settings={
    'karakara.event.start': str(now() + datetime.timedelta(minutes=0, seconds=30)),
})
def test_event_start(app, queue, queue_manager, tracks):
    response = queue_manager.add_queue_item(track_id='t1', performer_name='bob1', expect_errors=True)
    assert response.status_code == 400
    assert 'view.queue_item.add.event_start' in response.text