Ejemplo n.º 1
0
 def setUp(self):
     self.conn = self.lookup_connections(identities='111')[0]
     self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
     self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
     self.msg = u"%s" % (self.good_nid)
     self.election = ElectionFactory(polling_start_time=PAST_DAY,
                                     polling_end_time=FUTURE_DAY)
Ejemplo n.º 2
0
 def setUp(self):
     # lookup_connections takes any identity and creates connections.
     # It's better than create_connection because it uses 'mockbackend'
     # which keeps track of sent messages.
     self.conn = self.lookup_connections(identities=['111'])[0]
     self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
     self.good_center_id = get_random_number_string(
         length=constants.CENTER_ID_LENGTH)
     self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
     self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY,
                                                 end_time=FUTURE_DAY)
     self.election = ElectionFactory(polling_start_time=PAST_DAY,
                                     polling_end_time=FUTURE_DAY)
Ejemplo n.º 3
0
 def setUp(self):
     self.original = RegistrationCenterFactory()
     self.copy = RegistrationCenterFactory(copy_of=self.original)
     self.polling_locations = get_all_polling_locations()
     self.election = ElectionFactory(
         polling_start_time=now() - datetime.timedelta(hours=1),
         polling_end_time=now() + datetime.timedelta(hours=1),
     )
     # add decoy elections before/after the real one
     self.decoy_before_election = ElectionFactory(
         polling_start_time=self.election.polling_start_time -
         datetime.timedelta(days=5),
         polling_end_time=self.election.polling_end_time -
         datetime.timedelta(days=5),
     )
     self.decoy_after_election = ElectionFactory(
         polling_start_time=self.election.polling_start_time +
         datetime.timedelta(days=5),
         polling_end_time=self.election.polling_end_time +
         datetime.timedelta(days=5),
     )
     self.test_office_1 = 1
     self.test_office_2 = 2
     self.test_region = 3
     self.polling_centers = {
         '11001': {
             'polling_center_code': 11001,
             'office_id': self.test_office_1,
             'subconstituency_id': 2,
             'region': Office.REGION_NAMES[self.test_region],
             'country': 'Libya'
         },
         '11002': {
             'polling_center_code': 11002,
             'office_id': self.test_office_2,
             'subconstituency_id': 2,
             'region': Office.REGION_NAMES[self.test_region],
             'country': 'Libya'
         },
         '11003': {
             'polling_center_code': 11003,
             'office_id': self.test_office_1,
             'subconstituency_id': 2,
             'region': Office.REGION_NAMES[self.test_region],
             'country': 'Libya'
         }
     }
     self.center_opens = []
     self.center_reports = []
     self.inactive_for_election = ['11003']
Ejemplo n.º 4
0
    def test(self):
        center = RegistrationCenterFactory()
        elections = [
            {
                'polling_start_time': now() - datetime.timedelta(days=60)
            },
            {
                'polling_start_time': now() - datetime.timedelta(days=40)
            },
            {
                'polling_start_time': now() - datetime.timedelta(days=20)
            },
        ]

        for election in elections:
            election['polling_end_time'] = \
                election['polling_start_time'] + datetime.timedelta(hours=6)
            election['object'] = ElectionFactory(
                polling_start_time=election['polling_start_time'],
                polling_end_time=election['polling_end_time'],
            )
            election['staff_phone_1'] = StaffPhoneFactory(
                registration_center=center,
                creation_date=election['object'].work_start_time)
            election['staff_phone_2'] = StaffPhoneFactory(
                registration_center=center,
                creation_date=election['object'].work_end_time)

        for i, election in enumerate(elections, start=1):
            messages_for_center = message_log(
                election['object'])[center.center_id]
            self.assertEqual(len(messages_for_center), i * 2)
            # check for other junk leaking into the testcase
            for message in messages_for_center:
                self.assertEqual(message['type'], 'phonelink')
Ejemplo n.º 5
0
    def setUp(self):
        subconstituency_name = os.environ.get('ROLLGEN_TEST_SUBCONSTITUENCY_NAME', '')
        subconstituency_name = subconstituency_name.decode('utf-8')

        if not subconstituency_name:
            subconstituency_name = generate_arabic_place_name()

        center_name = os.environ.get('ROLLGEN_TEST_CENTER_NAME', '')
        center_name = center_name.decode('utf-8')

        if not center_name:
            center_name = generate_arabic_place_name()

        subconstituency = SubConstituencyFactory(name_arabic=subconstituency_name)

        self.center = RegistrationCenterFactory(subconstituency=subconstituency, name=center_name)

        # For the center that has copies, I give it the max number of copies possible in order
        # to force the 'copied by' string to be as long as possible to reveal any line wrapping
        # problems that result.
        self.original_center = RegistrationCenterFactory()
        self.copy_centers = RegistrationCenterFactory.create_batch(settings.N_MAX_COPY_CENTERS,
                                                                   copy_of=self.original_center)

        self.election = ElectionFactory()
Ejemplo n.º 6
0
    def setUp(self):
        self.election = ElectionFactory()

        self.center = RegistrationCenterFactory(name=generate_arabic_place_name())
        self.office_id = self.center.office.id

        # Create a bunch of voters registered at each of these centers. The number of voters
        # matters somewhat.
        # station_distributor() will create a unisex station under certain conditions if
        # there are < N male or female voters, where N = UNISEX_TRIGGER (currently 25). The
        # names of the generated PDFs (which this code tests) have the gender embedded, so if I
        # change the # of voters and that causes a unisex station to be created, the filenames of
        # the generated PDFs will be different than these tests expect so the tests will fail.
        # I use a number of voters that guarantees I won't create a unisex station.
        n_voters = (settings.ROLLGEN_UNISEX_TRIGGER * 2) + 2

        self.voters = create_voters(n_voters, center=self.center)

        self.password = '******'
        self.user = UserFactory(password=self.password)

        # Each test gets a fresh work dir.
        self.output_path = tempfile.mkdtemp()
        self.input_arguments = INPUT_ARGUMENTS_TEMPLATE.copy()
        self.input_arguments['center_ids'] = [self.center.center_id]
Ejemplo n.º 7
0
 def setUp(self):
     self.NUMBER = get_random_phone_number()
     # Most tests need the number whitelisted, so whitelist by default
     WhitelistFactory(phone_number=self.NUMBER)
     self.election = ElectionFactory(
         polling_start_time=now() - timedelta(hours=1),
         polling_end_time=now() + timedelta(hours=1),
     )
Ejemplo n.º 8
0
 def setUp(self):
     # lookup_connections takes any identity and creates connections.
     # It's better than create_connection because it uses 'mockbackend'
     # which keeps track of sent messages.
     self.conn = self.lookup_connections(identities=['111'])[0]
     self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
     self.good_center_id = get_random_number_string(length=constants.CENTER_ID_LENGTH)
     self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
     self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
     self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)
Ejemplo n.º 9
0
 def setUp(self):
     self.url = reverse('check_registration')
     self.user = UserFactory(username='******', password='******')
     self.client.login(username='******', password='******')
     # captcha has 2 form fields, _0 is a key, _1 is the text entered by the user
     self.captcha = {'captcha_0': 'dummy', 'captcha_1': 'PASSED'}
     self.registration = RegistrationPeriodFactory(start_time=PAST_DAY,
                                                   end_time=PAST_DAY)
     self.election = ElectionFactory(polling_start_time=FUTURE_DAY,
                                     polling_end_time=FUTURE_DAY)
Ejemplo n.º 10
0
 def setUp(self):
     super(PrelimVoteReportTestPhoneActivated, self).setUp()
     self.center = RegistrationCenterFactory()
     # Activate the phone to the center:
     StaffPhone.objects.create(phone_number=self.NUMBER,
                               registration_center=self.center)
     self.election = ElectionFactory(
         polling_start_time=now() - timedelta(hours=2),
         polling_end_time=now() + timedelta(hours=2),
     )
Ejemplo n.º 11
0
class QueryDuringRegistration(LibyaRapidTest):
    """
    Voter query should work any time.
    """
    def setUp(self):
        self.conn = self.lookup_connections(identities='111')[0]
        self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
        self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
        self.msg = u"%s" % (self.good_nid)
        self.election = ElectionFactory(polling_start_time=PAST_DAY,
                                        polling_end_time=FUTURE_DAY)

    def test_query_before_reg_opens(self, mock_lookup):
        RegistrationPeriodFactory(start_time=FUTURE_DAY, end_time=FUTURE_DAY)
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)

    def test_query_during_reg(self, mock_lookup):
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
        mock_lookup.return_value = Result('1', constants.VOTER_QUERY_NOT_FOUND)
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)

    def test_query_after_reg_closes(self, mock_lookup):
        # after reg closes but before polling is over
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        mock_lookup.return_value = Result('1', constants.VOTER_QUERY_NOT_FOUND)
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)

    def test_query_after_polling(self, mock_lookup):
        # after polling is over, voters can still check their registrations
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)
Ejemplo n.º 12
0
class QueryDuringRegistration(LibyaRapidTest):
    """
    Voter query should work any time.
    """

    def setUp(self):
        self.conn = self.lookup_connections(identities='111')[0]
        self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
        self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
        self.msg = u"%s" % (self.good_nid)
        self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)

    def test_query_before_reg_opens(self, mock_lookup):
        RegistrationPeriodFactory(start_time=FUTURE_DAY, end_time=FUTURE_DAY)
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)

    def test_query_during_reg(self, mock_lookup):
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
        mock_lookup.return_value = Result('1', constants.VOTER_QUERY_NOT_FOUND)
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)

    def test_query_after_reg_closes(self, mock_lookup):
        # after reg closes but before polling is over
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        mock_lookup.return_value = Result('1', constants.VOTER_QUERY_NOT_FOUND)
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)

    def test_query_after_polling(self, mock_lookup):
        # after polling is over, voters can still check their registrations
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        self.receive(self.msg, self.conn, fields=self.fields)
        self.assertTrue(mock_lookup.called)
Ejemplo n.º 13
0
 def test_after_election(self, processor):
     # can still query registration after election
     RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
     ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=PAST_DAY)
     io_table = [
         (self.garbage, constants.REGISTRATION_NOT_OPEN),
         (unicode(self.bad_nid), constants.VOTER_QUERY_NID_WRONG_LENGTH),
         (unicode(self.good_nid), constants.VOTER_QUERY_REGISTERED_AT),
     ]
     result = Mock(message="success",
                   message_code=constants.VOTER_QUERY_REGISTERED_AT)
     processor.return_value = result
     for incoming_message, expected_code in io_table:
         self.receive(incoming_message, self.conn, fields=self.fields)
         self.assertEqual(self.get_last_response_code(), expected_code)
Ejemplo n.º 14
0
    def setUp(self):
        super(TestPollingCSVs, self).setUp()
        # Jam a comma in one of the fields that appears in the CSV to exercise the code's
        # ability to escape the delimiter correctly.
        self.center.name = ',' + self.center.name
        self.center.save()
        job = Job('polling', [self.center], self.input_arguments, self.user.username,
                  self.output_path)
        job.generate_rolls()

        # Create a station related to an older election in a (hopefully unsuccessful) attempt to
        # confuse the code that creates the polling metadata CSV.
        start = django_now()
        start = start.replace(year=start.year - 1)
        end = start.replace(year=start.year - 1) + datetime.timedelta(days=1)
        old_election = ElectionFactory(polling_start_time=start, polling_end_time=end)
        old_center = RegistrationCenterFactory()
        Station(election=old_election, center=old_center, number=1, gender=FEMALE,
                n_registrants=42, first_voter_name='first', first_voter_number=1,
                last_voter_name='last', last_voter_number=42)
Ejemplo n.º 15
0
 def test_dont_get_deleted_election_by_default(self):
     election = ElectionFactory(deleted=True)
     self.assertNotIn(election, Election.objects.all())
Ejemplo n.º 16
0
class HandlerTest(LibyaRapidTest):
    def setUp(self):
        # lookup_connections takes any identity and creates connections.
        # It's better than create_connection because it uses 'mockbackend'
        # which keeps track of sent messages.
        self.conn = self.lookup_connections(identities=['111'])[0]
        self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
        self.good_center_id = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
        self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
        self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)

    def test_new_logic_rename_me(self):
        phone1 = get_random_number_string(length=10)
        phone2 = get_random_number_string(length=10)
        nid1 = self.good_nid
        ppc1 = self.good_center_id
        ppc2 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        ppc3 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        ppc4 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        ppc5 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        CitizenFactory(national_id=nid1)
        RegistrationCenterFactory(center_id=ppc1)
        RegistrationCenterFactory(center_id=ppc2)
        RegistrationCenterFactory(center_id=ppc3)
        RegistrationCenterFactory(center_id=ppc4)
        RegistrationCenterFactory(center_id=ppc5)
        # Each item in the test_data array is one test.
        # Each test contains one or more steps.
        # Each step contains the phone we receive a message from, the
        # registration center code in that message, the expected response,
        # and the expected registration state after that message.
        # All messages are for the same NID.
        # After each test item, the registrations are reset (deleted).

        # MSG1: you are registered, use same phone to change
        # MSG4: only one more time
        # MSG5: that was your last time

        test_data = [
            # Repeat the same registration from the same phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
            ],
            # Keep trying to change your registration from the same phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc2, constants.MESSAGE_1, ppc2),  # one change is okay
                (phone1, ppc3, constants.MESSAGE_4, ppc3),  # twice is okay but only one left
                (phone1, ppc4, constants.MESSAGE_5, ppc4),  # three is okay but last time
                (phone1, ppc3, constants.MESSAGE_6, ppc4),  # too many, sorry
                (phone1, ppc5, constants.MESSAGE_6, ppc4),  # still too many
            ],
            # Repeat the same registration from a different phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc1, constants.MESSAGE_7, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc1, constants.MESSAGE_7, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc1, constants.MESSAGE_7, ppc1),
            ],
            # Try to change registration from a different phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc2, constants.MESSAGE_2, ppc1),  # sorry charlie
                # then from the original phone
                (phone1, ppc2, constants.MESSAGE_1, ppc2),  # that's ok - change 1
                # again from another phone
                (phone2, ppc3, constants.MESSAGE_2, ppc2),
                # back to original phone
                (phone1, ppc3, constants.MESSAGE_4, ppc3),  # change 2 - 1 left
                # try other phone again
                (phone2, ppc4, constants.MESSAGE_2, ppc3),
                # original phone again
                (phone1, ppc2, constants.MESSAGE_5, ppc2),  # 3rd change is the last
                (phone1, ppc4, constants.MESSAGE_6, ppc2),  # too many, sorry
                (phone1, ppc5, constants.MESSAGE_6, ppc2),  # still too many
                # Once you've used up your changes, even sending your current
                # registration results in message 6
                (phone1, ppc2, constants.MESSAGE_6, ppc2),
            ],
            # After changing the registration, the repeat count is reset
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),  # 2nd time - msg 1
                (phone1, ppc1, constants.MESSAGE_1, ppc1),  # 3rd time - msg 1 (enhanced)
                (phone1, ppc2, constants.MESSAGE_1, ppc2),   # change #1 reg - reset counter
                (phone1, ppc2, constants.MESSAGE_1, ppc2),  # 2nd time, same data as #1 change
                (phone1, ppc2, constants.MESSAGE_1, ppc2),  # 3rd time, same data as #1 change
                (phone1, ppc3, constants.MESSAGE_4, ppc3),   # change reg - reset counter
                (phone1, ppc2, constants.MESSAGE_5, ppc2),  # final change
                (phone1, ppc2, constants.MESSAGE_6, ppc2),   # no more changes, always 6
            ],
        ]

        for one_test in test_data:
            # Reset state
            Registration.objects.unfiltered().delete()
            for from_phone, center_id, expected_response, expected_center_id in one_test:
                text = "%s*%s" % (nid1, center_id)
                conn = self.lookup_connections(identities=[from_phone])[0]
                self.receive(text, conn, fields=self.fields)

                # Check the response
                self.assertEqual(expected_response, self.get_last_response_code())
                # Check the state
                reg = Registration.objects.get(citizen__national_id=nid1)
                self.assertEqual(int(expected_center_id), reg.registration_center.center_id)

    def test_input_triggers_proper_response(self):
        short_center_id = u'%s*%s' % (
            self.good_nid, get_random_number_string(length=constants.CENTER_ID_LENGTH - 1))
        long_center_id = u'%s*%s' % (
            self.good_nid, get_random_number_string(length=constants.CENTER_ID_LENGTH + 1))
        short_nid = u"%s*%s" % (
            get_random_number_string(length=constants.NID_LENGTH - 1), self.good_center_id)
        long_nid = u"%s*%s" % (
            get_random_number_string(length=constants.NID_LENGTH + 1), self.good_center_id)
        three_ids = u"%s*%s*123" % (self.good_nid, self.good_center_id)
        io_table = [
            (u"garbage", constants.MESSAGE_INCORRECT),
            (get_random_number_string(), constants.VOTER_QUERY_NID_WRONG_LENGTH),
            (short_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH),
            (long_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH),
            (short_nid, constants.RESPONSE_NID_WRONG_LENGTH),
            (long_nid, constants.RESPONSE_NID_WRONG_LENGTH),
            (three_ids, constants.MESSAGE_INCORRECT),
        ]
        # send the messages
        for (input, _) in io_table:
            self.receive(input, self.conn, fields=self.fields)
        # strip out our split messages
        outputs = [o.fields['message_code'] for o in self.outbound if not o.fields.get('split')]
        for (i, (_, expected_output)) in enumerate(io_table):
            self.assertEqual(outputs[i], expected_output)

    def test_unexpected_error(self):
        with patch.object(PatternHandler, 'dispatch') as dispatch:
            dispatch.side_effect = ValueError
            self.receive("Anything", self.conn, fields=self.fields)
        self.assertEqual(self.outbound[0].fields['message_code'],
                         constants.RESPONSE_SERVER_ERROR)

    @patch('register.handlers.process_registration_request', autospec=True)
    def test_valid_nid(self, mock_prr):
        center_name = u"A Random Center"
        person_name = u"A Random Name"
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        mock_prr.return_value = Result('', constants.RESPONSE_VALID_REGISTRATION,
                                       dict(person=person_name,
                                            centre=center_name,
                                            code=int(self.good_center_id)))
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.outbound[0].fields['message_code'],
                         constants.RESPONSE_VALID_REGISTRATION)
        # message was saved
        sms = SMS.objects.get(message=msg)
        self.assertEqual(SMS.REGISTRATION, sms.msg_type)
        # response was saved
        sms = SMS.objects.filter(to_number=self.conn.identity)
        self.assertNotEqual(sms.count(), 0)

    @patch('register.processors.process_registration_request', autospec=True)
    def test_invalid_center_id(self, mock_prr):
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        mock_prr.return_value = Result('', constants.RESPONSE_CENTER_ID_INVALID)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(), constants.RESPONSE_CENTER_ID_INVALID)

    @patch('register.handlers.registration_allowed')
    def test_outside_registration_period(self, mock_is_open):
        mock_is_open.return_value = False
        RegistrationCenterFactory(center_id=self.good_center_id)
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN)

    def test_not_started(self):
        self.reg_period.start_time = FUTURE_DAY
        self.reg_period.save()
        RegistrationCenterFactory(center_id=self.good_center_id)
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN)

    def test_has_ended(self):
        self.reg_period.end_time = PAST_DAY
        self.reg_period.save()
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationCenterFactory(center_id=self.good_center_id)
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN)

    def test_we_only_handle_our_shortcode(self):
        msg = u"garbage"
        not_our_shortcode = '11111'
        self.receive(msg, self.conn, fields={'to_addr': not_our_shortcode})
        # We do send a default response, but we test that more below.
        self.assertEqual(1, len(self.full_outbound()))

    def test_that_we_save_incoming_sms_when_closed(self):
        self.reg_period.start_time = FUTURE_DAY
        self.reg_period.save()
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        msg = u"garbage"
        for shortcode in set((settings.REGISTRATION_SHORT_CODE,
                              settings.VOTER_QUERY_SHORT_CODE, settings.REPORTS_SHORT_CODE)):
            self.receive(msg, self.conn, fields={'to_addr': shortcode})
            # test that we save the incoming SMS
            incoming = SMS.objects.filter(to_number=shortcode)
            self.assertEqual(len(incoming), 1)
Ejemplo n.º 17
0
 def setUp(self):
     # Need a superuser
     get_user_model().objects.create_superuser(username="******",
                                               email="*****@*****.**",
                                               password="******")
     self.election = ElectionFactory()
Ejemplo n.º 18
0
def get_or_create_election(stub):
    """Return a current election if one exists, or create a new one using ElectionFactory"""
    election = Election.objects.get_most_current_election()
    return election if election else ElectionFactory()
Ejemplo n.º 19
0
    def setUp(self):
        self.staff_user = UserFactory()
        self.staff_user.is_staff = True
        self.staff_user.save()
        assert self.client.login(username=self.staff_user.username,
                                 password=DEFAULT_USER_PASSWORD)
        self.reporting_user = test_reports.TEST_USERNAME
        self.reporting_password = test_reports.TEST_PASSWORD
        REPORT_USER_DB[self.reporting_user] = self.reporting_password
        # Pick a start time that represents different days in Libya vs UTC
        tz = timezone(settings.TIME_ZONE)
        polling_start_time = astz(FUTURE_DAY.replace(hour=22), tz)
        polling_end_time = tz.normalize(polling_start_time +
                                        timedelta(hours=16))
        self.election = ElectionFactory(
            polling_start_time=polling_start_time,
            polling_end_time=polling_end_time,
        )
        self.election_day_dt = self.election.polling_start_time
        # Create "decoy" election just to confirm that it doesn't break reports.
        decoy_start_time = tz.normalize(polling_start_time -
                                        timedelta(days=10))
        decoy_end_time = tz.normalize(decoy_start_time + timedelta(hours=16))
        ElectionFactory(
            polling_start_time=decoy_start_time,
            polling_end_time=decoy_end_time,
        )
        self.all_centers = []
        self.rc_1 = RegistrationCenterFactory()
        self.all_centers.append(self.rc_1)
        self.rc_2 = RegistrationCenterFactory()
        self.all_centers.append(self.rc_2)
        self.rc_3 = RegistrationCenterFactory()
        self.all_centers.append(self.rc_3)
        self.rc_4 = RegistrationCenterFactory()
        self.all_centers.append(self.rc_4)
        self.copy_of_rc_1 = RegistrationCenterFactory(copy_of=self.rc_1,
                                                      office=self.rc_1.office)
        self.all_centers.append(self.copy_of_rc_1)
        # rc_5 is inactive for this election
        self.rc_5 = RegistrationCenterFactory(office=self.rc_1.office)
        self.all_centers.append(self.rc_5)
        inactive_on_election = CenterClosedForElection(
            registration_center=self.rc_5, election=self.election)
        inactive_on_election.full_clean()
        inactive_on_election.save()
        self.all_office_ids = [center.office_id for center in self.all_centers]
        self.carrier_1 = BackendFactory()
        self.citizen_1 = CitizenFactory()

        # Create registrations on the 4 days leading up to election day
        # Put the registrations at different hours of the day to stress TZ handling.
        self.registration_dates = []
        self.registration_date_strs = []
        hour_of_day = 0
        for delta_days in range(10, 4, -1):
            assert hour_of_day < 24
            reg_date = astz(self.election_day_dt - timedelta(days=delta_days), tz)\
                .replace(hour=hour_of_day)
            hour_of_day += 4
            self.registration_dates.append(reg_date)
            self.registration_date_strs.append(reg_date.strftime('%Y-%m-%d'))
        self.yesterday_date, _ = calc_yesterday(self.registration_date_strs)
        self.yesterday_date_dm = self.yesterday_date.strftime('%d/%m')
        # yesterday_date is a date; get a datetime form
        self.yesterday_date_dt = tz.localize(
            datetime(self.yesterday_date.year, self.yesterday_date.month,
                     self.yesterday_date.day, 0, 0, 0))
        self.staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % 12345
Ejemplo n.º 20
0
class HandlerTest(LibyaRapidTest):
    def setUp(self):
        # lookup_connections takes any identity and creates connections.
        # It's better than create_connection because it uses 'mockbackend'
        # which keeps track of sent messages.
        self.conn = self.lookup_connections(identities=['111'])[0]
        self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
        self.good_center_id = get_random_number_string(
            length=constants.CENTER_ID_LENGTH)
        self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
        self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY,
                                                    end_time=FUTURE_DAY)
        self.election = ElectionFactory(polling_start_time=PAST_DAY,
                                        polling_end_time=FUTURE_DAY)

    def test_new_logic_rename_me(self):
        phone1 = get_random_number_string(length=10)
        phone2 = get_random_number_string(length=10)
        nid1 = self.good_nid
        ppc1 = self.good_center_id
        ppc2 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        ppc3 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        ppc4 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        ppc5 = get_random_number_string(length=constants.CENTER_ID_LENGTH)
        CitizenFactory(national_id=nid1)
        RegistrationCenterFactory(center_id=ppc1)
        RegistrationCenterFactory(center_id=ppc2)
        RegistrationCenterFactory(center_id=ppc3)
        RegistrationCenterFactory(center_id=ppc4)
        RegistrationCenterFactory(center_id=ppc5)
        # Each item in the test_data array is one test.
        # Each test contains one or more steps.
        # Each step contains the phone we receive a message from, the
        # registration center code in that message, the expected response,
        # and the expected registration state after that message.
        # All messages are for the same NID.
        # After each test item, the registrations are reset (deleted).

        # MSG1: you are registered, use same phone to change
        # MSG4: only one more time
        # MSG5: that was your last time

        test_data = [
            # Repeat the same registration from the same phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
            ],
            # Keep trying to change your registration from the same phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc2, constants.MESSAGE_1,
                 ppc2),  # one change is okay
                (phone1, ppc3, constants.MESSAGE_4,
                 ppc3),  # twice is okay but only one left
                (phone1, ppc4, constants.MESSAGE_5,
                 ppc4),  # three is okay but last time
                (phone1, ppc3, constants.MESSAGE_6, ppc4),  # too many, sorry
                (phone1, ppc5, constants.MESSAGE_6, ppc4),  # still too many
            ],
            # Repeat the same registration from a different phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc1, constants.MESSAGE_7, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc1, constants.MESSAGE_7, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc1, constants.MESSAGE_7, ppc1),
            ],
            # Try to change registration from a different phone
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone2, ppc2, constants.MESSAGE_2, ppc1),  # sorry charlie
                # then from the original phone
                (phone1, ppc2, constants.MESSAGE_1, ppc2
                 ),  # that's ok - change 1
                # again from another phone
                (phone2, ppc3, constants.MESSAGE_2, ppc2),
                # back to original phone
                (phone1, ppc3, constants.MESSAGE_4, ppc3),  # change 2 - 1 left
                # try other phone again
                (phone2, ppc4, constants.MESSAGE_2, ppc3),
                # original phone again
                (phone1, ppc2, constants.MESSAGE_5, ppc2
                 ),  # 3rd change is the last
                (phone1, ppc4, constants.MESSAGE_6, ppc2),  # too many, sorry
                (phone1, ppc5, constants.MESSAGE_6, ppc2),  # still too many
                # Once you've used up your changes, even sending your current
                # registration results in message 6
                (phone1, ppc2, constants.MESSAGE_6, ppc2),
            ],
            # After changing the registration, the repeat count is reset
            [
                (phone1, ppc1, constants.MESSAGE_1, ppc1),
                (phone1, ppc1, constants.MESSAGE_1, ppc1),  # 2nd time - msg 1
                (phone1, ppc1, constants.MESSAGE_1,
                 ppc1),  # 3rd time - msg 1 (enhanced)
                (phone1, ppc2, constants.MESSAGE_1,
                 ppc2),  # change #1 reg - reset counter
                (phone1, ppc2, constants.MESSAGE_1,
                 ppc2),  # 2nd time, same data as #1 change
                (phone1, ppc2, constants.MESSAGE_1,
                 ppc2),  # 3rd time, same data as #1 change
                (phone1, ppc3, constants.MESSAGE_4,
                 ppc3),  # change reg - reset counter
                (phone1, ppc2, constants.MESSAGE_5, ppc2),  # final change
                (phone1, ppc2, constants.MESSAGE_6,
                 ppc2),  # no more changes, always 6
            ],
        ]

        for one_test in test_data:
            # Reset state
            Registration.objects.unfiltered().delete()
            for from_phone, center_id, expected_response, expected_center_id in one_test:
                text = "%s*%s" % (nid1, center_id)
                conn = self.lookup_connections(identities=[from_phone])[0]
                self.receive(text, conn, fields=self.fields)

                # Check the response
                self.assertEqual(expected_response,
                                 self.get_last_response_code())
                # Check the state
                reg = Registration.objects.get(citizen__national_id=nid1)
                self.assertEqual(int(expected_center_id),
                                 reg.registration_center.center_id)

    def test_input_triggers_proper_response(self):
        short_center_id = u'%s*%s' % (
            self.good_nid,
            get_random_number_string(length=constants.CENTER_ID_LENGTH - 1))
        long_center_id = u'%s*%s' % (
            self.good_nid,
            get_random_number_string(length=constants.CENTER_ID_LENGTH + 1))
        short_nid = u"%s*%s" % (get_random_number_string(
            length=constants.NID_LENGTH - 1), self.good_center_id)
        long_nid = u"%s*%s" % (get_random_number_string(
            length=constants.NID_LENGTH + 1), self.good_center_id)
        three_ids = u"%s*%s*123" % (self.good_nid, self.good_center_id)
        io_table = [
            (u"garbage", constants.MESSAGE_INCORRECT),
            (get_random_number_string(),
             constants.VOTER_QUERY_NID_WRONG_LENGTH),
            (short_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH),
            (long_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH),
            (short_nid, constants.RESPONSE_NID_WRONG_LENGTH),
            (long_nid, constants.RESPONSE_NID_WRONG_LENGTH),
            (three_ids, constants.MESSAGE_INCORRECT),
        ]
        # send the messages
        for (input, _) in io_table:
            self.receive(input, self.conn, fields=self.fields)
        # strip out our split messages
        outputs = [
            o.fields['message_code'] for o in self.outbound
            if not o.fields.get('split')
        ]
        for (i, (_, expected_output)) in enumerate(io_table):
            self.assertEqual(outputs[i], expected_output)

    def test_unexpected_error(self):
        with patch.object(PatternHandler, 'dispatch') as dispatch:
            dispatch.side_effect = ValueError
            self.receive("Anything", self.conn, fields=self.fields)
        self.assertEqual(self.outbound[0].fields['message_code'],
                         constants.RESPONSE_SERVER_ERROR)

    @patch('register.handlers.process_registration_request', autospec=True)
    def test_valid_nid(self, mock_prr):
        center_name = u"A Random Center"
        person_name = u"A Random Name"
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        mock_prr.return_value = Result(
            '', constants.RESPONSE_VALID_REGISTRATION,
            dict(person=person_name,
                 centre=center_name,
                 code=int(self.good_center_id)))
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.outbound[0].fields['message_code'],
                         constants.RESPONSE_VALID_REGISTRATION)
        # message was saved
        sms = SMS.objects.get(message=msg)
        self.assertEqual(SMS.REGISTRATION, sms.msg_type)
        # response was saved
        sms = SMS.objects.filter(to_number=self.conn.identity)
        self.assertNotEqual(sms.count(), 0)

    @patch('register.processors.process_registration_request', autospec=True)
    def test_invalid_center_id(self, mock_prr):
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        mock_prr.return_value = Result('',
                                       constants.RESPONSE_CENTER_ID_INVALID)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(),
                         constants.RESPONSE_CENTER_ID_INVALID)

    @patch('register.handlers.registration_allowed')
    def test_outside_registration_period(self, mock_is_open):
        mock_is_open.return_value = False
        RegistrationCenterFactory(center_id=self.good_center_id)
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(),
                         constants.REGISTRATION_NOT_OPEN)

    def test_not_started(self):
        self.reg_period.start_time = FUTURE_DAY
        self.reg_period.save()
        RegistrationCenterFactory(center_id=self.good_center_id)
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(),
                         constants.REGISTRATION_NOT_OPEN)

    def test_has_ended(self):
        self.reg_period.end_time = PAST_DAY
        self.reg_period.save()
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationCenterFactory(center_id=self.good_center_id)
        msg = u"%s*%s" % (self.good_nid, self.good_center_id)
        self.receive(msg, self.conn, fields=self.fields)
        self.assertEqual(self.get_last_response_code(),
                         constants.REGISTRATION_NOT_OPEN)

    def test_we_only_handle_our_shortcode(self):
        msg = u"garbage"
        not_our_shortcode = '11111'
        self.receive(msg, self.conn, fields={'to_addr': not_our_shortcode})
        # We do send a default response, but we test that more below.
        self.assertEqual(1, len(self.full_outbound()))

    def test_that_we_save_incoming_sms_when_closed(self):
        self.reg_period.start_time = FUTURE_DAY
        self.reg_period.save()
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        msg = u"garbage"
        for shortcode in set(
            (settings.REGISTRATION_SHORT_CODE, settings.VOTER_QUERY_SHORT_CODE,
             settings.REPORTS_SHORT_CODE)):
            self.receive(msg, self.conn, fields={'to_addr': shortcode})
            # test that we save the incoming SMS
            incoming = SMS.objects.filter(to_number=shortcode)
            self.assertEqual(len(incoming), 1)
Ejemplo n.º 21
0
 def setUp(self):
     # Default to polling in progress
     self.election = ElectionFactory(polling_start_time=PAST_DAY,
                                     polling_end_time=FUTURE_DAY)
Ejemplo n.º 22
0
def create(center_without_office=False,
           num_copy_centers=DEFAULT_NUM_COPY_CENTERS,
           num_registrations=DEFAULT_NUM_REGISTRATIONS,
           num_registration_dates=DEFAULT_NUM_REGISTRATION_DATES,
           num_daily_reports=DEFAULT_NUM_DAILY_REPORTS,
           num_registration_centers=DEFAULT_NUM_REGISTRATION_CENTERS,
           num_subconstituencies=DEFAULT_NUM_SUBCONSTITUENCIES,
           use_existing_infra=False,
           num_inactive_centers_per_election=DEFAULT_NUM_INACTIVE_PER_ELECTION,
           num_no_reg_centers=DEFAULT_NUM_NO_REG_CENTERS,
           election_dates=()):
    assert settings.ENVIRONMENT not in ('production', 'testing')
    delete(delete_infra=not use_existing_infra)
    empty_report_store()  # Remove any old data from Redis

    # Figure out ~10% of "normal" centers...
    fraction_of_normal_centers = \
        max(1, int(0.1 * num_registration_centers)) if num_registration_centers else 0

    # If numbers of some weird center types weren't specified, use a small
    # fraction of normal centers.
    if num_copy_centers == DEFAULT_NUM_COPY_CENTERS:
        num_copy_centers = fraction_of_normal_centers
    if num_no_reg_centers == DEFAULT_NUM_NO_REG_CENTERS:
        num_no_reg_centers = fraction_of_normal_centers

    carrier = BackendFactory()

    if election_dates:
        elections = [
            ElectionFactory(polling_start_time=election_date.replace(hour=8),
                            polling_end_time=election_date.replace(hour=20))
            for election_date in election_dates
        ]
    else:
        election_date = PAST_DAY.replace(hour=8, microsecond=123456)
        election = ElectionFactory(
            polling_start_time=election_date,
            polling_end_time=election_date.replace(hour=20))
        elections = (election, )

    if not use_existing_infra:
        OfficeFactory()
        ConstituencyFactory(name_english='first')
        SubConstituencyFactory(name_english='Benghazi')

    offices = Office.objects.all()
    copy_centers = []
    no_reg_centers = []
    staff_phones = []

    if use_existing_infra:
        # Pick centers that support registrations at random.
        centers = RegistrationCenter.objects.filter(reg_open=True)\
            .exclude(center_type=RegistrationCenter.Types.COPY)\
            .order_by('?')[:num_registration_centers]
        if num_copy_centers:  # user wants some, but there might not be any
            copy_centers = RegistrationCenter.objects.\
                filter(reg_open=True, center_type=RegistrationCenter.Types.COPY)\
                .order_by('?')[:num_copy_centers]
        if num_no_reg_centers:  # user wants some, but there might not be any
            no_reg_centers = RegistrationCenter.objects.\
                filter(reg_open=False).order_by('?')[:num_no_reg_centers]
        # why like this? sliced queries and/or list
        all_kinds_of_centers = \
            list(centers) + list(copy_centers) + list(no_reg_centers)
    else:
        subconstituencies = SubConstituency.objects.exclude(
            pk=SPLIT_CENTER_SUBCONSTITUENCY_ID)
        subconstituencies = subconstituencies[:num_subconstituencies]

        centers = []
        for i in range(num_registration_centers):
            constituency = Constituency.objects.filter(name_english='first')[0]
            subconstituency = random.choice(subconstituencies)

            rc = RegistrationCenter(name='polling-center-%d' % i,
                                    center_id=CENTER_ID_MIN_INT_VALUE + i,
                                    constituency=constituency,
                                    subconstituency=subconstituency,
                                    office=random.choice(offices))
            rc.full_clean()
            rc.save()
            centers.append(rc)

        for i in range(num_copy_centers):
            original = random.choice(centers)
            # XXX This doesn't handle accidentally making too many copies of the same
            #     center, so make sure --num-centers is "big enough" w.r.t. --num-copy-centers.
            new_center_id = CENTER_ID_MIN_INT_VALUE + num_registration_centers + i
            copy = RegistrationCenter(
                name='Copy of %s' % original.name,
                center_id=new_center_id,
                constituency=original.constituency,
                subconstituency=original.subconstituency,
                office=original.office,
                center_type=RegistrationCenter.Types.COPY,
                copy_of=original)
            copy.full_clean()
            copy.save()
            copy_centers.append(copy)

        for i in range(num_no_reg_centers):
            constituency = Constituency.objects.filter(name_english='first')[0]
            subconstituency = random.choice(subconstituencies)
            center_id = CENTER_ID_MIN_INT_VALUE + num_registration_centers + num_copy_centers + i
            rc = RegistrationCenter(name='no-reg-polling-center-%d' % i,
                                    center_id=center_id,
                                    constituency=constituency,
                                    subconstituency=subconstituency,
                                    office=random.choice(offices),
                                    reg_open=False)
            rc.full_clean()
            rc.save()

        all_kinds_of_centers = centers + copy_centers + no_reg_centers

    if center_without_office:
        try:
            # by not specifying office and other infra, it will be "standalone"
            rc = RegistrationCenter(name='dummy-registration-center',
                                    center_id=UNUSED_CENTER_ID)
            rc.full_clean()
            rc.save()
        except ValidationError:
            pass  # assume that it already exists

    for election in elections:
        num_daily_reports_on_election_day = int(round(0.9 * num_daily_reports))
        centers_reported = set()
        for i in range(num_daily_reports_on_election_day):
            staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % i
            from_center = random.choice(all_kinds_of_centers)
            ensure_staff_phone_exists(
                staff_phone_number, from_center, staff_phones,
                election.work_start_time + datetime.timedelta(minutes=5))

            # split votes between two options
            number_of_votes = (random.randint(1, 100), random.randint(1, 100))
            random_period_number = random.randint(FIRST_PERIOD_NUMBER,
                                                  LAST_PERIOD_NUMBER)
            pr = PollingReport(election=election,
                               phone_number=staff_phone_number,
                               registration_center=from_center,
                               period_number=random_period_number,
                               num_voters=sum(number_of_votes),
                               creation_date=election.polling_start_time)
            pr.full_clean()
            pr.save()
            s = SMS(from_number=staff_phone_number,
                    to_number=POLLING_REPORT_PHONE_NUMBER,
                    direction=INCOMING,
                    message='my message',
                    msg_type=SMS.POLLING_REPORT,
                    message_code=MESSAGE_1,
                    carrier=carrier,
                    creation_date=election.polling_start_time)
            s.full_clean()
            s.save()

            if from_center in centers_reported:
                continue  # can't send but one PreliminaryVoteCount from a center

            # send a corresponding vote count
            for option, votes_for_option in enumerate(number_of_votes,
                                                      start=1):
                pvc = PreliminaryVoteCount(
                    election=election,
                    phone_number=staff_phone_number,
                    registration_center=from_center,
                    option=option,
                    num_votes=votes_for_option,
                    creation_date=election.polling_start_time)
                pvc.full_clean()
                pvc.save()
                s = SMS(
                    from_number=staff_phone_number,
                    to_number=PRELIMINARY_VOTE_COUNT_PHONE_NUMBER,
                    # XXX no specific message type for PreliminaryVoteCount
                    direction=INCOMING,
                    message='my message',
                    msg_type=SMS.POLLING_REPORT,
                    message_code=MESSAGE_1,
                    carrier=carrier,
                    creation_date=election.polling_start_time)
                s.full_clean()
                s.save()

            centers_reported.add(from_center)

        # some daily reports on the day after
        for i in range(num_daily_reports - num_daily_reports_on_election_day):
            staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % i
            rc = random.choice(all_kinds_of_centers)
            ensure_staff_phone_exists(
                staff_phone_number, rc, staff_phones,
                election.work_start_time + datetime.timedelta(minutes=5))
            report_creation_date = election.polling_start_time + datetime.timedelta(
                days=1)
            pr = PollingReport(
                election=election,
                phone_number=staff_phone_number,
                registration_center=rc,
                period_number=
                LAST_PERIOD_NUMBER,  # day after counts as last period
                num_voters=random.randint(1, 50),
                creation_date=report_creation_date)
            pr.full_clean()
            pr.save()
            s = SMS(from_number=staff_phone_number,
                    to_number=POLLING_REPORT_PHONE_NUMBER,
                    direction=INCOMING,
                    message='my message',
                    msg_type=SMS.POLLING_REPORT,
                    message_code=MESSAGE_1,
                    carrier=carrier,
                    creation_date=election.polling_start_time)
            s.full_clean()
            s.save()

        # Tag some centers as inactive for the election.  We may or may not pick some that
        # sent messages as being inactive.
        num_inactive_centers_per_election = \
            min(num_inactive_centers_per_election, len(all_kinds_of_centers))
        if num_inactive_centers_per_election:
            reordered = all_kinds_of_centers
            random.shuffle(reordered)
            for i in range(num_inactive_centers_per_election):
                inactive_on_election = CenterClosedForElection(
                    registration_center=reordered[i], election=election)
                inactive_on_election.full_clean()
                inactive_on_election.save()

    tz = timezone(settings.TIME_ZONE)
    # construct a datetime that will change based on timezone discrepancies
    # 0-2am in Libya has a different date than the same time in UDT or EDT
    today_fragile = now().astimezone(tz).replace(hour=0, minute=59)

    # tz.normalize fixes up the date arithmetic when crossing DST boundaries
    creation_dates = \
        [tz.normalize((today_fragile -
                       datetime.timedelta(days=DAYS_BETWEEN_REGISTRATIONS * i)).astimezone(tz))
         for i in range(num_registration_dates)]

    citizens = []
    for i in range(num_registrations):
        # about 60% of registrations are for males, just as with actual data
        gender = MALE if random.randint(1, 100) <= 60 else FEMALE
        nat_id = '%d%011d' % (gender, i)

        creation_date = random.choice(creation_dates)
        modification_date = creation_date

        # Select voter ages from 18 years on up.
        voter_age = random.randint(18, 99)
        # If they were a certain age at any time yesterday, they are certainly that age at any time
        # today.
        yesterday = datetime.datetime.now().replace(
            tzinfo=tz) - datetime.timedelta(days=1)
        birth_date = datetime.date(yesterday.year - voter_age, yesterday.month,
                                   yesterday.day)
        civil_registry_id = random.randint(1, 99999999)
        citizen = CitizenFactory(civil_registry_id=civil_registry_id,
                                 national_id=nat_id,
                                 gender=gender,
                                 birth_date=birth_date)
        citizens.append(citizen)
        s = SMS(from_number=VOTER_PHONE_NUMBER_PATTERN % i,
                to_number=REGISTRATION_PHONE_NUMBER,
                citizen=citizen,
                direction=INCOMING,
                message='my reg message',
                msg_type=SMS.REGISTRATION,
                message_code=MESSAGE_1,
                carrier=carrier,
                creation_date=creation_date)
        s.full_clean()
        s.save()

        rc = random.choice(centers)

        confirmed = random.randint(1, 100) <= 80  # most are confirmed
        if confirmed:
            archive_time = None
        else:
            archive_time = random.choice(creation_dates)
        r = Registration(citizen=citizen,
                         registration_center=rc,
                         sms=s,
                         archive_time=archive_time,
                         creation_date=creation_date,
                         modification_date=modification_date)
        r.full_clean()
        r.save()

    if num_registrations:  # if any data being generated
        # generate a variety of sms messages
        for i in range(NUM_RANDOM_SMS_MESSAGES):
            sms_type = random.choice(SMS.MESSAGE_TYPES)[0]
            staff_phone = random.choice(staff_phones)
            s = SMS(from_number=staff_phone.phone_number,
                    to_number=RANDOM_MESSAGE_PHONE_NUMBER,
                    citizen=random.choice(citizens),
                    direction=INCOMING,
                    message='my long random message',
                    msg_type=sms_type,
                    message_code=MESSAGE_1,
                    carrier=carrier,
                    creation_date=random.choice(creation_dates))
            s.full_clean()
            s.save()

        for election in elections:
            for rc in centers:
                i = random.randint(8888, 9999)
                staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % i
                ensure_staff_phone_exists(
                    staff_phone_number, rc, staff_phones,
                    election.work_start_time + datetime.timedelta(minutes=5))
                center_open = CenterOpen(
                    election=election,
                    phone_number=staff_phone_number,
                    registration_center=rc,
                    creation_date=election.polling_start_time.replace(
                        hour=random.randint(0, 10), minute=23))
                center_open.full_clean()
                center_open.save()
                s = SMS(from_number=staff_phone_number,
                        to_number=ACTIVATE_PHONE_NUMBER,
                        direction=INCOMING,
                        message='my message',
                        msg_type=SMS.ACTIVATE,
                        message_code=MESSAGE_1,
                        carrier=carrier,
                        creation_date=election.polling_start_time)
                s.full_clean()
                s.save()
Ejemplo n.º 23
0
 def setUp(self):
     self.conn = self.lookup_connections(identities='111')[0]
     self.good_nid = get_random_number_string(length=constants.NID_LENGTH)
     self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE}
     self.msg = u"%s" % (self.good_nid)
     self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)
Ejemplo n.º 24
0
class PeriodsTest(LibyaTest):
    """
    Match requirements in Phases google spreadsheet:
    https://docs.google.com/a/caktusgroup.com/spreadsheet/ccc?
    key=0ApHYnffwYN6edDJSVmZaeXBqWDZnVk9ReTh6RWEyRWc&usp=drive_web#gid=0
    """
    def setUp(self):
        # Default to polling in progress
        self.election = ElectionFactory(polling_start_time=PAST_DAY,
                                        polling_end_time=FUTURE_DAY)

    def test_before_registration_opens_period(self):
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=FUTURE_DAY, end_time=FUTURE_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_during_registration(self):
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
        self.assertTrue(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_after_registration_before_polling(self):
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_polling_period(self):
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertTrue(polling_reports_enabled())

    def test_post_polling_reporting_period(self):
        self.election.polling_end_time = FIFTEEN_HOURS_AGO
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertTrue(polling_reports_enabled())

    def test_counting_period(self):
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_reopened_reg_period(self):
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_after_reopened_reg_period(self):
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())
Ejemplo n.º 25
0
class PeriodsTest(LibyaTest):
    """
    Match requirements in Phases google spreadsheet:
    https://docs.google.com/a/caktusgroup.com/spreadsheet/ccc?
    key=0ApHYnffwYN6edDJSVmZaeXBqWDZnVk9ReTh6RWEyRWc&usp=drive_web#gid=0
    """

    def setUp(self):
        # Default to polling in progress
        self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)

    def test_before_registration_opens_period(self):
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=FUTURE_DAY, end_time=FUTURE_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_during_registration(self):
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
        self.assertTrue(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_after_registration_before_polling(self):
        self.election.polling_start_time = FUTURE_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_polling_period(self):
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertTrue(polling_reports_enabled())

    def test_post_polling_reporting_period(self):
        self.election.polling_end_time = FIFTEEN_HOURS_AGO
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertTrue(polling_reports_enabled())

    def test_counting_period(self):
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_reopened_reg_period(self):
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())

    def test_after_reopened_reg_period(self):
        self.election.polling_end_time = PAST_DAY
        self.election.save()
        RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY)
        self.assertFalse(tool_1_enabled())
        self.assertFalse(polling_reports_enabled())
Ejemplo n.º 26
0
    def setUp(self):
        self.registrations_per_center = 4
        self.oil_center_period_1_voters = 1
        self.oil_center_period_2_voters = 2
        self.offices = [OfficeFactory(region=Office.REGION_EAST),
                        OfficeFactory(region=Office.REGION_WEST)]
        # Note: An oil center doesn't normally allow registrations, but it does so for
        # this testcase.
        self.oil_center = RegistrationCenterFactory(office=self.offices[0],
                                                    center_type=RegistrationCenter.Types.OIL)

        # !reg_open won't affect election day counts but it will affect whether
        # or not any registrations are found
        self.inactive_for_reg_center = RegistrationCenterFactory(office=self.offices[1],
                                                                 reg_open=False)

        self.centers = [self.oil_center,
                        RegistrationCenterFactory(office=self.offices[0]),
                        RegistrationCenterFactory(office=self.offices[0]),
                        RegistrationCenterFactory(office=self.offices[1]),
                        self.inactive_for_reg_center,
                        ]

        copy_center = RegistrationCenterFactory(office=self.offices[1], copy_of=self.centers[3])
        self.centers.append(copy_center)

        self.election_decoy_before = ElectionFactory(
            name_english='decoy before',
            name_arabic='decoy before (ar)',
            polling_start_time=now() - timedelta(days=10),
            polling_end_time=now() - timedelta(days=9),
        )
        self.election = ElectionFactory(
            name_english='%s election' % type(self).__name__,
            name_arabic='not Arabic',
            polling_start_time=now() - timedelta(hours=2),
            polling_end_time=now() + timedelta(hours=2),
        )
        self.election_decoy_after = ElectionFactory(
            name_english='decoy after',
            name_arabic='decoy after (ar)',
            polling_start_time=now() + timedelta(days=9),
            polling_end_time=now() + timedelta(days=10),
        )

        self.center_opens = []
        for center in self.centers:
            if center != self.centers[1]:
                self.center_opens.append(CenterOpenFactory(election=self.election,
                                                           registration_center=center))

        # CenterOpen may refer to a deleted center. Make sure that we don't find those
        self.deleted_center = RegistrationCenterFactory(office=self.offices[0], deleted=True)
        self.center_open_referring_to_deleted_center = CenterOpenFactory(
            election=self.election,
            registration_center=self.deleted_center)

        # Performance enhancement: this dummy person and SMS allow me to avoid creation of two
        # spurious objects for each registration I create.
        self.citizen = CitizenFactory()
        self.sms = SMSFactory(citizen=self.citizen)

        # Create registrations, but be careful not to create any at the copy center
        # or at the center which doesn't support registrations.
        self.registrations = []
        for center in self.centers:
            if center.reg_open and not center.copy_of:
                self.registrations += \
                    RegistrationFactory.create_batch(self.registrations_per_center,
                                                     citizen=self.citizen,
                                                     sms=self.sms,
                                                     registration_center=center)

        # These reports include quirks such as multiple reports for a center (very common in real
        # life), a missing final period report, and multiple reports for the same center & period.
        self.reports = [
            PollingReportFactory(election=self.election,
                                 registration_center=self.oil_center,
                                 period_number=FIRST_PERIOD_NUMBER,
                                 num_voters=self.oil_center_period_1_voters),
            PollingReportFactory(election=self.election,
                                 registration_center=self.oil_center,
                                 period_number=FIRST_PERIOD_NUMBER + 1,
                                 num_voters=self.oil_center_period_2_voters),
            PollingReportFactory(election=self.election,
                                 registration_center=self.centers[2],
                                 period_number=FIRST_PERIOD_NUMBER,
                                 num_voters=1),
            # The next two reports are for the same center & period with different num_voters
            # to exercise the code that sorts by modification_date.
            PollingReportFactory(election=self.election,
                                 registration_center=self.centers[2],
                                 period_number=FIRST_PERIOD_NUMBER + 1,
                                 num_voters=4),
            PollingReportFactory(election=self.election,
                                 registration_center=self.centers[2],
                                 period_number=FIRST_PERIOD_NUMBER + 1,
                                 num_voters=6),
            PollingReportFactory(election=self.election,
                                 registration_center=self.centers[3],
                                 period_number=FIRST_PERIOD_NUMBER,
                                 num_voters=1),
            PollingReportFactory(election=self.election,
                                 registration_center=self.centers[3],
                                 period_number=FIRST_PERIOD_NUMBER + 1,
                                 num_voters=4),
            # This report for a deleted center should be ignored
            PollingReportFactory(election=self.election,
                                 registration_center=self.deleted_center,
                                 period_number=FIRST_PERIOD_NUMBER + 1,
                                 num_voters=50),
            PollingReportFactory(election=self.election,
                                 registration_center=self.inactive_for_reg_center,
                                 period_number=FIRST_PERIOD_NUMBER + 1,
                                 num_voters=50),
            # This report for a copy center should count towards the original/parent center
            PollingReportFactory(election=self.election,
                                 registration_center=copy_center,
                                 period_number=LAST_PERIOD_NUMBER,
                                 num_voters=1), ]

        self.result = generate_election_day_hq_reports(self.election)
        # Create an alternate result which reflects that the "oil center" is
        # marked inactive for this election.
        self.inactive_on_election = CenterClosedForElection(
            registration_center=self.oil_center, election=self.election
        )
        self.inactive_on_election.full_clean()
        self.inactive_on_election.save()
        self.result_with_inactive = generate_election_day_hq_reports(self.election)
Ejemplo n.º 27
0
 def setUp(self):
     # Default to polling in progress
     self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)