Ejemplo n.º 1
0
    def fill_form(self):
        form_element = self.browser.find_element_by_css_selector(
            self.form_css_selector)

        all_input_type_checkbox_elements = get_all_input_type_checkbox_elements(
            form_element)
        # v1: This does not work when monkey checks zero checkbox, because in this case Belenios displays an Alert saying that voter is forced to check at least one checkbox
        # probability_to_click_a_checkbox = 0.5
        # for element in all_input_type_checkbox_elements:
        #     random_result = random.random()
        #     console_log("fill_form random_result:", random_result)
        #     if random_result < probability_to_click_a_checkbox:
        #         console_log("clicking element", representation_of_element(element))
        #         element.click()

        # v2: Define a random number of checkboxes to check, X, between 1 and the number of checkboxes. Pick X checkboxes at random and check them.
        if len(all_input_type_checkbox_elements) > 0:
            number_of_checkboxes_to_check = random.randint(
                1, len(all_input_type_checkbox_elements))
            checkboxes_to_check = random.sample(
                all_input_type_checkbox_elements,
                number_of_checkboxes_to_check)
            for element in checkboxes_to_check:
                console_log("clicking element",
                            representation_of_element(element))
                if not element.is_selected():
                    element.click()
Ejemplo n.º 2
0
    def administrator_completes_creation_of_election(self):
        # Alice, as an administrator of an election, wants to finalize her draft election creation, to start the vote.
        # She opens a browser
        self.browser = initialize_browser_for_scenario_2()
        browser = self.browser

        # She logs in as administrator
        log_in_as_administrator(browser)

        # She goes to the draft election administration page
        browser.get(self.draft_election_administration_page_url)

        # - In "Validate creation" section, she clicks on the "Create election" link
        # - (She arrives on the "Checklist" page, that lists all main parameters of the election for review, and that flags incoherent or misconfigured parameters. For example, in this test scenario, it displays 2 warnings: "Warning: No trustees were set. This means that the server will manage the election key by itself.", and "Warning: No contact was set!")
        # - In the "Validate creation" section, she clicks on the "Create election" button
        # - (She arrives back on the "My test election for Scenario 1 — Administration" page. Its contents have changed. There is now a text saying "The election is open. Voters can vote.", and there are now buttons "Close election", "Archive election", "Delete election")
        # - She remembers the URL of the voting page, that is where the "Election home" link points to
        # - She checks that a "Close election" button is present (but she does not click on it)
        self.election_page_url = administrator_validates_creation_of_election(
            browser)
        console_log("election_page_url:", self.election_page_url)
        self.election_id = election_page_url_to_election_id(
            self.election_page_url)
        console_log("election_id:", self.election_id)

        # She logs out
        log_out(browser, self.election_id)

        # She closes the window, and re-opens it (for next emulated user)
        browser.quit()
        self.browser = initialize_browser_for_scenario_2()
Ejemplo n.º 3
0
def belenios_tool_generate_credentials(election_id, number_of_voters=None):
    """
    Use local CLI belenios-tool to generate a number of credentials corresponding to the number of voters. Example:
    ```
    ./_run/tool-debug/bin/belenios-tool credgen --uuid dmGuNVL1meanZt --group ./files/groups/default.json --count 5
    5 private credentials with ids saved to ./1579802689.privcreds
    5 public credentials saved to ./1579802689.pubcreds
    5 hashed public credentials with ids saved to ./1579802689.hashcreds
    ```
    """

    if not number_of_voters:
        number_of_voters = settings.NUMBER_OF_INVITED_VOTERS
    generated_files_destination_folder = settings.GENERATED_FILES_DESTINATION_FOLDER
    belenios_tool_path = os.path.join(settings.GIT_REPOSITORY_ABSOLUTE_PATH, "_run/tool-debug/bin/belenios-tool")
    crypto_group_path = os.path.join(settings.GIT_REPOSITORY_ABSOLUTE_PATH, "files/groups/default.json")
    command = [belenios_tool_path, "credgen", "--uuid", election_id, "--group", crypto_group_path, "--count", str(number_of_voters)]
    running_process = subprocess.Popen(command, cwd=generated_files_destination_folder, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    process_timeout = 15 * number_of_voters # seconds
    credential_file_id = None
    try:
        outs, errs = running_process.communicate(timeout=process_timeout) # It looks like all output of this program is in stderr
        match = re.search(r'private credentials with ids saved to \./(.+)\.privcreds', outs, re.MULTILINE)
        if match:
            assert match
            console_log("Credentials have been generated successfully")
            credential_file_id = match.group(1)
        else:
            raise Exception("Error: Credentials generation went wrong. STDOUT was: " + outs + " STDERR was:" + errs)
    except subprocess.TimeoutExpired:
        running_process.kill()
        outs, errs = running_process.communicate()
        raise Exception("Error: Credentials generation took longer than " + process_timeout + " seconds. STDOUT was: " + outs + " STDERR was:" + errs)
    return os.path.join(generated_files_destination_folder, credential_file_id)
Ejemplo n.º 4
0
    def test_clicker_monkey_on_election_home(self):
        console_log("# test_clicker_monkey_on_election_home()")
        browser = self.browser
        election_url = get_election_url(self.election_id)
        console_log("## Going to election page:", election_url)

        monkey = SeleniumClickerMonkey(browser, election_url, 0.25, belenios_fence_filter, verify_page_is_not_an_error_page)
        monkey.start(200)
Ejemplo n.º 5
0
 def go_back(self):
     if self.verbose:
         console_log("Trying to go back")
     try:
         self.current_state = self.current_state.go_back()
         return "go_back"
     except Exception as e:
         raise Exception("Failed going back.") from e
Ejemplo n.º 6
0
    def some_voters_cast_their_vote(self, voters):
        """
        :param voters: list of dict. Each element contains information about a voter (their e-mail address, the planned answers to each question they will cast)
        """
        browser = self.browser
        timeout = settings.EXPLICIT_WAIT_TIMEOUT
        voters_count = len(voters)
        for index, voter in enumerate(voters):
            console_log(
                "#### Current voter casting their vote in current batch: " +
                str(index + 1) + "/" + str(voters_count))

            self.one_voter_votes(voter)
            wait_a_bit()
            """
            Next screen looks like this:
            Your ballot for My test election for Scenario 1 has been accepted. Your smart ballot tracker is ISXe/rCNCVa9XcVeFgKglbpgo5SoZs4svT6dPbR5b6M. You can check its presence in the {ballot box} anytime during the election. A confirmation e-mail has been sent to you.

            {Go back to election}

            Where {xxx} is a link
            """

            # He verifies that he is on step 6 and that page content is correct (page contains 'has been accepted'; page contains a ballot tracker which is the same as the one he noted)
            step_6_page = NormalVoteStep6Page(browser, timeout)
            step_6_page.verify_page(voter["smart_ballot_tracker"])

            # He clicks on the 'ballot box' link
            step_6_page.click_on_ballot_box_link()

            wait_a_bit()

            # He checks that his smart ballot tracker appears in the list
            ballot_box_page = BallotBoxPage(browser, timeout)
            ballot_box_page.verify_page(voter["smart_ballot_tracker"])
            ballot_box_page.click_on_ballot_link(voter["smart_ballot_tracker"])

            self.voters_email_addresses_who_have_voted[
                voter["email_address"]] = True

            # In a following pass, he checks his mailbox to find a new email with confirmation of his vote, and verifies the value of the smart ballot tracker written in this email is the same as the one he noted. This verification is done in a separated pass because of an optimization, so that we only re-read and re-populate the sendmail_fake text file once for all users.

            # He closes the window (there is no log-out link, because user is not logged in: credentials are not remembered)
            # It is not really mandatory for the test to close the window. Re-opening a browser takes much more time, compared to just navigating to another URL. So actually to save execution time, we choose to close the window only sometimes, randomly.
            if random.randint(0, 10) <= 3:
                browser.quit()
                self.browser = initialize_browser()
                browser = self.browser

        # Start another pass, where we re-read and re-populate the sendmail_fake text file once for all users.
        voters = repopulate_vote_confirmations_for_voters_from_sent_emails(
            self.fake_sent_emails_manager, voters, settings.ELECTION_TITLE)
        for voter in voters:
            # He checks his mailbox to find a new email with confirmation of his vote, and verifies the value of the smart ballot tracker written in this email is the same as the one he noted.
            assert voter["smart_ballot_tracker"] == voter[
                "smart_ballot_tracker_in_vote_confirmation_email"], "Ballot tracker read in vote confirmation email (" + voter[
                    "smart_ballot_tracker"] + ") is not the same as the one read on the vote confirmation page (" + voter[
                        "smart_ballot_tracker_in_vote_confirmation_email"] + ")"
Ejemplo n.º 7
0
    def administrator_completes_creation_of_election(self):
        # Alice, as an administrator of an election, wants to finalize her draft election creation, to start the vote.
        # She opens a browser
        self.browser = initialize_browser_for_scenario_2()
        browser = self.browser

        # She logs in as administrator
        log_in_as_administrator(browser)

        # She goes to the draft election administration page
        browser.get(self.draft_election_administration_page_url)

        # In the "Trustees" section, she clicks on "here"
        # TODO: use a better selector: edit Belenios page to use an ID in this DOM element
        setup_election_key_link_label = "here"
        setup_election_key_link_element = wait_for_an_element_with_partial_link_text_exists(
            browser, setup_election_key_link_label)
        setup_election_key_link_element.click()

        # She checks that in the table on all rows, the "STATE" column is now "done"
        state_column_css_selector = "#main table tr td:last-of-type"
        attribute_name = "innerText"
        attribute_value = "done"
        verify_all_elements_have_attribute_value(browser,
                                                 state_column_css_selector,
                                                 attribute_name,
                                                 attribute_value)

        wait_a_bit()

        # She clicks on the "Go back to election draft" link
        go_back_link_label = "Go back to election draft"
        go_back_link_element = wait_for_an_element_with_partial_link_text_exists(
            browser, go_back_link_label, settings.EXPLICIT_WAIT_TIMEOUT)
        go_back_link_element.click()

        # - In "Validate creation" section, she clicks on the "Create election" link
        # - (She arrives on the "Checklist" page, that lists all main parameters of the election for review, and that flags incoherent or misconfigured parameters.)
        # - She checks the presence of text "election ready"
        # - In the "Validate creation" section, she clicks on the "Create election" button
        # - (She arrives back on the "My test election for Scenario 1 — Administration" page. Its contents have changed. There is now a text saying "The election is open. Voters can vote.", and there are now buttons "Close election", "Archive election", "Delete election")
        # - She remembers the URL of the voting page, that is where the "Election home" link points to
        # - She checks that a "Close election" button is present (but she does not click on it)
        self.election_page_url = administrator_validates_creation_of_election(
            browser)
        console_log("election_page_url:", self.election_page_url)
        self.election_id = election_page_url_to_election_id(
            self.election_page_url)
        console_log("election_id:", self.election_id)

        wait_a_bit()

        # She logs out
        log_out(browser, self.election_id)

        # She closes the window, and re-opens it (for next emulated user)
        browser.quit()
        self.browser = initialize_browser_for_scenario_2()
Ejemplo n.º 8
0
    def test_very_smart_monkey_votes(self):
        console_log("# test_very_smart_monkey_votes()")
        browser = self.browser
        timeout = settings.EXPLICIT_WAIT_TIMEOUT
        election_url = election_id_to_election_home_page_url(self.election_id)

        smart_monkey_votes(browser, timeout, election_url,
                           settings.VOTER_USERNAME, settings.VOTER_PASSWORD,
                           settings.VOTER_CREDENTIAL)
Ejemplo n.º 9
0
def initialize_server():
    server_path = os.path.join(settings.GIT_REPOSITORY_ABSOLUTE_PATH, settings.SERVER_EXECUTABLE_FILE_PATH_RELATIVE_TO_GIT_REPOSITORY)
    fake_sendmail_absolute_path = os.path.join(settings.GIT_REPOSITORY_ABSOLUTE_PATH, settings.FAKE_SENDMAIL_EXECUTABLE_FILE_PATH_RELATIVE_TO_GIT_REPOSITORY)
    custom_environment_variables = dict(os.environ, BELENIOS_SENDMAIL=fake_sendmail_absolute_path)
    server = subprocess.Popen([server_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=custom_environment_variables)
    try:
        out, err = server.communicate(timeout=1)
        raise Exception("Error while trying to run the Belenios server: " + err)
    except subprocess.TimeoutExpired: # Server process has not exited yet, so we suppose it is working correctly. For example: When port is already in use, server process exits quickly, with error details in its stderr
        console_log("Server process has not exited yet, so we suppose it is working correctly")
    return server
Ejemplo n.º 10
0
    def test_scenario_1_simple_vote(self):
        with ConsoleLogDuration("### administrator_creates_election"):
            self.administrator_creates_election()

        with ConsoleLogDuration(
                "### administrator_regenerates_passwords_for_some_voters"):
            self.administrator_regenerates_passwords_for_some_voters()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#0)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### all_voters_vote_in_sequences"):
            self.all_voters_vote_in_sequences()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#1)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### create_election_data_snapshot (#0)"):
            snapshot_folder = create_election_data_snapshot(self.election_id)
            console_log("snapshot_folder: ", snapshot_folder)

        try:
            with ConsoleLogDuration("### some_voters_revote"):
                self.some_voters_revote()

            with ConsoleLogDuration(
                    "### verify_election_consistency using `belenios_tool verify-diff` (#2)"
            ):
                verify_election_consistency(self.election_id, snapshot_folder)
        finally:
            with ConsoleLogDuration("### delete_election_data_snapshot"):
                delete_election_data_snapshot(snapshot_folder)

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#3)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### administrator_does_tallying_of_election"):
            self.administrator_does_tallying_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#4)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration(
                "### one_voter_revotes_after_the_election_is_closed"):
            self.one_voter_revotes_after_the_election_is_closed()
Ejemplo n.º 11
0
    def execute_a_random_action(self):
        """
        Returns the name of the action which has been randomly chosen and executed.
        """
        if random.random() < self.probability_to_go_back:
            try:
                return self.go_back()
            except Exception as e:
                console_log(
                    "Failed going back. Trying something else. Exception was:",
                    e)

        possible_actions = self.current_state.get_all_possible_actions()
        if self.verbose:
            console_log("possible_actions:",
                        [action.__name__ for action in possible_actions])
        if len(possible_actions):
            random_action = random.choice(possible_actions)
            if self.verbose:
                console_log("action picked at random:", random_action.__name__)
            self.current_state = random_action(in_memory=self.in_memory)
            return random_action.__name__
        else:
            if self.verbose:
                console_log(
                    "List of possible actions is empty. Trying to go back")
            try:
                return self.go_back()
            except Exception as e:
                raise Exception(
                    "Cannot execute a random action, because list of posible actions is empty, and cannot go back."
                ) from e
Ejemplo n.º 12
0
def verify_election_consistency(election_id, snapshot_folder=None):
    """
    :param snapshot_folder: Optional parameter. If provided, it will verify consistency of differences (evolution) between this snapshot folder and current election database folder
    """

    election_folder = os.path.join(
        settings.GIT_REPOSITORY_ABSOLUTE_PATH,
        settings.DATABASE_FOLDER_PATH_RELATIVE_TO_GIT_REPOSITORY, election_id)
    verification_tool_path = os.path.join(
        settings.GIT_REPOSITORY_ABSOLUTE_PATH,
        "_run/tool-debug/bin/belenios-tool")
    command = [verification_tool_path, "verify"]
    if snapshot_folder:
        command = [
            verification_tool_path, "verify-diff", "--dir1=" + snapshot_folder,
            "--dir2=" + election_folder
        ]
    running_process = subprocess.Popen(command,
                                       cwd=election_folder,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       universal_newlines=True)
    process_timeout = 15  # seconds
    try:
        outs, errs = running_process.communicate(
            timeout=process_timeout
        )  # It looks like all output of this program is in stderr
        match = re.search(r'^I: all (checks|tests) passed!?$', errs,
                          re.MULTILINE)
        if match:
            console_log(
                "Verification of election consistency has been correctly processed"
            )
            assert match
        else:
            raise Exception(
                "Error: Verification of election consistency is wrong. STDOUT was: "
                + outs + " STDERR was:" + errs)
    except subprocess.TimeoutExpired:
        running_process.kill()
        outs, errs = running_process.communicate()
        raise Exception("Error: Verification took longer than " +
                        process_timeout + " seconds. STDOUT was: " + outs +
                        " STDERR was:" + errs)
Ejemplo n.º 13
0
    def one_voter_casts_after_the_election_is_closed(self, voter):
        browser = self.browser
        console_log(
            "#### Current voter casting their vote after the election is closed"
        )
        self.one_voter_votes(voter, direct=True)
        wait_a_bit()
        """
        Next screen looks like this:
        Your ballot for Test vote after close is rejected, because the election is closed.

        {Go back to election}

        Where {xxx} is a link
        """

        # He checks that "the election is closed" is present
        wait_for_element_exists_and_contains_expected_text(
            browser, "#main p", "the election is closed",
            settings.EXPLICIT_WAIT_TIMEOUT)
Ejemplo n.º 14
0
def belenios_tool_generate_ballots(voters_data, global_credential_file_id, vote_page_url):
    generated_files_destination_folder = settings.GENERATED_FILES_DESTINATION_FOLDER
    belenios_tool_path = os.path.join(settings.GIT_REPOSITORY_ABSOLUTE_PATH, "_run/tool-debug/bin/belenios-tool")

    i = 0
    for k, v in voters_data.items():
        i += 1
        # Extract voter private credential from global private credentials file (it corresponds to row `i` in the file) and write it to its own file
        voter_credential_file = os.path.join(generated_files_destination_folder, "voter_row_" + str(i) + "_privcred.txt")
        command = "tail -n +" + str(i) + " " + global_credential_file_id + ".privcreds | head -n 1 | cut -d' ' -f2 > " + voter_credential_file
        running_process = subprocess.Popen(command, cwd=generated_files_destination_folder, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
        process_timeout = 15 # seconds
        try:
            outs, errs = running_process.communicate(timeout=process_timeout)
        except subprocess.TimeoutExpired:
            running_process.kill()
            outs, errs = running_process.communicate()
            raise Exception("Error: Extraction of voter private credential from global private credentials file took longer than " + str(process_timeout) + " seconds. STDOUT was: " + outs + " STDERR was:" + errs)

        # Write array of voter's answers to questions in a file: This is his non-encrypted ballot, written as a JSON array where each element is the answer to the `i`th question. This answer is itself an array of zeros or ones depending on whether voter checked or not the checkbox corresponding to this answer.
        voter_uncrypted_ballot_file = os.path.join(generated_files_destination_folder, "voter_row_" + str(i) + "_uncrypted_ballot.json")
        voter_uncrypted_ballot_content = json.dumps(convert_voter_votes_to_json_uncrypted_ballot(v))
        console_log("voter_uncrypted_ballot_file:", voter_uncrypted_ballot_file)
        try:
            with open(voter_uncrypted_ballot_file, 'w') as myfile:
                myfile.write(voter_uncrypted_ballot_content)
        except Exception as e:
            raise Exception("Error: Could not write voter's answers (his uncrypted ballot) to a file.") from e

        # Execute belenios-tool to generate a vote ballot for voter
        voter_crypted_ballot_file = "voter_row_" + str(i) + "_crypted_ballot.json"
        command = [belenios_tool_path, "vote", "--url", vote_page_url, "--privcred", voter_credential_file, "--ballot", voter_uncrypted_ballot_file, ">", voter_crypted_ballot_file]
        running_process = subprocess.Popen(" ".join(command), cwd=generated_files_destination_folder, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
        process_timeout = 120 # seconds
        try:
            outs, errs = running_process.communicate(timeout=process_timeout)
        except subprocess.TimeoutExpired:
            running_process.kill()
            outs, errs = running_process.communicate()
            raise Exception("Error: Generation of voter's encrypted ballot file took longer than " + str(process_timeout) + " seconds. STDOUT was: " + outs + " STDERR was:" + errs)
Ejemplo n.º 15
0
 def handle_alerts(self):
     looking_for_alert = True
     while looking_for_alert:
         try:
             alert = self.browser.switch_to.alert
             console_log("* We encounter an Alert")
             random_result3 = random.random()
             if random_result3 < 0.5:
                 console_log("* We decide to accept the Alert")
                 alert.accept()
             else:
                 console_log("* We decide to dismiss the Alert")
                 alert.dismiss()
             sleep(1)
         except NoAlertPresentException:
             looking_for_alert = False
Ejemplo n.º 16
0
    def administrator_creates_election(self, nh_question=False):
        # # Setting up a new election (action of the administrator)

        browser = self.browser

        # Alice has been given administrator rights on an online voting app called Belenios. She goes
        # to check out its homepage and logs in
        log_in_as_administrator(browser)

        # She starts creation of the election:
        # - She clicks on the "Prepare a new election" link
        # (- She keeps default values on the form: Credential management is automatic (not manual), and Authentication method is Password, not CAS)
        # - She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
        # - She changes values of fields name and description of the election
        # - She clicks on the "Save changes button" (the one that is next to the election description field)
        administrator_starts_creation_of_election(browser)

        # She edits election's questions:
        # - She clicks on the "Edit questions" link, to write her own questions
        # - She arrives on the Questions page. She checks that the page title is correct
        # - She removes answer 3
        # - She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
        administrator_edits_election_questions(browser, nh_question)

        # She sets election's voters:
        # - She clicks on the "Edit voters" link, to then type the list of voters
        # - She types N e-mail addresses (the list of invited voters)
        # - She clicks on the "Add" button to submit changes
        # - She clicks on "Go back to election draft" link
        self.voters_email_addresses = random_email_addresses_generator(
            settings.NUMBER_OF_INVITED_VOTERS)
        administrator_sets_election_voters(browser,
                                           self.voters_email_addresses)

        # She clicks on button "Generate on server"
        generate_on_server_button_label = "Generate on server"
        generate_on_server_button_css_selector = build_css_selector_to_find_buttons_in_page_content_by_value(
            generate_on_server_button_label)
        generate_on_server_button_element = wait_for_element_exists(
            browser, generate_on_server_button_css_selector,
            settings.EXPLICIT_WAIT_TIMEOUT)
        generate_on_server_button_element.click()

        wait_a_bit()

        # (Server sends emails to voters.) She checks that server does not show any error that would happen when trying to send these emails (this can happen if sendmail is not configured)
        confirmation_sentence_expected_text = "Credentials have been generated and mailed!"
        confirmation_sentence_css_selector = "#main p"
        wait_for_element_exists_and_contains_expected_text(
            browser, confirmation_sentence_css_selector,
            confirmation_sentence_expected_text,
            settings.EXPLICIT_WAIT_TIMEOUT)

        # Now we do a sanity check that server has really tried to send emails. For this, we look for email addresses in the temporary file where our fake sendmail executable redirects its inputs to.
        """
        An email sent by Belenios (using sendmail or using the fake sendmail) to a voter looks like this:

Content-type: text/plain; charset="UTF-8"
Content-transfer-encoding: quoted-printable
From: Belenios public server <*****@*****.**>
To: "*****@*****.**"
 <*****@*****.**>
Subject: Your credential for election My test election for Scenario 1
MIME-Version: 1.0
X-Mailer: OcamlNet (ocamlnet.sourceforge.net)
Date: Wed, 31 Oct 2018 15:22:27 +0100

You are listed as a voter for the election

  My test election for Scenario 1

You will find below your credential.  To cast a vote, you will also
need a password, sent in a separate email.  Be careful, passwords and
credentials look similar but play different roles.  You will be asked
to enter your credential before entering the voting booth.  Login and
passwords are required once your ballot is ready to be cast.

Credential: yQVDQaKSAQVjdZq
Page of the election: http://localhost:8001/elections/AFFNDEPnpy21bw/

Note that you are allowed to vote several times.  Only the last vote
counts.

----------

Vous =C3=AAtes enregistr=C3=A9(e) en tant qu=27=C3=A9lecteur(trice) pour=20=
l=27=C3=A9lection

  My test election for Scenario 1

Veuillez trouver ci-dessous votre code de vote. Pour soumettre un
bulletin, vous aurez =C3=A9galement besoin d=27un mot de passe, envoy=C3=A9=
 dans
un e-mail s=C3=A9par=C3=A9. Soyez attentif(ve), le mot de passe et le cod=
e de
vote se ressemblent mais jouent des r=C3=B4les diff=C3=A9rents. Le syst=C3=
=A8me vous
demandera votre code de vote d=C3=A8s l=27entr=C3=A9e dans l=27isoloir=20=
virtuel. Le
nom d=27utilisateur et le mot de passe sont n=C3=A9cessaires lorsque votr=
e
bulletin est pr=C3=AAt =C3=A0 =C3=AAtre soumis.

Code de vote=C2=A0: yQVDQaKSAQVjdZq
Page de l=27=C3=A9lection=C2=A0: http://localhost:8001/elections/AFFNDEPn=
py21bw/

Notez que vous pouvez voter plusieurs fois. Seul le dernier vote est
pris en compte.

--=20
        """

        email_address_to_look_for = self.voters_email_addresses[0]
        text_to_look_for = 'To: "' + email_address_to_look_for + '"'
        email_address_found = self.fake_sent_emails_manager.find_in_sent_emails(
            text_to_look_for)
        assert email_address_found, "Text '" + email_address_to_look_for + "' not found in fake sendmail log file " + self.fake_sent_emails_manager.log_file_path

        # She clicks on the "Proceed" link
        proceed_link_css_selector = "#generic_proceed_link"
        proceed_link_element = wait_for_element_exists(
            browser, proceed_link_css_selector, settings.EXPLICIT_WAIT_TIMEOUT)
        proceed_link_element.click()

        wait_a_bit()

        # In "Authentication" section, she clicks on the "Generate and mail missing passwords" button
        generate_and_mail_missing_passwords_button_label = "Generate and mail missing passwords"
        generate_and_mail_missing_passwords_button_element = wait_for_element_exists(
            browser,
            build_css_selector_to_find_buttons_in_page_content_by_value(
                generate_and_mail_missing_passwords_button_label),
            settings.EXPLICIT_WAIT_TIMEOUT)
        generate_and_mail_missing_passwords_button_element.click()

        wait_a_bit()

        # She checks that the page contains expected confirmation text, instead of an error (TODO: explain in which case an error can happen, and check that it does not show)
        confirmation_sentence_expected_text = "Passwords have been generated and mailed!"
        confirmation_sentence_css_selector = "#main p"
        wait_for_element_exists_and_contains_expected_text(
            browser, confirmation_sentence_css_selector,
            confirmation_sentence_expected_text,
            settings.EXPLICIT_WAIT_TIMEOUT)

        # She clicks on the "Proceed" link (this redirects to the "Preparation of election" page)
        proceed_link_css_selector = "#generic_proceed_link"
        proceed_link_element = wait_for_element_exists(
            browser, proceed_link_css_selector, settings.EXPLICIT_WAIT_TIMEOUT)
        proceed_link_element.click()

        wait_a_bit()

        self.election_page_url = administrator_validates_creation_of_election(
            browser)
        console_log("election_page_url:", self.election_page_url)
        self.election_id = election_page_url_to_election_id(
            self.election_page_url)
        console_log("election_id:", self.election_id)

        log_out(browser, self.election_id)
Ejemplo n.º 17
0
    def some_voters_vote_in_sequences(self,
                                      voters=None,
                                      start_index=0,
                                      end_index=None,
                                      verify_every_x_votes=5):
        """
        Iterates over `voters` from index `start_index` (included) to `end_index` (not included), cast their vote, and checks vote data consistency for every batch of `verify_every_x_votes` votes (using `belenios_tool verify-diff` and a snapshot of election data copied in previous batch).
        """
        if start_index < 0:
            raise Exception("start_index cannot be below 0")
        current_start_index = start_index
        if end_index is None:
            end_index = settings.NUMBER_OF_VOTING_VOTERS
        elif end_index > settings.NUMBER_OF_VOTING_VOTERS:
            raise Exception("end_index cannot exceeed NUMBER_OF_VOTING_VOTERS")

        if voters is None:
            voters = self.voters_email_addresses
        voters_who_will_vote_now = voters[start_index:end_index]
        voters_who_will_vote_now_data = populate_credential_and_password_for_voters_from_sent_emails(
            self.fake_sent_emails_manager, voters_who_will_vote_now,
            settings.ELECTION_TITLE)
        voters_who_will_vote_now_data = populate_random_votes_for_voters(
            voters_who_will_vote_now_data)
        self.update_voters_data(voters_who_will_vote_now_data)
        snapshot_folder = None

        while current_start_index < end_index:
            increment = verify_every_x_votes  # could be randomized
            current_end_index = current_start_index + increment
            if current_end_index > end_index:
                current_end_index = end_index

            if current_start_index > 0:
                console_log(
                    "#### Starting substep: create_election_data_snapshot")
                snapshot_folder = create_election_data_snapshot(
                    self.election_id)
                console_log(
                    "#### Substep complete: create_election_data_snapshot")

            try:
                console_log("#### A batch of " +
                            str(current_end_index - current_start_index) +
                            " voters, indexed " + str(current_start_index) +
                            " to " + str(current_end_index - 1) +
                            " included are now going to vote")
                sublist_start_index = current_start_index - start_index
                sublist_end_index = current_end_index - start_index
                self.some_voters_cast_their_vote(voters_who_will_vote_now_data[
                    sublist_start_index:sublist_end_index])
                console_log("#### A batch of " +
                            str(current_end_index - current_start_index) +
                            " voters, indexed " + str(current_start_index) +
                            " to " + str(current_end_index - 1) +
                            " included have now voted")

                if current_start_index > 0:
                    console_log(
                        "#### Starting substep: verify_election_consistency using `belenios_tool verify-diff` (for a batch of votes)"
                    )
                    verify_election_consistency(self.election_id,
                                                snapshot_folder)
                    console_log(
                        "#### Substep complete: verify_election_consistency using `belenios_tool verify-diff` (for a batch of votes)"
                    )
            finally:
                if current_start_index > 0:
                    console_log(
                        "#### Starting substep: delete_election_data_snapshot")
                    delete_election_data_snapshot(snapshot_folder)
                    console_log(
                        "#### Substep complete: delete_election_data_snapshot")

            current_start_index += increment
Ejemplo n.º 18
0
    def test_scenario_4_manual_vote_with_threshold(self):
        console_log(
            "### Running test method BeleniosTestElectionScenario4::test_scenario_4_manual_vote_with_threshold()"
        )
        with ConsoleLogDuration(
                "### administrator_starts_creation_of_manual_election"):
            self.administrator_starts_creation_of_manual_election()

        with ConsoleLogDuration(
                "### credential_authority_sends_credentials_to_voters"):
            self.credential_authority_sends_credentials_to_voters()

        with ConsoleLogDuration(
                "### administrator_invites_trustees_and_sets_threshold"):
            self.administrator_invites_trustees_and_sets_threshold()

        with ConsoleLogDuration("### trustees_do_initialization_step_1_of_3"):
            self.trustees_do_initialization_step_1_of_3()

        with ConsoleLogDuration("### trustees_do_initialization_step_2_of_3"):
            self.trustees_do_initialization_step_2_of_3()

        with ConsoleLogDuration("### trustees_do_initialization_step_3_of_3"):
            self.trustees_do_initialization_step_3_of_3()

        with ConsoleLogDuration(
                "### administrator_completes_creation_of_election"):
            self.administrator_completes_creation_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#0)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### all_voters_vote_in_sequences"):
            self.all_voters_vote_in_sequences()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#1)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### create_election_data_snapshot (#0)"):
            snapshot_folder = create_election_data_snapshot(self.election_id)

        try:
            with ConsoleLogDuration("### some_voters_revote"):
                self.some_voters_revote()

            with ConsoleLogDuration(
                    "### verify_election_consistency using `belenios_tool verify-diff` (#2)"
            ):
                verify_election_consistency(self.election_id, snapshot_folder)
        finally:
            with ConsoleLogDuration("### delete_election_data_snapshot"):
                delete_election_data_snapshot(snapshot_folder)

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#3)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration(
                "### administrator_starts_tallying_of_election"):
            self.administrator_starts_tallying_of_election(
                settings.TRUSTEES_THRESHOLD_VALUE)

        with ConsoleLogDuration("### trustees_do_partial_decryption"):
            self.trustees_do_partial_decryption(
                settings.TRUSTEES_THRESHOLD_VALUE)

        with ConsoleLogDuration(
                "### administrator_finishes_tallying_of_election"):
            self.administrator_finishes_tallying_of_election(
                settings.TRUSTEES_THRESHOLD_VALUE)

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#4)"
        ):
            verify_election_consistency(self.election_id)
Ejemplo n.º 19
0
    def test_scenario_2_manual_vote_with_monkeys(self):
        console_log(
            "### Running test method BeleniosTestElectionScenario2WithMonkeys::test_scenario_2_manual_vote_with_monkeys()"
        )
        with ConsoleLogDuration(
                "### administrator_starts_creation_of_manual_election"):
            self.administrator_starts_creation_of_manual_election()

        with ConsoleLogDuration(
                "### credential_authority_sends_credentials_to_voters"):
            self.credential_authority_sends_credentials_to_voters()

        with ConsoleLogDuration("### administrator_invites_trustees"):
            self.administrator_invites_trustees()

        with ConsoleLogDuration("### trustees_generate_election_private_keys"):
            self.trustees_generate_election_private_keys()

        with ConsoleLogDuration(
                "### administrator_completes_creation_of_election"):
            self.administrator_completes_creation_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#0)"
        ):
            verify_election_consistency(self.election_id)

        self.voters_data = {
        }  # We reset this (set by `BeleniosTestElectionWithCreationBase`) because we generate voters data in several parts
        voters_who_will_vote = random.sample(self.voters_email_addresses,
                                             settings.NUMBER_OF_VOTING_VOTERS)
        console_log("voters who will vote:", voters_who_will_vote)
        start_index_of_voters_who_vote_in_first_part = 0
        end_index_of_voters_who_vote_in_first_part = settings.NUMBER_OF_VOTING_VOTERS_IN_FIRST_PART
        console_log(
            f"number of (normal) voters who will vote in first part: {end_index_of_voters_who_vote_in_first_part} (indexes {start_index_of_voters_who_vote_in_first_part} included to {end_index_of_voters_who_vote_in_first_part} excluded)"
        )
        start_index_of_voters_who_vote_in_second_part = end_index_of_voters_who_vote_in_first_part
        end_index_of_voters_who_vote_in_second_part = end_index_of_voters_who_vote_in_first_part + settings.NUMBER_OF_MONKEY_VOTING_VOTERS
        console_log(
            f"number of (smart monkey) voters who will vote in second part: {end_index_of_voters_who_vote_in_second_part - start_index_of_voters_who_vote_in_second_part} (indexes {start_index_of_voters_who_vote_in_second_part} included to {end_index_of_voters_who_vote_in_second_part} excluded)"
        )
        start_index_of_voters_who_vote_in_third_part = end_index_of_voters_who_vote_in_second_part
        end_index_of_voters_who_vote_in_third_part = settings.NUMBER_OF_VOTING_VOTERS
        console_log(
            f"number of (normal) voters who will vote in third part: {end_index_of_voters_who_vote_in_third_part - start_index_of_voters_who_vote_in_third_part} (indexes {start_index_of_voters_who_vote_in_third_part} included to {end_index_of_voters_who_vote_in_third_part} excluded)"
        )
        verify_every_x_votes = 5

        with ConsoleLogDuration(
                "### some_voters_vote_in_sequences (first part)"):
            self.some_voters_vote_in_sequences(
                voters_who_will_vote,
                start_index=start_index_of_voters_who_vote_in_first_part,
                end_index=end_index_of_voters_who_vote_in_first_part,
                verify_every_x_votes=verify_every_x_votes)

        with ConsoleLogDuration("### smart monkeys vote (second part)"):
            smart_monkey_voters_who_will_vote_now = voters_who_will_vote[
                start_index_of_voters_who_vote_in_second_part:
                end_index_of_voters_who_vote_in_second_part]
            timeout = settings.EXPLICIT_WAIT_TIMEOUT
            voters_who_will_vote_now_data = populate_credential_and_password_for_voters_from_sent_emails(
                self.fake_sent_emails_manager,
                smart_monkey_voters_who_will_vote_now, settings.ELECTION_TITLE)
            voters_who_will_vote_now_data = populate_random_votes_for_voters(
                voters_who_will_vote_now_data)
            self.update_voters_data(voters_who_will_vote_now_data)

            for idx, voter in enumerate(voters_who_will_vote_now_data):
                console_log(
                    f"#### Voting as smart monkey {idx+1} of {settings.NUMBER_OF_MONKEY_VOTING_VOTERS}"
                )
                voter_email_address = voter["email_address"]
                voter_username = voter["username"]
                voter_password = voter["password"]
                voter_credential = voter["credential"]
                voter_decided_vote = voter["votes"]
                election_url = voter[
                    "election_page_url"]  # this is the same as `election_id_to_election_home_page_url(self.election_id)`
                smart_ballot_tracker = smart_monkey_votes(
                    self.browser, timeout, election_url, voter_username,
                    voter_password, voter_credential, voter_decided_vote)
                if smart_ballot_tracker:
                    voter["smart_ballot_tracker"] = smart_ballot_tracker
                else:
                    raise Exception(
                        "Monkey voter did not complete its vote properly")
                self.voters_email_addresses_who_have_voted[
                    voter_email_address] = True
                self.browser.quit()
                self.browser = initialize_browser_for_scenario_2()

        with ConsoleLogDuration(
                "### some_voters_vote_in_sequences (third part)"):
            self.some_voters_vote_in_sequences(
                voters_who_will_vote,
                start_index=start_index_of_voters_who_vote_in_third_part,
                end_index=end_index_of_voters_who_vote_in_third_part,
                verify_every_x_votes=verify_every_x_votes)

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#1)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration(
                "### Starting step: create_election_data_snapshot (#0)"):
            snapshot_folder = create_election_data_snapshot(self.election_id)
            console_log("snapshot_folder: ", snapshot_folder)

        try:
            with ConsoleLogDuration("### some_voters_revote"):
                self.some_voters_revote()

            with ConsoleLogDuration(
                    "### verify_election_consistency using `belenios_tool verify-diff` (#2)"
            ):
                verify_election_consistency(self.election_id, snapshot_folder)
        finally:
            with ConsoleLogDuration("### delete_election_data_snapshot"):
                delete_election_data_snapshot(snapshot_folder)

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#3)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration(
                "### administrator_starts_tallying_of_election"):
            self.administrator_starts_tallying_of_election()

        with ConsoleLogDuration("### trustees_do_partial_decryption"):
            self.trustees_do_partial_decryption()

        with ConsoleLogDuration(
                "### administrator_finishes_tallying_of_election"):
            self.administrator_finishes_tallying_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#4)"
        ):
            verify_election_consistency(self.election_id)
Ejemplo n.º 20
0
 def verify_page(self, in_memory):
     console_log("BallotBoxPageState::verify_page()")
     smart_ballot_tracker = in_memory.get(
         "voter_validated_smart_ballot_tracker", None)
     return self.page.verify_page(smart_ballot_tracker)
Ejemplo n.º 21
0
    def test_scenario_2_manual_vote(self):
        console_log(
            "### Running test method BeleniosTestElectionScenario2::test_scenario_2_manual_vote()"
        )
        with ConsoleLogDuration(
                "### administrator_starts_creation_of_manual_election"):
            self.administrator_starts_creation_of_manual_election()

        with ConsoleLogDuration(
                "### credential_authority_sends_credentials_to_voters"):
            self.credential_authority_sends_credentials_to_voters()

        with ConsoleLogDuration("### administrator_invites_trustees"):
            self.administrator_invites_trustees()

        with ConsoleLogDuration("### trustees_generate_election_private_keys"):
            self.trustees_generate_election_private_keys()

        with ConsoleLogDuration(
                "### administrator_completes_creation_of_election"):
            self.administrator_completes_creation_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#0)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### all_voters_vote_in_sequences"):
            self.all_voters_vote_in_sequences()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#1)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration(
                "### Starting step: create_election_data_snapshot (#0)"):
            snapshot_folder = create_election_data_snapshot(self.election_id)
            console_log("snapshot_folder: ", snapshot_folder)

        try:
            with ConsoleLogDuration("### some_voters_revote"):
                self.some_voters_revote()

            with ConsoleLogDuration(
                    "### verify_election_consistency using `belenios_tool verify-diff` (#2)"
            ):
                verify_election_consistency(self.election_id, snapshot_folder)
        finally:
            with ConsoleLogDuration("### delete_election_data_snapshot"):
                delete_election_data_snapshot(snapshot_folder)

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#3)"
        ):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration(
                "### administrator_starts_tallying_of_election"):
            self.administrator_starts_tallying_of_election()

        with ConsoleLogDuration("### trustees_do_partial_decryption"):
            self.trustees_do_partial_decryption()

        with ConsoleLogDuration(
                "### administrator_finishes_tallying_of_election"):
            self.administrator_finishes_tallying_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#4)"
        ):
            verify_election_consistency(self.election_id)
Ejemplo n.º 22
0
    def start(self, maximum_actions_in_visit=100):
        """
        Warning: Do not set a very high value to `maximum_actions_in_visit`. This is because some links clicked by the monkey trigger a download confirmation modal. There seems to be no way in Selenium to click cancel in this modal. As we don't tell the monkey to accept the download (we don't want to), the monkey continues its navigation with the modal still open. Modals stack. You can avoid some or all downloads by customizing your fence function.
        """
        # Possibility of improvement: Detect also when a button (not only a link) redirects to a page which is outside of the fence filter
        probability_to_go_back_when_dead_end = 1  # 0.25

        console_log("## First action in visit goes to page:",
                    self.initial_page_url)
        self.browser.get(self.initial_page_url)
        current_actions_in_visit = 1

        while current_actions_in_visit < maximum_actions_in_visit:
            current_actions_in_visit += 1
            console_log("## current_actions_in_visit:",
                        current_actions_in_visit)
            if self.verify_page_is_not_an_error_page_function:
                self.verify_page_is_not_an_error_page_function(self.browser)
            random_result = random.random()
            if random_result < self.probability_to_go_back:
                if current_actions_in_visit > 2:
                    console_log("### Deciding to go back")
                    self.go_back()
            else:
                clickable_elements = get_all_clickable_elements_in_page(
                    self.browser, self.fence_filter_function,
                    self.initial_page_url)
                if not len(clickable_elements):
                    console_log("### No more clickable element to click on.")
                    random_result2 = random.random()
                    if random_result2 < probability_to_go_back_when_dead_end:
                        console_log("### Deciding to go back")
                        self.go_back()
                        continue
                    else:
                        console_log("### Deciding to end visit here.")
                        break
                else:
                    selected_element = random.choice(clickable_elements)
                    console_log("### We choose randomly this element:",
                                representation_of_element(selected_element))
                    selected_element.click()
                    wait_a_bit()
                    self.handle_alerts()

        console_log("### SeleniumClickerMonkey visit is now complete.")
Ejemplo n.º 23
0
    def test_scenario_1_simple_vote(self):
        console_log("### Starting step: administrator_creates_election")
        self.administrator_creates_election(nh_question=True)
        console_log("### Step complete: administrator_creates_election")

        console_log("### Starting step: administrator_regenerates_passwords_for_some_voters")
        self.administrator_regenerates_passwords_for_some_voters()
        console_log("### Step complete: administrator_regenerates_passwords_for_some_voters")

        console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (0)")
        verify_election_consistency(self.election_id)
        console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (0)")

        console_log("### Starting step: all_voters_vote_in_sequences")
        self.all_voters_vote_in_sequences()
        console_log("### Step complete: all_voters_vote_in_sequences")

        console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (1)")
        verify_election_consistency(self.election_id)
        console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (1)")

        console_log("### Starting step: create_election_data_snapshot (0)")
        snapshot_folder = create_election_data_snapshot(self.election_id)
        console_log("### Step complete: create_election_data_snapshot (0)")

        try:
            console_log("### Starting step: some_voters_revote")
            self.some_voters_revote()
            console_log("### Step complete: some_voters_revote")

            console_log("### Starting step: verify_election_consistency using `belenios_tool verify-diff` (0)")
            verify_election_consistency(self.election_id, snapshot_folder)
        finally:
            delete_election_data_snapshot(snapshot_folder)
        console_log("### Step complete: verify_election_consistency using `belenios_tool verify-diff` (0)")

        console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (2)")
        verify_election_consistency(self.election_id)
        console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (2)")

        console_log("### Starting step: administrator_does_tallying_of_election")
        self.administrator_does_tallying_of_election()
        console_log("### Step complete: administrator_does_tallying_of_election")

        console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (3)")
        verify_election_consistency(self.election_id)
        console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (3)")

        console_log("### Starting step: voter votes after the election is closed")
        self.one_voter_revotes_after_the_election_is_closed()
        console_log("### Step complete: voter votes after the election is closed")
Ejemplo n.º 24
0
        with ConsoleLogDuration(
                "### administrator_finishes_tallying_of_election"):
            self.administrator_finishes_tallying_of_election()

        with ConsoleLogDuration(
                "### verify_election_consistency using `belenios_tool verify` (#4)"
        ):
            verify_election_consistency(self.election_id)


if __name__ == "__main__":
    random_seed = os.getenv('RANDOM_SEED', None)
    if not random_seed:
        random_seed = random.randrange(sys.maxsize)
    console_log("Python random seed being used:", random_seed)
    random.seed(random_seed)

    if os.getenv('USE_HEADLESS_BROWSER', None):
        settings.USE_HEADLESS_BROWSER = bool(
            strtobool(os.getenv('USE_HEADLESS_BROWSER')))

    settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH = os.getenv(
        'SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH',
        settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH)
    settings.WAIT_TIME_BETWEEN_EACH_STEP = float(
        os.getenv('WAIT_TIME_BETWEEN_EACH_STEP',
                  settings.WAIT_TIME_BETWEEN_EACH_STEP))

    settings.EXPLICIT_WAIT_TIMEOUT = int(
        os.getenv('EXPLICIT_WAIT_TIMEOUT', settings.EXPLICIT_WAIT_TIMEOUT))
Ejemplo n.º 25
0
 def verify_page(self, in_memory):
     console_log("NormalVoteStep6PageState::verify_page()")
     return self.page.verify_page(
         in_memory["voter_temporary_smart_ballot_tracker"])
Ejemplo n.º 26
0
    def test_sometimes_smart_monkey_votes(self):
        console_log("# test_sometimes_smart_monkey_votes()")
        browser = self.browser
        timeout = settings.EXPLICIT_WAIT_TIMEOUT
        election_url = get_election_url(self.election_id)
        console_log("## Going to election page:", election_url)
        browser.get(election_url)

        wait_a_bit()

        console_log("## Starting clicker monkey behaviour")
        monkey = SeleniumClickerMonkey(browser, election_url, 0.25, belenios_fence_filter, verify_page_is_not_an_error_page)
        maximum_monkey_clicks = 50
        monkey.start(maximum_monkey_clicks)
        console_log("## End of clicker monkey behaviour")

        console_log("## Going to election page again", election_url)
        browser.get(election_url)

        wait_a_bit()

        console_log("## Clicking on 'en' language link")
        election_home_page = ElectionHomePage(browser, timeout)
        election_home_page.click_on_language_link("en")

        wait_a_bit()

        console_log("## Clicking on 'Start' button")
        election_home_page.click_on_start_button()

        wait_a_bit()

        console_log("## Verifying that we are on step 1 page")
        step_1_page = NormalVoteStep1Page(browser, timeout)
        step_1_page.verify_page()

        # Here:
        # We cannot have a monkey behaviour, because there is only one button to click (the "here" button).
        # We can go back. This goes back to election home page

        console_log("## Clicking on 'here' button")
        step_1_page.click_on_here_button_and_type_voter_credential(settings.VOTER_CREDENTIAL)

        wait_a_bit()

        step_2_page = NormalVoteStep2Page(browser, timeout)
        step_2_page.verify_page()

        # Here:
        # We can check any checkbox for the question (check 0 to n checkboxes)
        # We can click on the "Next" button
        # We can go back. This would go back to the election home page (not to the "Step 1" page, which would probably have been the intuitive behaviour)

        console_log("## Answering vote question by checking randomly some checkboxes")
        step_2_parent_css_selector = "#question_div"
        form_filler_monkey = SeleniumFormFillerMonkey(browser, step_2_parent_css_selector) # Warning: In the DOM of the vote page, step 2, checkboxes are not in a `<form>`.
        form_filler_monkey.fill_form()

        console_log("## Click on the 'Next' button")
        step_2_page.click_on_next_button()

        wait_a_bit()

        console_log("## Verify that we are on step 3 and that page content is correct (ballot tracker is not empty)")
        step_3_page = NormalVoteStep3Page(browser, timeout)
        step_3_page.verify_page()
        step_3_smart_ballot_tracker_value = step_3_page.get_smart_ballot_tracker_value()

        # Here:
        # We can click on the "Continue" button (`<input style="font-size:30px;" value="Continue" type="submit">`)
        # We can click on the "Restart" button (`<button onclick="location.reload();">Restart</button>`). This goes back to step 1.

        console_log("## Click on the 'Continue' button")
        step_3_page.click_on_continue_button()

        wait_a_bit()

        # We arrive on the login form (if we have not already logged in during this visit, which could happen if we do a complex navigation after a first login. If we have already logged in, we arrive directly on the step 5 page)
        console_log("## Verify that we are on login page")
        login_page = VoterLoginPage(browser, timeout)
        login_page.verify_page()

        # Here:
        # We can click on the "Login" button without filling the username nor password field
        # We can click on the "Login" button after having filled the username and password fields with wrong data
        # We can click on the "Login" button after having filled the username and password fields with correct data
        # We can go back. This goes back to step 3.

        # If we don't fill the form, or fill the form with wrong username/password, and click on the "Login" button, we arrive on an "Unauthorized" "Error 401" page.

        # If we fill the form with correct data and click on the "Login" button, we arrive on step 5 page.

        console_log("## Filling log in form and submitting it")
        login_page.log_in(settings.VOTER_USERNAME, settings.VOTER_PASSWORD)

        console_log("## Verify that we are on step 5 and that page content is correct (page contains 'has been received, but not recorded yet'; page contains a ballot tracker which is the same as the one we noted; page contains voter's username)")
        step_5_page = NormalVoteStep5Page(browser, timeout)
        step_5_page.verify_page(step_3_smart_ballot_tracker_value, settings.VOTER_USERNAME)

        # Here:
        # We can click on the Belenios logo on the top-left of the screen
        # We can click on a link in the footer
        # We can click on the "I cast my vote" button
        # We can click on the "Go back to election" link
        # We can go back. This goes back to the Login page which immediately redirects to this same step 5 page.

        console_log("Click on the 'I cast my vote' button")
        step_5_page.click_on_i_cast_my_vote_button()

        wait_a_bit()

        console_log("## Verify that we are on step 6 and that page content is correct (page contains 'has been accepted'; page contains a ballot tracker which is the same as the one we noted)")
        step_6_page = NormalVoteStep6Page(browser, timeout)
        step_6_page.verify_page(step_3_smart_ballot_tracker_value)

        # Here:
        # We can click on the Belenios logo on the top-left of the screen
        # We can click on a link in the footer
        # We can click on the "ballot box" link
        # We can click on the "Go back to election" link
        # We can go back. This goes to another page which looks like the "Advanced mode" page. This looks like a small bug.

        console_log("## Click on the 'ballot box' link")
        step_6_page.click_on_ballot_box_link()

        wait_a_bit()

        console_log("## Verify that ballot box page contains a link labelled as voter's smart ballot tracker, and click on it")
        ballot_box_page = BallotBoxPage(browser, timeout)
        ballot_box_page.verify_page(step_3_smart_ballot_tracker_value)
        ballot_box_page.click_on_ballot_link(step_3_smart_ballot_tracker_value)

        console_log("## Verify that my ballot page is not an error page")
        verify_page_is_not_an_error_page(browser)
Ejemplo n.º 27
0
        with ConsoleLogDuration("### administrator_does_tallying_of_election"):
            self.administrator_does_tallying_of_election()

        with ConsoleLogDuration("### verify_election_consistency using `belenios_tool verify` (#4)"):
            verify_election_consistency(self.election_id)

        with ConsoleLogDuration("### one_voter_revotes_after_the_election_is_closed"):
            self.one_voter_revotes_after_the_election_is_closed()



if __name__ == "__main__":
    random_seed = os.getenv('RANDOM_SEED', None)
    if not random_seed:
        random_seed = random.randrange(sys.maxsize)
    console_log("Python random seed being used:", random_seed)
    random.seed(random_seed)

    if os.getenv('USE_HEADLESS_BROWSER', None):
        settings.USE_HEADLESS_BROWSER = bool(strtobool(os.getenv('USE_HEADLESS_BROWSER')))

    settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH = os.getenv('SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH', settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH)
    settings.WAIT_TIME_BETWEEN_EACH_STEP = float(os.getenv('WAIT_TIME_BETWEEN_EACH_STEP', settings.WAIT_TIME_BETWEEN_EACH_STEP))
    settings.EXPLICIT_WAIT_TIMEOUT = int(os.getenv('EXPLICIT_WAIT_TIMEOUT', settings.EXPLICIT_WAIT_TIMEOUT))

    if os.getenv('CLEAN_UP_POLICY', None):
        input_clean_up_policy = os.getenv('CLEAN_UP_POLICY')
        if hasattr(settings.CLEAN_UP_POLICIES, input_clean_up_policy):
            settings.CLEAN_UP_POLICY = getattr(settings.CLEAN_UP_POLICIES, input_clean_up_policy)
        else:
            raise Exception("Error: Unknown value for CLEAN_UP_POLICY:", input_clean_up_policy)
Ejemplo n.º 28
0
def smart_monkey_votes(browser,
                       timeout,
                       election_url,
                       voter_username,
                       voter_password,
                       voter_credential,
                       voter_decided_vote=None):
    console_log("## Going to election page:", election_url)
    browser.get(election_url)

    election_home_page_state = ElectionHomePageState(browser, timeout)
    election_home_page_state.page.click_on_language_link("en")
    in_memory = {
        "voter_username": voter_username,
        "voter_password": voter_password,
        "voter_credential": voter_credential,
    }
    if voter_decided_vote:
        in_memory["voter_decided_vote"] = voter_decided_vote
    smart_monkey = SmartMonkeyWithMemoryAndKnownStateMachine(
        election_home_page_state, in_memory=in_memory)
    console_log(f"smart_monkey.current_state: {smart_monkey.current_state}")
    current_iteration = 1
    while not isinstance(smart_monkey.current_state, NormalVoteStep6PageState):
        smart_monkey.verify_page()
        current_iteration += 1
        console_log(f"executing action number {current_iteration}")
        try:
            executed_action = smart_monkey.execute_a_random_action()
            console_log(f"executed action was: {executed_action}")
        except Exception as e:
            console_log(
                f"Exception while executing `smart_monkey.execute_a_random_action()`. Page state was {smart_monkey.current_state} and exception was: {repr(e)}"
            )
            time.sleep(10)
            raise Exception(
                "Exception while executing `smart_monkey.execute_a_random_action()`"
            ) from e
        console_log(
            f"smart_monkey.current_state: {smart_monkey.current_state}")

    if isinstance(smart_monkey.current_state, NormalVoteStep6PageState):
        console_log(
            "Ending monkey behaviour here because we have completed the vote")
        smart_monkey.verify_page()
        console_log(
            "Clicking on the ballot box link and verifying presence of voter's smart ballot tracker"
        )
        smart_monkey.current_state.page.click_on_ballot_box_link()
        ballot_box_page = BallotBoxPage(browser, timeout)
        voter_validated_smart_ballot_tracker = smart_monkey.get_memory_element(
            "voter_validated_smart_ballot_tracker")
        ballot_box_page.verify_page(voter_validated_smart_ballot_tracker)
        return voter_validated_smart_ballot_tracker