Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests against a local instance in the container #3628

Merged
merged 10 commits into from
Jul 26, 2018

Conversation

kushaldas
Copy link
Contributor

Status

Ready for review.

Description of Changes

Fixes #3483 and #3487

If the instance_information.json file does not exists, it starts a local servers and tests against them using Tor Browser.

This PR is on top of #3592 PR, so that has to get in first.

Testing

You can run the functional tests like:

./bin/dev-shell ./bin/run-test --capture=no -v tests/functional/test_submit_and_retrieve_message.py

Deployment

Any special considerations for deployment? Consider both:

  1. Upgrading existing production instances.
  2. New installs.

Checklist

If you made changes to the server application code:

  • Linting (make ci-lint) and tests (make -C securedrop test) pass in the development container

If you made changes to securedrop-admin:

  • Linting and tests (make -C admin test) pass in the admin development container

If you made changes to the system configuration:

If you made non-trivial code changes:

  • I have written a test plan and validated it for this PR

If you made changes to documentation:

  • Doc linting (make docs-lint) passed locally

@kushaldas kushaldas requested a review from conorsch as a code owner July 12, 2018 14:54
@kushaldas kushaldas requested a review from a user July 12, 2018 14:54
@kushaldas
Copy link
Contributor Author

@redshiftzero @msheiny The admin test now creates real users and test those, so it takes more than 10 minutes in total. How to change the CI so that it does not fail for that?

@conorsch
Copy link
Contributor

Ran the entire functional test suite via:

./bin/dev-shell ./bin/run-test --capture=no -v tests/functional/

Astoundingly, only two errors reported!

2 failed, 18 passed, 2 xfailed in 2105.32 seconds

I'll try with subsets of the tests and try to isolate the failure. The failure output is terribly verbose, and I forgot to pipe to less to get a handle on it.

@conorsch
Copy link
Contributor

conorsch commented Jul 12, 2018

In the interest of transparency, I'll keep a running list of which function test files have passed for me, so others can compare the behavior:

  • tests/functional/test_admin_interface.py
  • tests/functional/test_journalist.py
  • tests/functional/test_make_account_changes.py
  • tests/functional/test_source_notfound.py
  • tests/functional/test_source.py
  • tests/functional/test_source_session_timeout.py
  • tests/functional/test_source_warnings.py
  • 🔶 (xfail) tests/functional/test_submission_not_in_memory.py
  • tests/functional/test_submit_and_retrieve_file.py
  • tests/functional/test_submit_and_retrieve_message.py

@conorsch
Copy link
Contributor

Updated test report with what's failing and what's not. @kushaldas please have a look and let me know if your experience has been any different. Haven't investigated the cause of the failures yet—clearly, the warnings on source interface tests will fail due to actual use of Tor Browser 😄—but we should be able to resolve prior to merge.

Reading through the commit history, we should definitely perform some squashing to clarify why changes were made to which files. We'll likely have to do the same when merging tbb-0.9.0 into develop, so I'm willing to wait, but it might be helpful to tackle some of that as part of review here.

As it stands, there's little to no visible justification for the use of a fork for the gnupg pip library. It seems there was trouble with PID lookups in the tests, but more clarification would be helpful. We should seriously scrutinize any changes to a dependency as important as gnupg prior to shipping. Standardizing on this fork would also conflict with #3622, otherwise we'd be maintaining a fork with multiple upstreams.

RUN chown -R $USER_NAME.$USER_NAME /tmp/.local/

RUN wget -O /opt/torsocks_2.2.0-2_amd64.deb http://mirrors.kernel.org/ubuntu/pool/universe/t/torsocks/torsocks_2.2.0-2_amd64.deb
RUN dpkg -i /opt/torsocks_2.2.0-2_amd64.deb && apt-get install -f
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The strategy for installing a more recent version of torsocks fetches the package over HTTP and installs whatever it gets, with no checksum or signature verification beforehand. That's bad. Perhaps we can sidestep the need to fetch a newer version of torsocks entirely if we instead use nc to pass the connection off to tor. Whatever version of nc is in the Trusty repos should be sufficient to pull that off!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@conorsch Can you please help me with that patch? In my mind I would prefer to rebuild and store a version of torsocks somewhere and then pull and use that.

@kushaldas
Copy link
Contributor Author

As it stands, there's little to no visible justification for the use of a fork for the gnupg pip library. It seems there was trouble with PID lookups in the tests, but more clarification would be helpful. We should seriously scrutinize any changes to a dependency as important as gnupg prior to shipping. Standardizing on this fork would also conflict with #3622, otherwise we'd be maintaining a fork with multiple upstreams.

We should try with the latest upstream release and see if that solves our problem. I am also with the idea that maintaining our fork is always difficult.

@kushaldas
Copy link
Contributor Author

Haven't investigated the cause of the failures yet—clearly, the warnings on source interface tests will fail due to actual use of Tor Browser smile—but we should be able to resolve prior to merge.

This is due to the test for orbot and warning.

@kushaldas
Copy link
Contributor Author

I pushed a commit which should fix our orbot related warning test.

@@ -24,6 +24,7 @@ mkdir -p "/tmp/test-results/logs"

: "${PAGE_LAYOUT_LOCALES:=en_US,ar,fr_FR}"
export PAGE_LAYOUT_LOCALES
export TOR_FORCE_NET_CONFIG=0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's document why this was used in a commit message

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind I see you did this! ❤️ :-)

self.gpg = env.init_gpg()
db.create_all()

# Add our test user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we re-use create-dev-data.py for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried, but, could not import from there, that is why added here.

@@ -4,6 +4,7 @@
#
# pip-compile --output-file securedrop/requirements/securedrop-app-code-requirements.txt securedrop/requirements/securedrop-app-code-requirements.in
#
-e git+https://github.com/freedomofpress/python-gnupg.git@af4508260d6eaa2b05efc59f8253585b7be29ad3#egg=gnupg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kushaldas @msheiny: Regarding this psutil issue you both ran into on import of python-gnupg, can you confirm that the issue was due to a zombie process? That is, was the exception raised psutil.ZombieProcess?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if yes, my next question is: why are there so many gpg-agent zombie processes on the system? Was this seen in local machine, in the dev container, CI or some combination of the above?

Making a temporary fork simply for debugging makes a lot of sense 👍. That said, we shouldn't merge the Tor Browser functional testing feature branch with the fork of python-gnupg. Generally, we'll avoid creating a fork of libraries unless it becomes absolutely necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not see any zombie processes. It was trying to access PID 2.

Copy link
Contributor

@redshiftzero redshiftzero Jul 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, hm, what was the psutil exception? NoSuchProcess?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah @redshiftzero -- im pretty certain it was psutil.AccessDenied

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks @msheiny. I was not able to reproduce this issue on macOS on Friday (well, I can artificially generate an exception by putting a breakpoint in the GPGMeta. _find_agent method and killing the process, which produces psutil.NoSuchProcess, but that's not really a reproducer).

The reason I was asking is to understand if the broad exception handling over in isislovecruft/python-gnupg#203 was necessary (or if a different approach would be better), but it seems like the original PR is the right call given that you hit psutil.AccessDenied, and the user in the original issue on FreeBSD (isislovecruft/python-gnupg#201) that was having this issue hit psutil.ZombieProcess

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @redshiftzero! Thanks for alerting me about this issue via email! I get a lot of github notifications and I can't address all of them. Sorry for the delay!

I've merged that PR and a couple more fixes. If there's anything else SecureDrop needs, feel free to ping me. I have a bit of time in the next couple days to fix bugs and/or review patches.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The upstream PR has been merged: isislovecruft/python-gnupg#203 so we're in a better position now to include the new logic, rather than maintaining a fork. My initial understanding of the introduction of this new dependency was that it was required to get the TBB logic working; during sprint planning today, however, @kushaldas indicated that the problem is not related to the TBB work, and can sometimes occur on develop.

One possibility is that the issue only arises on grsecurity-patched workstations, given that CI seems relatively happy, I'm able to run make test on my workstation on the develop branch without error, on a grsecurity-patched workstation, so I'm inclined to say that's not the case. Either way, I'd like to remove this change from the current PR and defer to a separate ticket, so reduce the scope of work we're reviewing and queuing up for a future release.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pleased to report that backing out the gnupg dependency change locally did not break the functional tests. Note that two separate commits had to be reverted to back out the change entirely. It may be that the change was introduced to fix issues with non-functional tests, but I couldn't find any record of that. I'll push up the changes I've made locally to this branch, then continue with the general cleanup and rebase tomorrow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome, thanks @isislovecruft!

@@ -5,7 +5,7 @@ set -euo pipefail

source "${BASH_SOURCE%/*}/dev-deps"

run_xvfb &
#run_xvfb &
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm.. why is this commented out? I didn't see anything in the commit messages about this, apologies if I missed it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this is my mistake. I will clean things out in a commit based on the review.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the the removal of run_xvfb has not yet been addressed; I will attempt patching locally and fix if tests still pass.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can confirm that re-enabling run_xvfb locally does not break functional tests, so will include that modification in the upcoming cleanup.

@redshiftzero
Copy link
Contributor

I'm running into trouble testing this locally, as in all functional tests (that are not xfailed) are failing for me... is a testing step missing?

I am:

  1. Checking out this branch
  2. cd securedrop
  3. ./bin/dev-shell ./bin/run-test --capture=no -v tests/functional/

Running functional test files one at a time also produces the same behavior.

Full output
$ ./bin/dev-shell ./bin/run-test --capture=no -v tests/functional/
Run with DOCKER_BUILD_VERBOSE=true for more information
Docker image build in progress  done !
DEPRECATION WARNING:
Sass 3.5 will no longer support Ruby 1.9.3.
Please upgrade to Ruby 2.0.0 or greater as soon as possible.

      write static/css/journalist.css
      write static/css/journalist.css.map
      write static/css/source.css
      write static/css/source.css.map
========================================================================= test session starts =========================================================================
platform linux2 -- Python 2.7.6, pytest-3.3.2, py-1.5.2, pluggy-0.6.0 -- /usr/bin/python
cachedir: tests/.cache
rootdir: /Users/redshiftzero/Documents/Github/securedrop/securedrop/tests, inifile: pytest.ini
plugins: cov-2.5.1, mock-1.7.1
collected 22 items                                                                                                                                                    

tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_interface FAILED                                                                       [  4%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_edits_hotp_secret FAILED                                                               [  9%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_deletes_user FAILED                                                                    [ 13%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_updates_image FAILED                                                                   [ 18%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_ossec_alert_button FAILED                                                                    [ 22%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_verifies_deletion_of_one_submission_modal FAILED                                           [ 27%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_uses_col_delete_collection_button_modal FAILED                                             [ 31%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_uses_index_delete_collections_button_modal FAILED                                          [ 36%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_interface_ui_with_modal FAILED                                                             [ 40%]
tests/functional/test_make_account_changes.py::TestMakeAccountChanges::test_admin_edit_account_html_template_rendering FAILED                                   [ 45%]
tests/functional/test_source.py::TestSourceInterface::test_lookup_codename_hint FAILED                                                                          [ 50%]
tests/functional/test_source_notfound.py::TestSourceInterfaceNotFound::test_not_found FAILED                                                                    [ 54%]
tests/functional/test_source_session_timeout.py::TestSourceSessions::test_source_session_timeout FAILED                                                         [ 59%]
tests/functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_appears_if_tor_browser_not_in_use FAILED                              [ 63%]
tests/functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_appears_if_orbot_is_used FAILED                                       [ 68%]
tests/functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_high_security FAILED                                                  [ 72%]
tests/functional/test_submission_not_in_memory.py::TestSubmissionNotInMemory::test_message_is_not_retained_in_memory xfail                                      [ 77%]
tests/functional/test_submission_not_in_memory.py::TestSubmissionNotInMemory::test_file_upload_is_not_retained_in_memory xfail                                  [ 81%]
tests/functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_submit_and_retrieve_happy_path FAILED                                        [ 86%]
tests/functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_source_cancels_at_login_page FAILED                                          [ 90%]
tests/functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_source_cancels_at_submit_page FAILED                                         [ 95%]
tests/functional/test_submit_and_retrieve_message.py::TestSubmitAndRetrieveMessage::test_submit_and_retrieve_happy_path FAILED                                  [100%]Coverage.py warning: Couldn't read data from '/Users/redshiftzero/Documents/Github/securedrop/securedrop/.coverage.c37f03d8dbc2.21600.636140': CoverageException: Doesn't seem to be a coverage.py data file


----------------------------------------------------------- generated xml file: /tmp/test-results/junit.xml -----------------------------------------------------------

---------- coverage: platform linux2, python 2.7.6-final-0 -----------
Name                                   Stmts   Miss Branch BrPart  Cover   Missing
----------------------------------------------------------------------------------
config.py                                 41      3      6      3    87%   52, 55-58, 50->52, 53->55, 59->69
create-dev-data.py                        42     42      2      0     0%   4-68
crypto_util.py                           100     69     36      1    24%   22, 55-81, 86-92, 105-121, 126-128, 132, 142-144, 168-170, 178-186, 190-194, 198-219, 230-232, 244-249, 17->22
db.py                                      2      0      0      0   100%
i18n.py                                   78     59     38      0    16%   42-70, 81-109, 113, 122-138, 147-154, 158-164, 168
i18n_tool.py                             188    188     54      0     0%   4-365
journalist.py                              3      3      0      0     0%   3-7
journalist_app/__init__.py                80     61     18      1    20%   28, 35-148, 23->28
journalist_app/account.py                 44     39     10      0     9%   13-71
journalist_app/admin.py                  150    139     38      0     6%   20-238
journalist_app/col.py                     48     40      6      0    15%   18-86
journalist_app/decorators.py              11      6      2      0    38%   11-19
journalist_app/forms.py                   23      5      4      0    67%   14-16, 24-25
journalist_app/main.py                    98     88     30      0     8%   19-198
journalist_app/utils.py                  155    126     36      1    16%   26, 38, 42-54, 60-64, 76-111, 121-144, 158-168, 174-184, 188, 195-200, 204-209, 213-217, 221-225, 230-240, 245-253, 258-267, 271-290, 299-310, 315-321, 21->26
manage.py                                226    226     36      0     0%   4-395
management/__init__.py                     0      0      0      0   100%
management/run.py                         14     14      2      0     0%   1-43
models.py                                249    130     56      1    39%   15-16, 37-46, 70-71, 74, 78-79, 83-93, 99-103, 120-122, 126, 150-153, 157, 167-170, 173-174, 210, 213-216, 249-255, 258, 263, 268-270, 276-283, 287-288, 295-304, 308-312, 317, 320-326, 330-333, 337-340, 344-357, 364-366, 371, 374-394, 402-413, 420-438, 452, 32->36
qa_loader.py                             142    142     36      0     0%   4-239
request_that_secures_file_uploads.py      10      4      2      0    50%   20-28, 31
rm.py                                      4      2      0      0    50%   23-24
sdconfig.py                              119     47      2      1    60%   12, 21-22, 27-28, 32-33, 57-58, 62-63, 67-68, 72-73, 77-78, 82-83, 87-88, 92-93, 97-98, 102-103, 107-108, 112-113, 118-119, 124-125, 129-130, 135-136, 140-141, 145-146, 150-151, 160-161, 7->12
secure_tempfile.py                        51     31     10      0    33%   48-54, 64-66, 72-74, 82-89, 109-118, 125-132
source.py                                  3      3      0      0     0%   3-7
source_app/__init__.py                    89     67     14      1    22%   31, 36-174, 26->31
source_app/api.py                         11      7      0      0    36%   9-20
source_app/decorators.py                  15     10      4      0    26%   8-13, 19-24
source_app/forms.py                        7      0      0      0   100%
source_app/info.py                        14     11      0      0    21%   8-31
source_app/main.py                       142    128     36      0     8%   22-262
source_app/utils.py                       57     37      8      0    31%   18, 22-31, 36-60, 64-65, 70-71, 80-95, 104-111
store.py                                  85     66     28      0    17%   30-40, 52-68, 74-77, 81-109, 113-146, 150-153, 159-174
template_filters.py                       26     18      6      0    25%   11-17, 21-24, 28-47
version.py                                 1      0      0      0   100%
worker.py                                  7      1      0      0    86%   14
----------------------------------------------------------------------------------
TOTAL                                   2335   1812    520      9    19%
Coverage annotated source written to dir /tmp/test-results/cov_annotate
Coverage HTML written to dir /tmp/test-results/cov_html
Coverage XML written to file /tmp/test-results/cov.xml

====================================================================== slowest 10 test durations ======================================================================
21.26s setup    functional/test_admin_interface.py::TestAdminInterface::test_admin_interface
12.97s setup    functional/test_admin_interface.py::TestAdminInterface::test_admin_updates_image
12.95s setup    functional/test_admin_interface.py::TestAdminInterface::test_ossec_alert_button
12.93s setup    functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_submit_and_retrieve_happy_path
12.76s setup    functional/test_submit_and_retrieve_message.py::TestSubmitAndRetrieveMessage::test_submit_and_retrieve_happy_path
12.57s setup    functional/test_journalist.py::TestJournalist::test_journalist_uses_col_delete_collection_button_modal
12.57s setup    functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_source_cancels_at_submit_page
12.54s setup    functional/test_journalist.py::TestJournalist::test_journalist_verifies_deletion_of_one_submission_modal
12.43s setup    functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_appears_if_orbot_is_used
12.40s setup    functional/test_journalist.py::TestJournalist::test_journalist_uses_index_delete_collections_button_modal
============================================================================== FAILURES ===============================================================================
_______________________________________________________________ TestAdminInterface.test_admin_interface _______________________________________________________________

self = <tests.functional.test_admin_interface.TestAdminInterface object at 0x7ff67f8b2e10>

    def test_admin_interface(self):
>       self._admin_logs_in()

/Users/redshiftzero/Documents/Github/securedrop/securedrop/tests/functional/test_admin_interface.py:10: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/redshiftzero/Documents/Github/securedrop/securedrop/tests/functional/journalist_navigation_steps.py:216: in _admin_logs_in
    self._login_user(self.admin, self.admin_pw, self.admin_user['totp'])
/Users/redshiftzero/Documents/Github/securedrop/securedrop/tests/functional/journalist_navigation_steps.py:85: in _login_user
    self._try_login_user(username, password, token)
/Users/redshiftzero/Documents/Github/securedrop/securedrop/tests/functional/journalist_navigation_steps.py:76: in _try_login_user
    self._input_text_in_login_form(username, password, token)
/Users/redshiftzero/Documents/Github/securedrop/securedrop/tests/functional/journalist_navigation_steps.py:62: in _input_text_in_login_form
    self.driver.get(self.journalist_location + "/login")
/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py:332: in get
    self.execute(Command.GET, {'url': url})
/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py:320: in execute
    self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7ff67f892790>
response = {'status': 500, 'value': '{"value":{"error":"unknown error","message":"Reached error page: about:neterror?e=connection...s::imp::thread::{{impl}}::new::thread_start\n                        at /checkout/src/libstd/sys/unix/thread.rs:84"}}'}

    def check_response(self, response):
        """
            Checks that a JSON response from the WebDriver does not have an error.
    
            :Args:
             - response - The JSON response from the WebDriver server as a dictionary
               object.
    
            :Raises: If the response contains an error message.
            """
        status = response.get('status', None)
        if status is None or status == ErrorCode.SUCCESS:
            return
        value = None
        message = response.get("message", "")
        screen = response.get("screen", "")
        stacktrace = None
        if isinstance(status, int):
            value_json = response.get('value', None)
            if value_json and isinstance(value_json, basestring):
                import json
                try:
                    value = json.loads(value_json)
                    if len(value.keys()) == 1:
                        value = value['value']
                    status = value.get('error', None)
                    if status is None:
                        status = value["status"]
                        message = value["value"]
                        if not isinstance(message, basestring):
                            value = message
                            message = message.get('message')
                    else:
                        message = value.get('message', None)
                except ValueError:
                    pass
    
        exception_class = ErrorInResponseException
        if status in ErrorCode.NO_SUCH_ELEMENT:
            exception_class = NoSuchElementException
        elif status in ErrorCode.NO_SUCH_FRAME:
            exception_class = NoSuchFrameException
        elif status in ErrorCode.NO_SUCH_WINDOW:
            exception_class = NoSuchWindowException
        elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
            exception_class = StaleElementReferenceException
        elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
            exception_class = ElementNotVisibleException
        elif status in ErrorCode.INVALID_ELEMENT_STATE:
            exception_class = InvalidElementStateException
        elif status in ErrorCode.INVALID_SELECTOR \
                or status in ErrorCode.INVALID_XPATH_SELECTOR \
                or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
            exception_class = InvalidSelectorException
        elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
            exception_class = ElementNotSelectableException
        elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
            exception_class = ElementNotInteractableException
        elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
            exception_class = InvalidCookieDomainException
        elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
            exception_class = UnableToSetCookieException
        elif status in ErrorCode.TIMEOUT:
            exception_class = TimeoutException
        elif status in ErrorCode.SCRIPT_TIMEOUT:
            exception_class = TimeoutException
        elif status in ErrorCode.UNKNOWN_ERROR:
            exception_class = WebDriverException
        elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
            exception_class = UnexpectedAlertPresentException
        elif status in ErrorCode.NO_ALERT_OPEN:
            exception_class = NoAlertPresentException
        elif status in ErrorCode.IME_NOT_AVAILABLE:
            exception_class = ImeNotAvailableException
        elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
            exception_class = ImeActivationFailedException
        elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
            exception_class = MoveTargetOutOfBoundsException
        elif status in ErrorCode.JAVASCRIPT_ERROR:
            exception_class = JavascriptException
        elif status in ErrorCode.SESSION_NOT_CREATED:
            exception_class = SessionNotCreatedException
        elif status in ErrorCode.INVALID_ARGUMENT:
            exception_class = InvalidArgumentException
        elif status in ErrorCode.NO_SUCH_COOKIE:
            exception_class = NoSuchCookieException
        elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
            exception_class = ScreenshotException
        elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
            exception_class = ElementClickInterceptedException
        elif status in ErrorCode.INSECURE_CERTIFICATE:
            exception_class = InsecureCertificateException
        elif status in ErrorCode.INVALID_COORDINATES:
            exception_class = InvalidCoordinatesException
        elif status in ErrorCode.INVALID_SESSION_ID:
            exception_class = InvalidSessionIdException
        elif status in ErrorCode.UNKNOWN_METHOD:
            exception_class = UnknownMethodException
        else:
            exception_class = WebDriverException
        if value == '' or value is None:
            value = response['value']
        if isinstance(value, basestring):
            if exception_class == ErrorInResponseException:
                raise exception_class(response, value)
            raise exception_class(value)
        if message == "" and 'message' in value:
            message = value['message']
    
        screen = None
        if 'screen' in value:
            screen = value['screen']
    
        stacktrace = None
        if 'stackTrace' in value and value['stackTrace']:
            stacktrace = []
            try:
                for frame in value['stackTrace']:
                    line = self._value_or_default(frame, 'lineNumber', '')
                    file = self._value_or_default(frame, 'fileName', '<anonymous>')
                    if line:
                        file = "%s:%s" % (file, line)
                    meth = self._value_or_default(frame, 'methodName', '<anonymous>')
                    if 'className' in frame:
                        meth = "%s.%s" % (frame['className'], meth)
                    msg = "    at %s (%s)"
                    msg = msg % (meth, file)
                    stacktrace.append(msg)
            except TypeError:
                pass
        if exception_class == ErrorInResponseException:
            raise exception_class(response, message)
        elif exception_class == UnexpectedAlertPresentException:
            alert_text = None
            if 'data' in value:
                alert_text = value['data'].get('text')
            elif 'alert' in value:
                alert_text = value['alert'].get('text')
            raise exception_class(message, screen, stacktrace, alert_text)
>       raise exception_class(message, screen, stacktrace)
E       WebDriverException: Message: Reached error page: about:neterror?e=connectionFailure&u=http%3A//127.0.0.1%3A8081/login&c=UTF-8&f=regular&d=Firefox%20can%E2%80%99t%20establish%20a%20connection%20to%20the%20server%20at%20127.0.0.1%3A8081.

/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py:242: WebDriverException
------------------------------------------------------------------------- Captured log setup --------------------------------------------------------------------------
__init__.py                110 DEBUG    param: "['Xvfb', '-help']" 
__init__.py                111 DEBUG    command: ['Xvfb', '-help']
__init__.py                112 DEBUG    joined command: Xvfb -help
__init__.py                232 DEBUG    process was started (pid=26)
__init__.py                316 DEBUG    process has ended
__init__.py                320 DEBUG    return code=0
__init__.py                326 DEBUG    stdout=
__init__.py                327 DEBUG    stderr=use: X [:<display>] [option]
-a #                   default pointer acceleration (factor)
-ac                    disable access control restrictions
-audit int             set audit trail level
-auth file             select authorization file
-br                    create root window with black background
+bs                    enable any backing store support
-bs                    disable any backing store support
-c                     turns off key-click
c #                    key-click volume (0-100)
-cc int                default color visual class
-nocursor              disable the cursor
-core                  generate core dump on fatal error
-dpi int               screen resolution in dots per inch
-dpms                  disables VESA DPMS monitor control
-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs
-f #                   bell base (0-100)
-fc string             cursor font
-fn string             default font name
-fp string             default font path
-help                  prints message with these options
-I                     ignore all remaining arguments
-ld int                limit data space to N Kb
-lf int                limit number of open files to N
-ls int                limit stack space to N Kb
-nolock                disable the locking mechanism
-nolisten string       don't listen on protocol
-noreset               don't reset after last client exists
-background [none]     create root window with no background
-reset                 reset after last client exists
-p #                   screen-saver pattern duration (minutes)
-pn                    accept failure to listen on all ports
-nopn                  reject failure to listen on all ports
-r                     turns off auto-repeat
r                      turns on auto-repeat 
-render [default|mono|gray|color] set render color alloc policy
-retro                 start with classic stipple and cursor
-s #                   screen-saver timeout (minutes)
-seat string           seat to run on
-t #                   default pointer threshold (pixels/t)
-terminate             terminate at server reset
-to #                  connection time out
-tst                   disable testing extensions
ttyxx                  server started from init on /dev/ttyxx
v                      video blanking for screen-saver
-v                     screen-saver without video blanking
-wm                    WhenMapped default backing-store
-wr                    create root window with white background
-maxbigreqsize         set maximal bigrequest size 
+xinerama              Enable XINERAMA extension
-xinerama              Disable XINERAMA extension
-dumbSched             Disable smart scheduling, enable old behavior
-schedInterval int     Set scheduler interval in msec
-sigstop               Enable SIGSTOP based startup
+extension name        Enable extension
-extension name        Disable extension
-query host-name       contact named host for XDMCP
-broadcast             broadcast for XDMCP
-multicast [addr [hops]] IPv6 multicast for XDMCP
-indirect host-name    contact named host for indirect XDMCP
-port port-num         UDP port number to send messages to
-from local-address    specify the local address to connect from
-once                  Terminate server after one session
-class display-class   specify display class to send in manage
-cookie xdm-auth-bits  specify the magic cookie for XDMCP
-displayID display-id  manufacturer display ID for request
[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]
                       enable/disable accessx key sequences
-ardelay               set XKB autorepeat delay
-arinterval            set XKB autorepeat interval
-screen scrn WxHxD     set screen's width, height, depth
-pixdepths list-of-int support given pixmap depths
+/-render		   turn on/off RENDER extension support(default on)
-linebias n            adjust thin line pixelization
-blackpixel n          pixel value for black
-whitepixel n          pixel value for white
-fbdir directory       put framebuffers in mmap'ed files in directory
-shmem                 put framebuffers in shared memory
__init__.py                110 DEBUG    param: "['xauth', '-h']" 
__init__.py                111 DEBUG    command: ['xauth', '-h']
__init__.py                112 DEBUG    joined command: xauth -h
__init__.py                232 DEBUG    process was started (pid=27)
__init__.py                316 DEBUG    process has ended
__init__.py                320 DEBUG    return code=1
__init__.py                326 DEBUG    stdout=
__init__.py                327 DEBUG    stderr=usage:  xauth [-options ...] [command arg ...]

where options include:
    -f authfilename                name of authority file to use
    -v                             turn on extra messages
    -q                             turn off extra messages
    -i                             ignore locks on authority file
    -b                             break locks on authority file

and commands have the following syntax:

    add dpyname protoname hexkey   add entry
    exit                           save changes and exit program
    extract filename dpyname...    extract entries into file
    help [topic]                   print help
    info                           print information about entries
    list [dpyname...]              list entries
    merge filename...              merge entries from files
    nextract filename dpyname...   numerically extract entries
    nlist [dpyname...]             numerically list entries
    nmerge filename...             numerically merge entries
    quit                           abort changes and exit program
    remove dpyname...              remove entries
    source filename                read commands from file
    ?                              list available commands
    generate dpyname protoname [options]  use server to generate entry
    options are:
      timeout n    authorization expiration time in seconds
      trusted      clients using this entry are trusted
      untrusted    clients using this entry are untrusted
      group n      clients using this entry belong to application group n
      data hexkey  auth protocol specific data needed to generate the entry


A dash may be used with the "merge" and "source" to read from the
standard input.  Commands beginning with "n" use numeric format.

__init__.py                110 DEBUG    param: "['Xvfb', '-br', '-nolisten', 'tcp', '-screen', '0', '1280x800x24', ':1000']" 
__init__.py                111 DEBUG    command: ['Xvfb', '-br', '-nolisten', 'tcp', '-screen', '0', '1280x800x24', ':1000']
__init__.py                112 DEBUG    joined command: Xvfb -br -nolisten tcp -screen 0 1280x800x24 :1000
__init__.py                110 DEBUG    param: "['xauth', '-h']" 
__init__.py                111 DEBUG    command: ['xauth', '-h']
__init__.py                112 DEBUG    joined command: xauth -h
__init__.py                232 DEBUG    process was started (pid=28)
__init__.py                316 DEBUG    process has ended
__init__.py                320 DEBUG    return code=1
__init__.py                326 DEBUG    stdout=
__init__.py                327 DEBUG    stderr=usage:  xauth [-options ...] [command arg ...]

where options include:
    -f authfilename                name of authority file to use
    -v                             turn on extra messages
    -q                             turn off extra messages
    -i                             ignore locks on authority file
    -b                             break locks on authority file

and commands have the following syntax:

    add dpyname protoname hexkey   add entry
    exit                           save changes and exit program
    extract filename dpyname...    extract entries into file
    help [topic]                   print help
    info                           print information about entries
    list [dpyname...]              list entries
    merge filename...              merge entries from files
    nextract filename dpyname...   numerically extract entries
    nlist [dpyname...]             numerically list entries
    nmerge filename...             numerically merge entries
    quit                           abort changes and exit program
    remove dpyname...              remove entries
    source filename                read commands from file
    ?                              list available commands
    generate dpyname protoname [options]  use server to generate entry
    options are:
      timeout n    authorization expiration time in seconds
      trusted      clients using this entry are trusted
      untrusted    clients using this entry are untrusted
      group n      clients using this entry belong to application group n
      data hexkey  auth protocol specific data needed to generate the entry


A dash may be used with the "merge" and "source" to read from the
standard input.  Commands beginning with "n" use numeric format.

__init__.py                110 DEBUG    param: "['Xvfb', '-br', '-nolisten', 'tcp', '-screen', '0', '1280x800x24', ':1001']" 
__init__.py                111 DEBUG    command: ['Xvfb', '-br', '-nolisten', 'tcp', '-screen', '0', '1280x800x24', ':1001']
__init__.py                112 DEBUG    joined command: Xvfb -br -nolisten tcp -screen 0 1280x800x24 :1001
__init__.py                232 DEBUG    process was started (pid=29)
abstractdisplay.py          90 DEBUG    DISPLAY=:1001
remote_connection.py       486 DEBUG    POST http://127.0.0.1:38201/session {"capabilities": {"alwaysMatch": {"acceptInsecureCerts": true, "browserName": "firefox", "moz:firefoxOptions": {"binary": "/usr/lib/firefox-esr/firefox-esr"}}, "firstMatch": [{}]}, "desiredCapabilities": {"acceptInsecureCerts": true, "browserName": "firefox", "moz:firefoxOptions": {"binary": "/usr/lib/firefox-esr/firefox-esr"}, "marionette": true}}
remote_connection.py       543 DEBUG    {"value": {"sessionId":"53d057a3-b588-430b-bed3-a843ed896ebc","capabilities":{"acceptInsecureCerts":true,"browserName":"firefox","browserVersion":"52.9.0","moz:accessibilityChecks":false,"moz:processID":46,"moz:profile":"/tmp/rust_mozprofile.vTqxxv6h8zJP","pageLoadStrategy":"normal","platformName":"linux","platformVersion":"4.9.87-linuxkit-aufs","rotatable":false,"specificationLevel":0,"timeouts":{"implicit":0,"page load":300000,"script":30000}}}}
remote_connection.py       574 DEBUG    Finished Request
remote_connection.py       486 DEBUG    POST http://127.0.0.1:38201/session/53d057a3-b588-430b-bed3-a843ed896ebc/timeouts {"implicit": 15000}
remote_connection.py       543 DEBUG    {"value": {}}
remote_connection.py       574 DEBUG    Finished Request
remote_connection.py       486 DEBUG    POST http://127.0.0.1:54105/session {"capabilities": {"alwaysMatch": {"acceptInsecureCerts": true, "browserName": "firefox", "moz:firefoxOptions": {"profile": " 
[...crazy amounts of base64 snipped...]

@conorsch
Copy link
Contributor

@redshiftzero Technically I messed with my virtualenv a bit while reviewing the various TBB-related branches recently. I don't expect it created a divergence, but let me purge my venv and recreate, to see if I can reproduce your trouble. The description you provide is somewhat similar to the problems I had in #3488 (comment). Will report back on results of fresh venv.



Update this information to the `functional/instance_infomration.json file.
Update this information to the `tests/functional/instance_infomration.json file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit typo :) s/instance_infomration.json/instance_information.json/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instance_information.json typo is still present in this branch, and in fact preventing me from located the docs when I first tried to test here. Will include in upcoming cleanup commits.

@@ -4,6 +4,7 @@
#
# pip-compile --output-file securedrop/requirements/securedrop-app-code-requirements.txt securedrop/requirements/securedrop-app-code-requirements.in
#
-e git+https://github.com/freedomofpress/python-gnupg.git@af4508260d6eaa2b05efc59f8253585b7be29ad3#egg=gnupg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah @redshiftzero -- im pretty certain it was psutil.AccessDenied

@conorsch
Copy link
Contributor

let me purge my venv and recreate, to see if I can reproduce your trouble.

@redshiftzero After cloning fresh from @kushaldas's fork and creating a new virtualenv, I am able to run the entire functional test suite with only a single failure. As @kushaldas noted in standup, perhaps you have a dangling instance_config.json? Clean it up if so. If not, try from a fresh clone as I did and report any trouble!

@kushaldas
Copy link
Contributor Author

In my latest run:

================================================================= slowest 10 test durations ==================================================================
509.59s call     functional/test_admin_interface.py::TestAdminInterface::test_admin_interface
135.78s call     functional/test_make_account_changes.py::TestMakeAccountChanges::test_admin_edit_account_html_template_rendering
74.17s call     functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_submit_and_retrieve_happy_path
65.69s call     functional/test_journalist.py::TestJournalist::test_journalist_verifies_deletion_of_one_submission_modal
51.87s call     functional/test_journalist.py::TestJournalist::test_journalist_uses_index_delete_collections_button_modal
49.92s call     functional/test_source.py::TestSourceInterface::test_lookup_codename_hint
46.58s setup    functional/test_admin_interface.py::TestAdminInterface::test_admin_interface
40.41s call     functional/test_journalist.py::TestJournalist::test_journalist_uses_col_delete_collection_button_modal
31.27s call     functional/test_admin_interface.py::TestAdminInterface::test_admin_deletes_user
25.89s call     functional/test_submit_and_retrieve_message.py::TestSubmitAndRetrieveMessage::test_submit_and_retrieve_happy_path
========================================================== 20 passed, 2 xfailed in 1601.28 seconds ===========================================================```

@kushaldas
Copy link
Contributor Author

Will update the branch based on the review comments tomorrow morning my time.

@redshiftzero
Copy link
Contributor

redshiftzero commented Jul 17, 2018

yep instance_information.json in my local dir was the issue, all functional tests are passing for me on latest 🤘

@redshiftzero
Copy link
Contributor

I've:

  • rebased the base branch tbb-0.9.0 onto latest develop on the freedomofpress remote
  • then rebased the local_tests on @kushaldas' remote onto latest tbb-0.9.0

@redshiftzero
Copy link
Contributor

redshiftzero commented Jul 18, 2018

Note that to close #3483, functional tests must pass for:

  • running tests against a local server
  • against an external server (looks like this hasn't been tested yet, correct me if I'm wrong)

It's unclear what is going on with the test failures that are still occurring in CI after rebase. I do not see those failures locally. Investigating..


# Set window size and position explicitly to avoid potential bugs due
# to discrepancies between environments.
#self.driver.set_window_position(0, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to remove this? Standardizing this prevents us from having divergent window sizes between CI and dev that can produce CI test failures that are annoying to debug

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can get these back into the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finally figured out why i had to comment that out. mozilla/geckodriver#676 is causing the trouble as we have to test against the firefox 52esr in this branch. None of those position calls are working in this. @redshiftzero

@@ -8,7 +8,6 @@
# We'll catch that error and respond accordingly in the next task.
failed_when: false
register: paxctl_firefox_header_check
when: ansible_kernel.endswith('-grsec')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it necessary to remove this? (while the app-test role is used in staging, which does use grsec kernels, it doesn't hurt to leave this in explicitly no? Or did this produce some other issue?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I see. For other reviewers, the when condition was duplicated (see below)

@conorsch
Copy link
Contributor

Can now report that all functional tests are passing locally. We're still having CI woes, which I propose we handle separately. Merging this PR as-is will not break develop, as it's target a long-lived feature branch. For the next sprint, we should drill down on the CI problems to resolve the container logic, as we've done with the other test suites already.

It's also worth noting that there are a number of debugging/WIP commits in this branch. Those should absolutely be cleaned up, i.e. via interactive rebase, prior to landing in develop. As we're closing out a sprint right now, I suggest we merge as-is, and focus on the rebase in the freedomofpress:tbb-0.9.0 branch.

So, next steps required are:

@kushaldas
Copy link
Contributor Author

I just figured that #1502 will also get closed when we merge this.

@eloquence
Copy link
Member

Most of the tests passed for me, but I got one "Broken pipe" exception and a couple of test failures like this:

chown: cannot access '/tmp/core_dump.4522': No such file or directory
xfail [ 77%]
Full output
Run with DOCKER_BUILD_VERBOSE=true for more information
Docker image build in progress ........................................................................... done !
DEPRECATION WARNING:
Sass 3.5 will no longer support Ruby 1.9.3.
Please upgrade to Ruby 2.0.0 or greater as soon as possible.

      write static/css/journalist.css
      write static/css/journalist.css.map
      write static/css/source.css
      write static/css/source.css.map
====================================================== test session starts =======================================================
platform linux2 -- Python 2.7.6, pytest-3.3.2, py-1.5.2, pluggy-0.6.0 -- /usr/bin/python
cachedir: tests/.cache
rootdir: /home/erik/Code/securedrop/securedrop/tests, inifile: pytest.ini
plugins: cov-2.5.1, mock-1.7.1
collected 22 items                                                                                                               

tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_interface --------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 671216
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'dellsberg' logged in with the token 143781
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 787762
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'dellsberg2' logged in with the token 816403
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 382883
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'dellsberg2' logged in with the token 953601
--------------------------------------------------------------------------------
PASSED                                  [  4%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_edits_hotp_secret Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 477545
--------------------------------------------------------------------------------
PASSED                          [  9%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_deletes_user Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 629010
--------------------------------------------------------------------------------
PASSED                               [ 13%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_admin_updates_image Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 133277
--------------------------------------------------------------------------------
PASSED                              [ 18%]
tests/functional/test_admin_interface.py::TestAdminInterface::test_ossec_alert_button Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 630533
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
ERROR in admin [/home/erik/Code/securedrop/securedrop/journalist_app/admin.py:233]:
This is a test OSSEC alert
--------------------------------------------------------------------------------
PASSED                               [ 22%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_verifies_deletion_of_one_submission_modal Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 513091
--------------------------------------------------------------------------------
PASSED      [ 27%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_uses_col_delete_collection_button_modal Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 756274
--------------------------------------------------------------------------------
PASSED        [ 31%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_uses_index_delete_collections_button_modal Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 304842
--------------------------------------------------------------------------------
PASSED     [ 36%]
tests/functional/test_journalist.py::TestJournalist::test_journalist_interface_ui_with_modal Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 895092
--------------------------------------------------------------------------------
PASSED                        [ 40%]
tests/functional/test_make_account_changes.py::TestMakeAccountChanges::test_admin_edit_account_html_template_rendering Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 799287
--------------------------------------------------------------------------------
PASSED [ 45%]
tests/functional/test_source.py::TestSourceInterface::test_lookup_codename_hint Test user already added
PASSED                                     [ 50%]
tests/functional/test_source_notfound.py::TestSourceInterfaceNotFound::test_not_found Test user already added
PASSED                               [ 54%]
tests/functional/test_source_session_timeout.py::TestSourceSessions::test_source_session_timeout Test user already added
PASSED                    [ 59%]
tests/functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_appears_if_tor_browser_not_in_use Test user already added
PASSED [ 63%]
tests/functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_appears_if_orbot_is_used Test user already added
PASSED  [ 68%]
tests/functional/test_source_warnings.py::TestSourceInterfaceBannerWarnings::test_warning_high_security Test user already added
PASSED             [ 72%]
tests/functional/test_submission_not_in_memory.py::TestSubmissionNotInMemory::test_message_is_not_retained_in_memory Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
chown: cannot access '/tmp/core_dump.4522': No such file or directory
xfail [ 77%]
tests/functional/test_submission_not_in_memory.py::TestSubmissionNotInMemory::test_file_upload_is_not_retained_in_memory Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
chown: cannot access '/tmp/core_dump.4808': No such file or directory
xfail [ 81%]
tests/functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_submit_and_retrieve_happy_path Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 025064
--------------------------------------------------------------------------------
PASSED   [ 86%]
tests/functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_source_cancels_at_login_page Test user already added
PASSED     [ 90%]
tests/functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_source_cancels_at_submit_page Test user already added
PASSED    [ 95%]----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 51186)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 651, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 710, in finish
    self.wfile.close()
  File "/usr/lib/python2.7/socket.py", line 279, in close
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------

tests/functional/test_submit_and_retrieve_message.py::TestSubmitAndRetrieveMessage::test_submit_and_retrieve_happy_path Test user already added
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/source_app/main.py:191]:
generating key, entropy: 8192
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INFO in main [/home/erik/Code/securedrop/securedrop/journalist_app/main.py:30]:
'journalist' logged in with the token 826441
--------------------------------------------------------------------------------
PASSED [100%]

---------------------------------------- generated xml file: /tmp/test-results/junit.xml -----------------------------------------

---------- coverage: platform linux2, python 2.7.6-final-0 -----------
Name                                   Stmts   Miss Branch BrPart  Cover   Missing
----------------------------------------------------------------------------------
config.py                                 41      3      6      3    87%   51, 54-57, 49->51, 52->54, 58->67
create-dev-data.py                        42     42      2      0     0%   4-68
crypto_util.py                           100     50     36      2    38%   22, 86, 104-120, 125-127, 131, 141-143, 167-169, 177-185, 188-192, 196-217, 228-230, 242-247, 17->22, 85->86
db.py                                      2      0      0      0   100%
i18n.py                                   78     42     38      6    40%   55, 81-109, 113, 123, 126, 133, 147-154, 158-164, 168, 44->51, 54->55, 70->exit, 122->123, 125->126, 132->133
i18n_tool.py                             188    188     54      0     0%   4-365
journalist.py                              3      3      0      0     0%   3-7
journalist_app/__init__.py                80     32     18      3    52%   28, 49, 78-81, 89-91, 103-109, 114-140, 23->28, 45->49, 88->89
journalist_app/account.py                 44     32     10      0    22%   17-18, 23-35, 39-50, 54-57, 61-69
journalist_app/admin.py                  150    115     38      0    19%   25-26, 31-48, 53-97, 104-120, 125-130, 135-144, 149-180, 186-193, 198-216, 221-228, 233-236
journalist_app/col.py                     48     32      6      0    30%   22-24, 28-30, 34-37, 43-48, 52-67, 72-83
journalist_app/decorators.py              11      4      2      0    54%   13-17
journalist_app/forms.py                   23      5      4      0    67%   14-16, 24-25
journalist_app/main.py                    98     77     30      0    16%   23-40, 44-46, 50-54, 58-77, 96-131, 135-137, 142-164, 168-183, 187-196
journalist_app/utils.py                  155    126     36      1    16%   26, 38, 42-54, 60-64, 76-111, 121-144, 158-168, 174-184, 188, 195-200, 204-209, 213-217, 221-225, 230-240, 245-253, 258-267, 271-290, 299-310, 315-321, 21->26
manage.py                                226    226     36      0     0%   4-395
management/__init__.py                     0      0      0      0   100%
management/run.py                         14     14      2      0     0%   1-43
models.py                                249    113     56      8    47%   15-16, 34-43, 67-68, 71, 75-76, 80-90, 96-100, 117-119, 123, 147-150, 154, 164-167, 170-171, 207, 210-213, 252, 255, 277, 285, 293, 297, 301, 305-309, 314, 317-323, 327-330, 334-337, 341-354, 361-363, 368, 371-391, 399-410, 417-435, 449, 29->33, 251->252, 265->267, 276->277, 284->285, 292->293, 296->297, 300->301
qa_loader.py                             142    142     36      0     0%   4-239
request_that_secures_file_uploads.py      10      4      2      0    50%   20-28, 31
rm.py                                      4      2      0      0    50%   23-24
sdconfig.py                              119     47      2      1    60%   12, 21-22, 27-28, 32-33, 57-58, 62-63, 67-68, 72-73, 77-78, 82-83, 87-88, 92-93, 97-98, 102-103, 107-108, 112-113, 118-119, 124-125, 129-130, 135-136, 140-141, 145-146, 150-151, 160-161, 7->12
secure_tempfile.py                        51     31     10      0    33%   48-54, 64-66, 72-74, 82-89, 109-118, 125-132
source.py                                  3      3      0      0     0%   3-7
source_app/__init__.py                    89     32     14      3    60%   31, 52, 80-83, 94-96, 114-115, 128-164, 168, 172, 26->31, 48->52, 93->94
source_app/api.py                         11      4      0      0    64%   13-18
source_app/decorators.py                  15      6      4      0    47%   10-12, 21-23
source_app/forms.py                        7      0      0      0   100%
source_app/info.py                        14      5      0      0    64%   12, 16, 20-22, 29
source_app/main.py                       142    112     36      0    17%   26, 30-41, 45-49, 53-73, 78-112, 124-201, 206-214, 219-231, 235-246, 250-260
source_app/utils.py                       57     37      8      0    31%   18, 22-31, 36-60, 64-65, 70-71, 80-95, 104-111
store.py                                  85     61     28      2    23%   31, 36, 52-68, 74-77, 81-109, 113-146, 150-153, 159-174, 30->31, 35->36
template_filters.py                       26     18      6      0    25%   11-17, 21-24, 28-47
version.py                                 1      0      0      0   100%
worker.py                                  7      1      0      0    86%   14
----------------------------------------------------------------------------------
TOTAL                                   2335   1609    520     29    27%
Coverage annotated source written to dir /tmp/test-results/cov_annotate
Coverage HTML written to dir /tmp/test-results/cov_html
Coverage XML written to file /tmp/test-results/cov.xml

=================================================== slowest 10 test durations ====================================================
506.47s call     functional/test_admin_interface.py::TestAdminInterface::test_admin_interface
134.75s call     functional/test_make_account_changes.py::TestMakeAccountChanges::test_admin_edit_account_html_template_rendering
72.26s call     functional/test_submit_and_retrieve_file.py::TestSubmitAndRetrieveFile::test_submit_and_retrieve_happy_path
64.75s call     functional/test_journalist.py::TestJournalist::test_journalist_verifies_deletion_of_one_submission_modal
50.69s call     functional/test_source.py::TestSourceInterface::test_lookup_codename_hint
50.64s call     functional/test_journalist.py::TestJournalist::test_journalist_uses_index_delete_collections_button_modal
40.44s call     functional/test_journalist.py::TestJournalist::test_journalist_uses_col_delete_collection_button_modal
33.12s setup    functional/test_admin_interface.py::TestAdminInterface::test_admin_interface
30.36s call     functional/test_admin_interface.py::TestAdminInterface::test_admin_deletes_user
23.80s call     functional/test_submit_and_retrieve_message.py::TestSubmitAndRetrieveMessage::test_submit_and_retrieve_happy_path
============================================ 20 passed, 2 xfailed in 1429.67 seconds =============================================

@conorsch
Copy link
Contributor

That's good news, @eloquence ! The xfails you report are, well, "expected failures", so the 20 passing is solid progress here. I'm going to clean up a bit as described in the comments above, aiming for merge into the feature branch.

@kushaldas
Copy link
Contributor Author

@conorsch Sorry for my language problem, I wanted to remove run_xvfb totally and I forgot to remove the line along with the comment. It is now handled by the Python code instead of the shell script.

Means the commit 23dd905d1a6acc91103dba136894990fad4e4a4f should not be there.

The 'when' conditional detecting a grsec kernel, used for running the
paxctl commands on the TBB binary, was needlessly duplicated on the
relevant task. Fortunately that didn't cause breakage, because the
'when' lines were identical, but only one was active.
Now installs Firefox 52 ESR, rather than Firefox 46, for use inside the
test container.

Includes changes to run-test shell script:

    TOR_FORCE_NET_CONFIG=0 is required to directly connect to Tor
    network, otherwise it will wait for userinput to either connect
    or to configure

    The `run_xvfb` invocation is no longer necessary, since the test suite
    code bootstraps the headless server now.
@kushaldas
Copy link
Contributor Author

@conorsch All functional tests passed locally. 💯

@conorsch
Copy link
Contributor

Same! Down to 20, rather than 21, given your latest commit. I'm going to squash your latest into the history, then we're set for merge here.

kushaldas and others added 8 commits July 26, 2018 11:29
Bootstrapping the application services within the functional test suite.
Includes some cleanup, culling unused debugging code, and also cleans up
the various print statements.

Ignore functional test firefox logs (thanks, @msheiny!)

Adds retries for tor network connection failure, using the pre-existing
logic.
The version of torsocks in the Trusty repos isn't recent enough to
support custom ports. Rather than install from other sources, which
requires manual package verification (or configuring non-trusty repos,
which could break other packages), let's fall back to good ol' nc.
We need to create a new firefox profile to test the orbot specific
warning. This works for both locally and over Tor.
Now we can safely execute the account changes in the tests running
on the Tor browser. The logic update makes sure to create different
user for this test than any other test.
We don't have to sleep for too long if we are running against
local instance. The ultimate goal remains to remove hardcoded sleeps
altogether, but we'll circle back and eliminate those calls once the
test suite is passing reliably.
The functional tests can take a long time, so let's instruct CircleCI to
continue waiting, to give the test suite a chance to finish
successfully.
This commit represented a squash of 3, all written by @msheiny, during a
debugging session trying to get CI to pass on the long-lived TBB
Selenium feature branch. CI isn't yet passing, so we'll punt to a
separate ticket and revisit prior to merge into develop. Preserving the
original commit messages below.

1.
    CircleCI - attempt to standardize CI to match devs

    Not sure this will solve the issue but occasionally we chase phantom
    bugs that only exist in CI and are really annoying to reproduce locally.
    Lets try to use the machine builder in CI instead to solve this problem.

2.
    Python3 not available in machine executor

    Lets just default to whatever is in python path.. code is compatible
    with both py 2.x and 3.x

3.
    Fix caching permissions issues for machine executor
Mostly correcting a typo in the `instance_information.json` config
filename, but also updated some of the example commands. The notes
regarding potentially failing tests also seemed out of date, as several
members of the team have confirmed working functional tests under the
new TB Selenium logic recently.
@conorsch conorsch self-requested a review July 26, 2018 18:30
Copy link
Contributor

@conorsch conorsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All functional tests are passing locally. More work required on revising CI, but we'll get to that after the new functional test suite stabilizes. Merging into feature branch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants