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

Add App Engine system tests #59

Merged
merged 3 commits into from
Oct 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ matrix:
- python: 3.5
env: TOXENV=cover
- python: 3.5
env: TOXENV=py35-system SYSTEM_TEST=1
env: TOXENV=py35-system SYSTEM_TEST=1 SKIP_APP_ENGINE_SYSTEM_TEST=1
- python: 2.7
env: TOXENV=py27-system SYSTEM_TEST=1
env: TOXENV=py27-system SYSTEM_TEST=1 SKIP_APP_ENGINE_SYSTEM_TEST=1
cache:
directories:
- ${HOME}/.cache
Expand Down
1 change: 1 addition & 0 deletions system_tests/app_engine/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib

This comment was marked as spam.

12 changes: 12 additions & 0 deletions system_tests/app_engine/app/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
api_version: 1
service: google-auth-system-tests
runtime: python27
threadsafe: true

handlers:
- url: .*
script: main.app

libraries:
- name: ssl
version: 2.7.11
29 changes: 29 additions & 0 deletions system_tests/app_engine/app/appengine_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.
vendor.add('lib')


# Patch os.path.expanduser. This should be fixed in GAE
# versions released after Nov 2016.

This comment was marked as spam.

This comment was marked as spam.

import os.path


def patched_expanduser(path):
return path

os.path.expanduser = patched_expanduser
129 changes: 129 additions & 0 deletions system_tests/app_engine/app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""App Engine standard application that runs basic system tests for
google.auth.app_engine.

This application has to run tests manually instead of using py.test because
py.test currently doesn't work on App Engine standard.
"""

import contextlib
import json
import sys
from StringIO import StringIO

This comment was marked as spam.

This comment was marked as spam.

import traceback

from google.appengine.api import app_identity
import google.auth
from google.auth import _helpers
from google.auth import app_engine
import google.auth.transport.urllib3
import urllib3.contrib.appengine
import webapp2

TOKEN_INFO_URL = 'https://www.googleapis.com/oauth2/v3/tokeninfo'
EMAIL_SCOPE = 'https://www.googleapis.com/auth/userinfo.email'
HTTP = urllib3.contrib.appengine.AppEngineManager()
HTTP_REQUEST = google.auth.transport.urllib3.Request(HTTP)


def test_credentials():
credentials = app_engine.Credentials()
scoped_credentials = credentials.with_scopes([EMAIL_SCOPE])

scoped_credentials.refresh(None)

assert scoped_credentials.valid
assert scoped_credentials.token is not None

# Get token info and verify scope
url = _helpers.update_query(TOKEN_INFO_URL, {
'access_token': scoped_credentials.token,
})
response = HTTP_REQUEST(url=url, method='GET')
token_info = json.loads(response.data.decode('utf-8'))

assert token_info['scope'] == EMAIL_SCOPE

This comment was marked as spam.

This comment was marked as spam.



def test_default():
credentials, project_id = google.auth.default()

assert isinstance(credentials, app_engine.Credentials)
assert project_id == app_identity.get_application_id()


@contextlib.contextmanager
def capture():
"""Context manager that captures stderr and stdout."""

This comment was marked as spam.

This comment was marked as spam.

oldout, olderr = sys.stdout, sys.stderr
try:
out = StringIO()
sys.stdout, sys.stderr = out, out
yield out

This comment was marked as spam.

This comment was marked as spam.

finally:
sys.stdout, sys.stderr = oldout, olderr


def run_test_func(func):
with capture() as capsys:
try:
func()
return True, ''
except Exception as exc:
output = (
'Test {} failed: {}\n\n'
'Stacktrace:\n{}\n\n'
'Captured output:\n{}').format(

This comment was marked as spam.

This comment was marked as spam.

func.func_name, exc, traceback.format_exc(),
capsys.getvalue())
return False, output


def run_tests():
"""Runs all tests.

Returns:
Tuple[bool, str]: A tuple containing True if all tests pass, False
otherwise, and any captured output from the tests.
"""
status = True
output = ''

tests = (test_credentials, test_default)

for test in tests:

This comment was marked as spam.

This comment was marked as spam.

test_status, test_output = run_test_func(test)
status = status and test_status
output += test_output

return status, output


class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['content-type'] = 'text/plain'

status, output = run_tests()

if not status:
self.response.status = 500

self.response.write(output)

This comment was marked as spam.



app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
3 changes: 3 additions & 0 deletions system_tests/app_engine/app/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
urllib3
# Relative path to google-auth-python's source.
../../..

This comment was marked as spam.

This comment was marked as spam.

58 changes: 58 additions & 0 deletions system_tests/app_engine/test_app_engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import subprocess

from google.auth import _cloud_sdk
import pytest

SKIP_TEST_ENV = 'SKIP_APP_ENGINE_SYSTEM_TEST'
HERE = os.path.dirname(__file__)
TEST_APP_DIR = os.path.join(HERE, 'app')
TEST_APP_SERVICE = 'google-auth-system-tests'


def vendor_app_dependencies():
"""Vendors in the test application's third-party dependencies."""
subprocess.check_call(
['pip', 'install', '--target', 'lib', '-r', 'requirements.txt'])


def deploy_app():
"""Deploys the test application using gcloud."""
subprocess.check_call(
['gcloud', 'app', 'deploy', '-q', 'app.yaml'])

This comment was marked as spam.

This comment was marked as spam.



@pytest.fixture
def app(monkeypatch):
monkeypatch.chdir(TEST_APP_DIR)

vendor_app_dependencies()
deploy_app()

application_id = _cloud_sdk.get_project_id()
application_url = 'https://{}-dot-{}.appspot.com'.format(
TEST_APP_SERVICE, application_id)

yield application_url


@pytest.mark.skipif(
SKIP_TEST_ENV in os.environ,
reason='Explicitly skipping App Engine system tests.')
def test_live_application(app, http_request):
response = http_request(method='GET', url=app)
assert response.status == 200, response.data.decode('utf-8')

This comment was marked as spam.

This comment was marked as spam.

8 changes: 6 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ deps =
[testenv:py35-system]
basepython = python3.5
commands =
py.test system_tests
py.test --ignore system_tests/app_engine/app {posargs:system_tests}
deps =
{[testenv]deps}
passenv =
SKIP_APP_ENGINE_SYSTEM_TEST

[testenv:py27-system]
basepython = python2.7
commands =
py.test system_tests
py.test --ignore system_tests/app_engine/app {posargs:system_tests}
deps =
{[testenv]deps}
passenv =
SKIP_APP_ENGINE_SYSTEM_TEST

[testenv:docgen]
basepython = python3.5
Expand Down