From a1ad83b073e6f0420a55e6bee2f3093a66d84e8f Mon Sep 17 00:00:00 2001 From: Jon Wayne Parrott Date: Thu, 11 Feb 2016 21:07:27 -0800 Subject: [PATCH] gigantic re-organization of tests. * /testing/resources have been moved to their respective samples. * /testing/utils.py has been broken up into several files, many of which will be moved to gcp-python-repo-tools. * Managed VMs tests have been re-written and enabled. * /scripts/check_requirements.py and /scripts/update_requirements.txt have been removed in favor of gcp-python-repo tools. * /lib has been removed, the tox environment for gae will just create it when needed. * Switched to using manual encryption and a secrets.tar file so that we can store both the service account and the environment variables needed. * Moved the testing section in CONTRIBUTING.md to its own file. * Changed the way that environment variables are used in tests. See testing.cloud.config. --- .coveragerc | 1 + .gitignore | 6 ++ .travis.yml | 30 ++---- CONTRIBUTING.md | 100 +----------------- TESTING.md | 79 ++++++++++++++ appengine/app_identity/signing/main_test.py | 4 +- appengine/bigquery/main_test.py | 13 ++- .../bigquery}/resources/datasets-list.json | 0 appengine/blobstore/main_test.py | 6 +- appengine/cloudsql/main_test.py | 4 +- appengine/images/main_test.py | 4 +- .../localtesting}/resources/queue.yaml | 0 appengine/localtesting/test_task_queue.py | 6 +- appengine/logging/reading_logs/main_test.py | 4 +- appengine/logging/writing_logs/main_test.py | 4 +- appengine/mailgun/main_test.py | 4 +- appengine/memcache/guestbook/main_test.py | 4 +- appengine/multitenancy/datastore_test.py | 4 +- appengine/multitenancy/memcache_test.py | 4 +- appengine/multitenancy/taskqueue_test.py | 8 +- .../contact_with_group_models_test.py | 4 +- .../ndb/modeling/keyproperty_models_test.py | 4 +- appengine/ndb/modeling/naive_models_test.py | 4 +- .../ndb/modeling/parent_child_models_test.py | 4 +- .../modeling/relation_model_models_test.py | 4 +- .../structured_property_models_test.py | 4 +- appengine/ndb/overview/main_test.py | 4 +- appengine/ndb/transactions/main_test.py | 4 +- {tests => appengine}/resources/app.yaml | 0 appengine/storage/main_test.py | 6 +- bigquery/api/async_query_test.py | 8 +- .../api/export_data_to_cloud_storage_test.py | 16 +-- bigquery/api/getting_started_test.py | 8 +- bigquery/api/list_datasets_projects_test.py | 8 +- bigquery/api/load_data_by_post_test.py | 26 +++-- bigquery/api/load_data_from_csv_test.py | 14 ++- {tests => bigquery/api}/resources/data.csv | 0 {tests => bigquery/api}/resources/data.json | 0 {tests => bigquery/api}/resources/schema.json | 0 .../api}/resources/streamrows.json | 0 bigquery/api/streaming_test.py | 9 +- bigquery/api/sync_query_test.py | 6 +- .../blog_test.py | 6 +- .../wiki_test.py | 6 +- cloud_logging/api/list_logs_test.py | 8 +- compute/api/create_instance_test.py | 12 +-- datastore/api/snippets_test.py | 6 +- datastore/api/tasks_test.py | 8 +- lib/README.md | 1 - managed_vms/{django_cloudsql => }/__init__.py | 0 managed_vms/{tests => analytics}/__init__.py | 0 managed_vms/cloudsql/__init__.py | 0 managed_vms/cloudsql/main_test.py | 30 ++++++ managed_vms/datastore/README.md | 4 +- managed_vms/datastore/__init__.py | 0 managed_vms/datastore/app.yaml | 2 +- managed_vms/datastore/main.py | 3 +- .../main_test.py} | 17 ++- managed_vms/disk/__init__.py | 0 managed_vms/disk/main.py | 17 +++ .../cloudsql_test.py => disk/main_test.py} | 17 ++- managed_vms/extending_runtime/__init__.py | 0 .../main_test.py} | 23 ++-- managed_vms/hello_world/__init__.py | 0 .../main_test.py} | 16 +-- managed_vms/hello_world_compat/__init__.py | 0 .../main_test.py} | 17 ++- managed_vms/mailgun/__init__.py | 0 managed_vms/memcache/__init__.py | 0 .../main_test.py} | 20 ++-- managed_vms/pubsub/__init__.py | 0 .../pubsub_test.py => pubsub/main_test.py} | 35 +++--- managed_vms/sendgrid/__init__.py | 0 managed_vms/static_files/__init__.py | 0 managed_vms/static_files/main_test.py | 30 ++++++ managed_vms/storage/README.md | 2 +- managed_vms/storage/__init__.py | 0 managed_vms/storage/app.yaml | 2 +- managed_vms/storage/main.py | 6 +- .../storage_test.py => storage/main_test.py} | 36 +++---- managed_vms/tests/disk_test.py | 30 ------ managed_vms/tests/runserver.py | 88 --------------- managed_vms/twilio/__init__.py | 0 managed_vms/websockets/__init__.py | 0 managed_vms/websockets/app.yaml | 4 +- monitoring/api/auth_test.py | 8 +- python-docs-samples.json.enc | Bin 1248 -> 0 bytes requirements-py27-dev.txt | 28 +++++ ...ments-dev.txt => requirements-py34-dev.txt | 7 +- scripts/check_requirements.py | 53 ---------- scripts/encrypt-secrets.sh | 24 +++++ scripts/prepare-testing-project.sh | 41 +++++++ scripts/{ => resources}/docs-links.json | 0 scripts/update_requirements.py | 74 ------------- secrets.tar.enc | Bin 0 -> 9760 bytes storage/api/compose_objects_test.py | 12 +-- storage/api/list_objects_test.py | 6 +- {tests => storage/api}/resources/file1.txt | 0 {tests => storage/api}/resources/file2.txt | 0 {tests => testing}/__init__.py | 17 ++- tests/utils.py => testing/appengine.py | 98 ++--------------- testing/cloud.py | 74 +++++++++++++ testing/flaky.py | 37 +++++++ testing/resources/test-env.tmpl.sh | 19 ++++ testing/utils.py | 70 ++++++++++++ tests/scripts/fetch_gae_sdk.py | 100 ------------------ tests/scripts/travis-before-install.sh | 25 ----- tox.ini | 57 +++++++--- 108 files changed, 766 insertions(+), 848 deletions(-) create mode 100644 TESTING.md rename {tests => appengine/bigquery}/resources/datasets-list.json (100%) rename {tests => appengine/localtesting}/resources/queue.yaml (100%) rename {tests => appengine}/resources/app.yaml (100%) rename {tests => bigquery/api}/resources/data.csv (100%) rename {tests => bigquery/api}/resources/data.json (100%) rename {tests => bigquery/api}/resources/schema.json (100%) rename {tests => bigquery/api}/resources/streamrows.json (100%) delete mode 100644 lib/README.md rename managed_vms/{django_cloudsql => }/__init__.py (100%) rename managed_vms/{tests => analytics}/__init__.py (100%) create mode 100644 managed_vms/cloudsql/__init__.py create mode 100644 managed_vms/cloudsql/main_test.py create mode 100644 managed_vms/datastore/__init__.py rename managed_vms/{tests/memcache_test.py => datastore/main_test.py} (70%) create mode 100644 managed_vms/disk/__init__.py rename managed_vms/{tests/cloudsql_test.py => disk/main_test.py} (70%) create mode 100644 managed_vms/extending_runtime/__init__.py rename managed_vms/{tests/extending_runtime_test.py => extending_runtime/main_test.py} (63%) create mode 100644 managed_vms/hello_world/__init__.py rename managed_vms/{tests/hello_world_test.py => hello_world/main_test.py} (73%) create mode 100644 managed_vms/hello_world_compat/__init__.py rename managed_vms/{tests/datastore_test.py => hello_world_compat/main_test.py} (70%) create mode 100644 managed_vms/mailgun/__init__.py create mode 100644 managed_vms/memcache/__init__.py rename managed_vms/{tests/static_files_test.py => memcache/main_test.py} (66%) create mode 100644 managed_vms/pubsub/__init__.py rename managed_vms/{tests/pubsub_test.py => pubsub/main_test.py} (66%) create mode 100644 managed_vms/sendgrid/__init__.py create mode 100644 managed_vms/static_files/__init__.py create mode 100644 managed_vms/static_files/main_test.py create mode 100644 managed_vms/storage/__init__.py rename managed_vms/{tests/storage_test.py => storage/main_test.py} (62%) delete mode 100644 managed_vms/tests/disk_test.py delete mode 100644 managed_vms/tests/runserver.py create mode 100644 managed_vms/twilio/__init__.py create mode 100644 managed_vms/websockets/__init__.py delete mode 100644 python-docs-samples.json.enc create mode 100644 requirements-py27-dev.txt rename requirements-dev.txt => requirements-py34-dev.txt (81%) delete mode 100755 scripts/check_requirements.py create mode 100755 scripts/encrypt-secrets.sh create mode 100755 scripts/prepare-testing-project.sh rename scripts/{ => resources}/docs-links.json (100%) delete mode 100755 scripts/update_requirements.py create mode 100644 secrets.tar.enc rename {tests => storage/api}/resources/file1.txt (100%) rename {tests => storage/api}/resources/file2.txt (100%) rename {tests => testing}/__init__.py (75%) rename tests/utils.py => testing/appengine.py (55%) create mode 100644 testing/cloud.py create mode 100644 testing/flaky.py create mode 100644 testing/resources/test-env.tmpl.sh create mode 100644 testing/utils.py delete mode 100755 tests/scripts/fetch_gae_sdk.py delete mode 100755 tests/scripts/travis-before-install.sh diff --git a/.coveragerc b/.coveragerc index 61ef6f4acb3f..c24f83113ef0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -8,6 +8,7 @@ include = monitoring/* storage/* cloud_logging/* + managed_vms/* [report] exclude_lines = pragma: NO COVER diff --git a/.gitignore b/.gitignore index 809e1a0d031a..146119deb5f9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,14 @@ coverage-gae.json .tox coverage.xml nosetests.xml +nosetests-*.xml python-docs-samples.json +service-account.json __pycache__ *db\.sqlite3 managed_vms/django_tutorial/static/* **/migrations/* +lib +testing/resources/test-env.sh +testing/resources/service-account.json +secrets.tar diff --git a/.travis.yml b/.travis.yml index e8f3c017120e..fdfd5933ba05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,35 +1,27 @@ sudo: false -#add language, etc. here language: python - +services: + - memcached + - mysql branches: only: - - master - + - master cache: directories: - $HOME/.cache - env: global: - PATH=${PATH}:${HOME}/gcloud/google-cloud-sdk/bin - - GOOGLE_APPLICATION_CREDENTIALS=${TRAVIS_BUILD_DIR}/python-docs-samples.json + - GOOGLE_APPLICATION_CREDENTIALS=${TRAVIS_BUILD_DIR}/testing/resources/service-account.json - GAE_PYTHONPATH=${HOME}/.cache/google_appengine - - TEST_BUCKET_NAME=bigquery-devrel-samples-bucket - - TEST_PROJECT_ID=bigquery-devrel-samples - + - secure: YIowCOMJ97rTcehKVT6Gi3u0Etm8s9+TBRGsNPJLgSF2zZdsh9IHcIc+tMDUMR3lpOe8y2a060RuODQcRsW1W1LIHej+ZE/gv6vATT6qNA3eKfKmZ9AyrpBO0fTOHlHrGBuU9ktBPR+iqvnq8MLWjnUozPFMJbuNBFITU7JP8jc= before_install: -- tests/scripts/travis-before-install.sh - +- openssl aes-256-cbc -k "$secrets_password" -in secrets.tar.enc -out secrets.tar -d +- tar xvf secrets.tar install: -# TODO: unpin tox when the following issue is fixed -# https://bitbucket.org/hpk42/tox/issues/285/tox-220-breaks-some-toxini-config-files - pip install tox - +- pip install -e git+https://github.com/GoogleCloudPlatform/python-repo-tools#egg=python-repo-tools +- gcp-python-repo-tools download-appengine-sdk `dirname "${GAE_PYTHONPATH}"` script: +- source ${TRAVIS_BUILD_DIR}/testing/resources/test-env.sh - tox - -# Coveralls is disabled in travis because travis does not run all of our -# tests. The full suite of tests is run on an internal Jenkins instance. -# after_success: -# - coveralls diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c922090aae05..cd004ed073d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,102 +36,4 @@ be able to accept your pull requests. ## Testing -The tests in this repository run against live services, therefore, it -takes a bit of configuration to run all of the tests locally. - -### Local setup - -Before you can run tests locally you must have: - -* The latest [tox](https://tox.readthedocs.org/en/latest/) and - [pip](https://pypi.python.org/pypi/pip) installed. - - $ sudo pip install --upgrade tox pip - -* The [Google Cloud SDK](https://cloud.google.com/sdk/) installed. You - can do so with the following command: - - $ curl https://sdk.cloud.google.com | bash - -* Most tests require you to have an active, billing-enabled project on - the - [Google Developers Console](https://console.developers.google.com). - -* You will need a set of - [Service Account Credentials](https://console.developers.google.com/project/_/apiui/credential) - for your project in ``json`` form. - -* Set the environment variables appropriately for your project. - - $ export GOOGLE_APPLICATION_CREDENTIALS=your-service-account-json-file - $ export TEST_PROJECT_ID=your-project-id - $ export TEST_BUCKET_NAME=your-bucket-name - -If you want to run the Google App Engine tests, you will need: - -* The App Engine Python SDK. You can install this by downloading it [here] -(https://cloud.google.com/appengine/downloads?hl=en) - -* You can also download it programatically with the - tests/scripts/fetch_gae_sdk.py - - $ test/scripts/fetch_gae_sdk.py - -* You will need to set an additional environment variable: - - $ export GAE_PYTHONPATH= - -To run the bigquery tests: - -* Create a dataset in your project named `test_dataset`. - - gcloud alpha bigquery datasets create test_dataset - -* Load sample data into google cloud storage (for import tests): - - gsutil cp tests/resources/data.csv gs://$TEST_BUCKET_NAME/data.csv - -* Load the sample data into a table named `test_table` (for export and streaming tests): - - gcloud alpha bigquery import \ - gs://$TEST_BUCKET_NAME/data.csv \ - test_dataset/test_table \ - --schema-file tests/resources/schema.json - -### Test environments - -We use [tox](https://tox.readthedocs.org/en/latest/) to configure -multiple python environments: - -* ``py27`` contains tests for samples that run in a normal Python 2.7 - environment. This is (mostly) everything outside of the - ``appengine`` directory. -* ``gae`` contains tests for samples that run only in Google App - Engine. This is (mostly) everything in the ``appengine`` directory. -* ``pep8`` just runs the linter. - -To run tests for a particular environment, invoke tox with the ``-e`` -flag: - - tox -e py27 - -To run one particular test suite or provide additional parameters to -``nose``, invoke tox like this: - - toxe -e py27 -- storage/tests/test_list_objects.py - -*Note*: The ``gae`` environment can't be told to run one particular - test at this time. - -### Adding new tests - -There are a handful of common testing utilities are located under -``tests``, see existing tests for example usage. - -When adding a new top-level directory, be sure to edit ``.coveragerc`` -to include it in coveralls. - -To add new tests that require Google App Engine, please place them in -the ``appengine`` directory if possible. If you place them elsewhere, -you will need to modify ``tox.ini`` to make the environments -appropriately run or ignore your test. +See [TESTING.md](TESTING.md). diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 000000000000..f88f6ce63ac6 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,79 @@ +# Testing + +The tests in this repository are system tests and run against live services, therefore, it takes a bit of configuration to run all of the tests locally. + +Before you can run tests locally you must have: + +* The latest [tox](https://tox.readthedocs.org/en/latest/), + [pip](https://pypi.python.org/pypi/pip), and [gcp-python-repo-tools](https://pypi.python.org/pypi/gcp-python-repo-tools) installed. + + $ sudo pip install --upgrade tox pip gcp-python-repo-tools + +* The [Google Cloud SDK](https://cloud.google.com/sdk/) installed. You + can do so with the following command: + + $ curl https://sdk.cloud.google.com | bash + +## Preparing a project for testing + +Most tests require you to have an active, billing-enabled project on the +[Google Cloud Console](https://console.cloud.google.com). + +### Creating resources + +Some resources need to be created in a project ahead of time before testing. We have a script that can create everything needed: + + gcloud config set project + scripts/prepare-testing-project.sh + +The script will also instruct you to follow a URL to enable APIs. You will need to do that. + +### Getting a service account key + +From the Cloud Console, create a new Service Account and download its json key. Place this file in `testing/resources/service-account.json`. + +## Environment variables + +* Copy `testing/resources/test-env.tmpl.sh` to `testing/resources/test-env.sh`, and updated it with your configuration. +* Run `source testing/resources/test-env.sh`. +* Run `export GOOGLE_APPLICATION_CREDENTIALS=testing/resources/service-account.json`. + +If you want to run the Google App Engine tests, you will need: + +* The App Engine Python SDK. You can also download it programatically with `gcp-python-repo-tools`: + + $ gcp-python-repo-tools download-appengine-sdk + +* Set the `GAE_PYTHONPATH` variable: + + $ export GAE_PYTHONPATH= + +### Test environments + +We use [tox](https://tox.readthedocs.org/en/latest/) to configure +multiple python environments: + +* ``py27`` and ``py34`` contains tests for samples that run in a normal Python 2.7 pr 3.4 environment. This is everything outside of the ``appengine`` directory that isn't slow or flaky. +* ``py27-all`` and ``py34-all`` runs all tests except for App Engine tests. This can time some time and some tests are flaky. +* ``gae`` contains tests for samples that run only in Google App Engine. This is (mostly) everything in the ``appengine`` directory. +* ``pep8`` just runs the linter. + +To run tests for a particular environment, invoke tox with the ``-e`` +flag: + + tox -e py27 + +To run one particular test suite or provide additional parameters to +``nose``, invoke tox like this: + + toxe -e py27 -- storage/tests/test_list_objects.py + +### Adding new tests + +When adding a new top-level directory, be sure to edit ``.coveragerc`` +to include it in coveralls. + +To add new tests that require Google App Engine, please place them in +the ``appengine`` directory if possible. If you place them elsewhere, +you will need to modify ``tox.ini`` to make the environments +appropriately run or ignore your test. diff --git a/appengine/app_identity/signing/main_test.py b/appengine/app_identity/signing/main_test.py index fdb5a75b9e80..7d2133838bdc 100644 --- a/appengine/app_identity/signing/main_test.py +++ b/appengine/app_identity/signing/main_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase +from testing import AppEngineTest import webtest from . import main -class TestAppIdentityHandler(AppEngineTestbedCase): +class TestAppIdentityHandler(AppEngineTest): def setUp(self): super(TestAppIdentityHandler, self).setUp() diff --git a/appengine/bigquery/main_test.py b/appengine/bigquery/main_test.py index 7eff8ec469f6..de170a50b244 100644 --- a/appengine/bigquery/main_test.py +++ b/appengine/bigquery/main_test.py @@ -12,23 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import re from apiclient.http import HttpMock import mock -import tests +import testing import webtest from . import main -class TestAuthSample(tests.AppEngineTestbedCase): +class TestAuthSample(testing.AppEngineTest): def setUp(self): super(TestAuthSample, self).setUp() self.app = webtest.TestApp(main.app) - main.PROJECTID = self.project_id + main.PROJECTID = self.config.GCLOUD_PROJECT def test_anonymous_get(self): response = self.app.get('/') @@ -39,7 +38,7 @@ def test_anonymous_get(self): r'.*accounts.*Login.*') def test_loggedin_get(self): - self.loginUser() + self.login_user() response = self.app.get('/') @@ -49,10 +48,10 @@ def test_loggedin_get(self): @mock.patch.object(main.decorator, 'has_credentials', return_value=True) def test_oauthed_get(self, *args): - self.loginUser() + self.login_user() mock_http = HttpMock( - os.path.join(self.resource_path, 'datasets-list.json'), + self.resource_path('datasets-list.json'), {'status': '200'}) with mock.patch.object(main.decorator, 'http', return_value=mock_http): diff --git a/tests/resources/datasets-list.json b/appengine/bigquery/resources/datasets-list.json similarity index 100% rename from tests/resources/datasets-list.json rename to appengine/bigquery/resources/datasets-list.json diff --git a/appengine/blobstore/main_test.py b/appengine/blobstore/main_test.py index 53d6642e23a3..da6e6bfeb675 100644 --- a/appengine/blobstore/main_test.py +++ b/appengine/blobstore/main_test.py @@ -12,20 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -import tests +import testing import webtest from . import main -class TestBlobstoreSample(tests.AppEngineTestbedCase): +class TestBlobstoreSample(testing.AppEngineTest): def setUp(self): super(TestBlobstoreSample, self).setUp() self.app = webtest.TestApp(main.app) def test_form(self): - self.loginUser() + self.login_user() response = self.app.get('/') self.assertTrue('/_ah/upload' in response) diff --git a/appengine/cloudsql/main_test.py b/appengine/cloudsql/main_test.py index 2b7304c81886..2ad2cacc071b 100644 --- a/appengine/cloudsql/main_test.py +++ b/appengine/cloudsql/main_test.py @@ -16,13 +16,13 @@ import re from unittest.case import SkipTest -import tests +import testing import webtest from . import main -class TestMySQLSample(tests.AppEngineTestbedCase): +class TestMySQLSample(testing.AppEngineTest): def setUp(self): if not os.path.exists('/var/run/mysqld/mysqld.sock'): diff --git a/appengine/images/main_test.py b/appengine/images/main_test.py index f1ed70690066..25c264470ff2 100644 --- a/appengine/images/main_test.py +++ b/appengine/images/main_test.py @@ -13,13 +13,13 @@ # limitations under the License. import mock -from tests import AppEngineTestbedCase +from testing import AppEngineTest import webtest from . import main -class TestHandlers(AppEngineTestbedCase): +class TestHandlers(AppEngineTest): def setUp(self): super(TestHandlers, self).setUp() diff --git a/tests/resources/queue.yaml b/appengine/localtesting/resources/queue.yaml similarity index 100% rename from tests/resources/queue.yaml rename to appengine/localtesting/resources/queue.yaml diff --git a/appengine/localtesting/test_task_queue.py b/appengine/localtesting/test_task_queue.py index fb8e0ac01276..cfa3d85f1aac 100644 --- a/appengine/localtesting/test_task_queue.py +++ b/appengine/localtesting/test_task_queue.py @@ -12,8 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import operator # [START taskqueue] +import operator +import os import unittest from google.appengine.api import taskqueue @@ -28,7 +29,8 @@ def setUp(self): # root_path must be set the the location of queue.yaml. # Otherwise, only the 'default' queue will be available. - self.testbed.init_taskqueue_stub(root_path='tests/resources') + self.testbed.init_taskqueue_stub( + root_path=os.path.join(os.path.dirname(__file__), 'resources')) self.taskqueue_stub = self.testbed.get_stub( testbed.TASKQUEUE_SERVICE_NAME) diff --git a/appengine/logging/reading_logs/main_test.py b/appengine/logging/reading_logs/main_test.py index 0ab76921a0b7..0dcc8cd61bc3 100644 --- a/appengine/logging/reading_logs/main_test.py +++ b/appengine/logging/reading_logs/main_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase +from testing import AppEngineTest import webtest from . import main -class TestReadingLogs(AppEngineTestbedCase): +class TestReadingLogs(AppEngineTest): def setUp(self): super(TestReadingLogs, self).setUp() diff --git a/appengine/logging/writing_logs/main_test.py b/appengine/logging/writing_logs/main_test.py index c2f6fd86757c..339caa4ef662 100644 --- a/appengine/logging/writing_logs/main_test.py +++ b/appengine/logging/writing_logs/main_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase +from testing import AppEngineTest import webtest from . import main -class TestWritingLogs(AppEngineTestbedCase): +class TestWritingLogs(AppEngineTest): def setUp(self): super(TestWritingLogs, self).setUp() diff --git a/appengine/mailgun/main_test.py b/appengine/mailgun/main_test.py index 99664fcd91c3..dbd3345bb442 100644 --- a/appengine/mailgun/main_test.py +++ b/appengine/mailgun/main_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase, Http2Mock +from testing import AppEngineTest, Http2Mock import webtest from . import main -class TestMailgunHandlers(AppEngineTestbedCase): +class TestMailgunHandlers(AppEngineTest): def setUp(self): super(TestMailgunHandlers, self).setUp() diff --git a/appengine/memcache/guestbook/main_test.py b/appengine/memcache/guestbook/main_test.py index f6030adc9184..62bf0e92aa71 100644 --- a/appengine/memcache/guestbook/main_test.py +++ b/appengine/memcache/guestbook/main_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase +from testing import AppEngineTest import webtest from . import main -class TestHandlers(AppEngineTestbedCase): +class TestHandlers(AppEngineTest): def test_hello(self): app = webtest.TestApp(main.app) diff --git a/appengine/multitenancy/datastore_test.py b/appengine/multitenancy/datastore_test.py index f63f5e57a559..abdf9eee6636 100644 --- a/appengine/multitenancy/datastore_test.py +++ b/appengine/multitenancy/datastore_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import tests +import testing import webtest from . import datastore -class TestNamespaceDatastoreSample(tests.AppEngineTestbedCase): +class TestNamespaceDatastoreSample(testing.AppEngineTest): def setUp(self): super(TestNamespaceDatastoreSample, self).setUp() diff --git a/appengine/multitenancy/memcache_test.py b/appengine/multitenancy/memcache_test.py index b37b1f268910..df30155a6a4c 100644 --- a/appengine/multitenancy/memcache_test.py +++ b/appengine/multitenancy/memcache_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import tests +import testing import webtest from . import memcache -class TestNamespaceMemcacheSample(tests.AppEngineTestbedCase): +class TestNamespaceMemcacheSample(testing.AppEngineTest): def setUp(self): super(TestNamespaceMemcacheSample, self).setUp() diff --git a/appengine/multitenancy/taskqueue_test.py b/appengine/multitenancy/taskqueue_test.py index 5fdf5c18835b..a8dd703a473a 100644 --- a/appengine/multitenancy/taskqueue_test.py +++ b/appengine/multitenancy/taskqueue_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import tests +import testing import webtest from . import taskqueue -class TestNamespaceTaskQueueSample(tests.AppEngineTestbedCase): +class TestNamespaceTaskQueueSample(testing.AppEngineTest): def setUp(self): super(TestNamespaceTaskQueueSample, self).setUp() @@ -29,7 +29,7 @@ def test_get(self): self.assertEqual(response.status_int, 200) self.assertTrue('Global: 0' in response.body) - self.runTasks() + self.run_tasks() response = self.app.get('/taskqueue') self.assertEqual(response.status_int, 200) @@ -39,7 +39,7 @@ def test_get(self): self.assertEqual(response.status_int, 200) self.assertTrue('a: 0' in response.body) - self.runTasks() + self.run_tasks() response = self.app.get('/taskqueue/a') self.assertEqual(response.status_int, 200) diff --git a/appengine/ndb/modeling/contact_with_group_models_test.py b/appengine/ndb/modeling/contact_with_group_models_test.py index e08a2980200b..286948bc5f4d 100644 --- a/appengine/ndb/modeling/contact_with_group_models_test.py +++ b/appengine/ndb/modeling/contact_with_group_models_test.py @@ -15,12 +15,12 @@ """Test classes for code snippet for modeling article.""" from google.appengine.ext import ndb -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import contact_with_group_models as models -class ContactTestCase(AppEngineTestbedCase): +class ContactTestCase(AppEngineTest): """A test case for the Contact model with groups.""" def setUp(self): """Creates 3 contacts and 1 group. diff --git a/appengine/ndb/modeling/keyproperty_models_test.py b/appengine/ndb/modeling/keyproperty_models_test.py index 2a119bb4d1a4..ec0cf87d8baa 100644 --- a/appengine/ndb/modeling/keyproperty_models_test.py +++ b/appengine/ndb/modeling/keyproperty_models_test.py @@ -16,12 +16,12 @@ import unittest -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import keyproperty_models as models -class ContactTestCase(AppEngineTestbedCase): +class ContactTestCase(AppEngineTest): """A test case for the Contact model class with KeyProperty.""" NAME = 'Takashi Matsuo' diff --git a/appengine/ndb/modeling/naive_models_test.py b/appengine/ndb/modeling/naive_models_test.py index d54be0c49504..07d5935e0b13 100644 --- a/appengine/ndb/modeling/naive_models_test.py +++ b/appengine/ndb/modeling/naive_models_test.py @@ -14,12 +14,12 @@ """Test classes for code snippet for modeling article.""" -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import naive_models as models -class ContactTestCase(AppEngineTestbedCase): +class ContactTestCase(AppEngineTest): """A test case for the naive Contact model classe.""" NAME = 'Takashi Matsuo' diff --git a/appengine/ndb/modeling/parent_child_models_test.py b/appengine/ndb/modeling/parent_child_models_test.py index b76db71d9f5d..95f3d876ad7e 100644 --- a/appengine/ndb/modeling/parent_child_models_test.py +++ b/appengine/ndb/modeling/parent_child_models_test.py @@ -15,12 +15,12 @@ """Test classes for code snippet for modeling article.""" from google.appengine.ext import ndb -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import parent_child_models as models -class ContactTestCase(AppEngineTestbedCase): +class ContactTestCase(AppEngineTest): """A test case for the Contact model class with KeyProperty.""" NAME = 'Takashi Matsuo' diff --git a/appengine/ndb/modeling/relation_model_models_test.py b/appengine/ndb/modeling/relation_model_models_test.py index eb1f61f02a13..45eb7805617a 100644 --- a/appengine/ndb/modeling/relation_model_models_test.py +++ b/appengine/ndb/modeling/relation_model_models_test.py @@ -15,12 +15,12 @@ """Test classes for code snippet for modeling article.""" from google.appengine.ext import ndb -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import relation_model_models as models -class ContactTestCase(AppEngineTestbedCase): +class ContactTestCase(AppEngineTest): """A test case for the Contact model with relationship model.""" def setUp(self): """Creates 1 contact and 1 company. diff --git a/appengine/ndb/modeling/structured_property_models_test.py b/appengine/ndb/modeling/structured_property_models_test.py index 28e65347618c..0e60d71d14dd 100644 --- a/appengine/ndb/modeling/structured_property_models_test.py +++ b/appengine/ndb/modeling/structured_property_models_test.py @@ -14,12 +14,12 @@ """Test classes for code snippet for modeling article.""" -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import structured_property_models as models -class ContactTestCase(AppEngineTestbedCase): +class ContactTestCase(AppEngineTest): """A test case for the Contact model with StructuredProperty.""" def setUp(self): """Creates one Contact entity with 2 phone numbers.""" diff --git a/appengine/ndb/overview/main_test.py b/appengine/ndb/overview/main_test.py index 41ae248c194f..2cc6dd2badb0 100644 --- a/appengine/ndb/overview/main_test.py +++ b/appengine/ndb/overview/main_test.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase +from testing import AppEngineTest import webtest from . import main -class TestHandlers(AppEngineTestbedCase): +class TestHandlers(AppEngineTest): def test_hello(self): app = webtest.TestApp(main.app) response = app.get('/') diff --git a/appengine/ndb/transactions/main_test.py b/appengine/ndb/transactions/main_test.py index 07442f86fd0f..988bdbb5e9c4 100644 --- a/appengine/ndb/transactions/main_test.py +++ b/appengine/ndb/transactions/main_test.py @@ -12,12 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from tests import AppEngineTestbedCase +from testing import AppEngineTest from . import main -class TestHandlers(AppEngineTestbedCase): +class TestHandlers(AppEngineTest): def setUp(self): super(TestHandlers, self).setUp() main.app.config['TESTING'] = True diff --git a/tests/resources/app.yaml b/appengine/resources/app.yaml similarity index 100% rename from tests/resources/app.yaml rename to appengine/resources/app.yaml diff --git a/appengine/storage/main_test.py b/appengine/storage/main_test.py index 8648b8a1e6b8..5dbddc985305 100644 --- a/appengine/storage/main_test.py +++ b/appengine/storage/main_test.py @@ -13,18 +13,18 @@ # limitations under the License. import re -import tests +import testing import webtest from . import main -class TestStorageSample(tests.AppEngineTestbedCase): +class TestStorageSample(testing.AppEngineTest): def setUp(self): super(TestStorageSample, self).setUp() self.app = webtest.TestApp(main.app) - main.BUCKET_NAME = self.bucket_name + main.BUCKET_NAME = self.config.GCLOUD_PROJECT def test_get(self): response = self.app.get('/') diff --git a/bigquery/api/async_query_test.py b/bigquery/api/async_query_test.py index 336f9ec57a47..575d90326df3 100644 --- a/bigquery/api/async_query_test.py +++ b/bigquery/api/async_query_test.py @@ -13,21 +13,21 @@ # import json -import tests +import testing from .async_query import main -class TestAsyncQuery(tests.CloudBaseTest): +class TestAsyncQuery(testing.CloudTest): def test_async_query(self): query = ( 'SELECT corpus FROM publicdata:samples.shakespeare ' 'GROUP BY corpus;') - with tests.capture_stdout() as stdout: + with testing.capture_stdout() as stdout: main( - project_id=self.project_id, + project_id=self.config.GCLOUD_PROJECT, query_string=query, batch=False, num_retries=5, diff --git a/bigquery/api/export_data_to_cloud_storage_test.py b/bigquery/api/export_data_to_cloud_storage_test.py index 8d6a7cd207a5..135b2bf075d5 100644 --- a/bigquery/api/export_data_to_cloud_storage_test.py +++ b/bigquery/api/export_data_to_cloud_storage_test.py @@ -14,22 +14,22 @@ """Tests for export_table_to_gcs.""" from nose.plugins.attrib import attr -from tests import CloudBaseTest +from testing import CloudTest from .export_data_to_cloud_storage import main @attr('slow') -class TestExportTableToGCS(CloudBaseTest): +class TestExportTableToGCS(CloudTest): dataset_id = 'test_dataset' table_id = 'test_table' def test_export_table_csv(self): cloud_storage_output_uri = \ - 'gs://{}/output.csv'.format(self.bucket_name) + 'gs://{}/output.csv'.format(self.config.CLOUD_STORAGE_BUCKET) main( cloud_storage_output_uri, - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id, num_retries=5, @@ -38,10 +38,10 @@ def test_export_table_csv(self): def test_export_table_json(self): cloud_storage_output_uri = \ - 'gs://{}/output.json'.format(self.bucket_name) + 'gs://{}/output.json'.format(self.config.CLOUD_STORAGE_BUCKET) main( cloud_storage_output_uri, - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id, num_retries=5, @@ -50,10 +50,10 @@ def test_export_table_json(self): def test_export_table_avro(self): cloud_storage_output_uri = \ - 'gs://{}/output.avro'.format(self.bucket_name) + 'gs://{}/output.avro'.format(self.config.CLOUD_STORAGE_BUCKET) main( cloud_storage_output_uri, - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id, num_retries=5, diff --git a/bigquery/api/getting_started_test.py b/bigquery/api/getting_started_test.py index 5eb8242b6304..4d32f4d44cbc 100644 --- a/bigquery/api/getting_started_test.py +++ b/bigquery/api/getting_started_test.py @@ -13,15 +13,15 @@ # import re -import tests +import testing from .getting_started import main -class TestGettingStarted(tests.CloudBaseTest): +class TestGettingStarted(testing.CloudTest): def test_main(self): - with tests.capture_stdout() as mock_stdout: - main(self.project_id) + with testing.capture_stdout() as mock_stdout: + main(self.config.GCLOUD_PROJECT) stdout = mock_stdout.getvalue() self.assertRegexpMatches(stdout, re.compile( diff --git a/bigquery/api/list_datasets_projects_test.py b/bigquery/api/list_datasets_projects_test.py index d99acb62f91d..2dd92a8d6b9b 100644 --- a/bigquery/api/list_datasets_projects_test.py +++ b/bigquery/api/list_datasets_projects_test.py @@ -13,16 +13,16 @@ # import re -import tests +import testing from .list_datasets_projects import main -class TestListDatasetsProjects(tests.CloudBaseTest): +class TestListDatasetsProjects(testing.CloudTest): def test_main(self): - with tests.capture_stdout() as mock_stdout: - main(self.project_id) + with testing.capture_stdout() as mock_stdout: + main(self.config.GCLOUD_PROJECT) stdout = mock_stdout.getvalue() diff --git a/bigquery/api/load_data_by_post_test.py b/bigquery/api/load_data_by_post_test.py index 6d0db5899238..08286e144b1e 100644 --- a/bigquery/api/load_data_by_post_test.py +++ b/bigquery/api/load_data_by_post_test.py @@ -10,29 +10,27 @@ # 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 re from nose.plugins.attrib import attr - -import tests +import testing from .load_data_by_post import load_data @attr('slow') -class TestLoadDataByPost(tests.CloudBaseTest): - dataset_id = 'ephemeral_dataset' +class TestLoadDataByPost(testing.CloudTest): + dataset_id = 'ephemeral_test_dataset' table_id = 'load_data_by_post' def test_load_csv_data(self): - schema_path = os.path.join(self.resource_path, 'schema.json') - data_path = os.path.join(self.resource_path, 'data.csv') - with tests.capture_stdout() as mock_stdout: + schema_path = self.resource_path('schema.json') + data_path = self.resource_path('data.csv') + with testing.capture_stdout() as mock_stdout: load_data(schema_path, data_path, - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id ) @@ -43,13 +41,13 @@ def test_load_csv_data(self): r'Waiting for job to finish.*Job complete.', re.DOTALL)) def test_load_json_data(self): - schema_path = os.path.join(self.resource_path, 'schema.json') - data_path = os.path.join(self.resource_path, 'data.json') + schema_path = self.resource_path('schema.json') + data_path = self.resource_path('data.json') - with tests.capture_stdout() as mock_stdout: + with testing.capture_stdout() as mock_stdout: load_data(schema_path, data_path, - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id ) diff --git a/bigquery/api/load_data_from_csv_test.py b/bigquery/api/load_data_from_csv_test.py index 41ed703ca838..fd64fdeca9a2 100644 --- a/bigquery/api/load_data_from_csv_test.py +++ b/bigquery/api/load_data_from_csv_test.py @@ -10,27 +10,25 @@ # 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. -# -"""Tests for load_data_from_csv.""" -import os from nose.plugins.attrib import attr -from tests import CloudBaseTest +from testing import CloudTest from .load_data_from_csv import main @attr('slow') -class TestLoadDataFromCSV(CloudBaseTest): +class TestLoadDataFromCSV(CloudTest): dataset_id = 'test_dataset' table_id = 'test_import_table' def test_load_table(self): - cloud_storage_input_uri = 'gs://{}/data.csv'.format(self.bucket_name) - schema_file = os.path.join(self.resource_path, 'schema.json') + cloud_storage_input_uri = 'gs://{}/data.csv'.format( + self.config.CLOUD_STORAGE_BUCKET) + schema_file = self.resource_path('schema.json') main( - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id, schema_file=schema_file, diff --git a/tests/resources/data.csv b/bigquery/api/resources/data.csv similarity index 100% rename from tests/resources/data.csv rename to bigquery/api/resources/data.csv diff --git a/tests/resources/data.json b/bigquery/api/resources/data.json similarity index 100% rename from tests/resources/data.json rename to bigquery/api/resources/data.json diff --git a/tests/resources/schema.json b/bigquery/api/resources/schema.json similarity index 100% rename from tests/resources/schema.json rename to bigquery/api/resources/schema.json diff --git a/tests/resources/streamrows.json b/bigquery/api/resources/streamrows.json similarity index 100% rename from tests/resources/streamrows.json rename to bigquery/api/resources/streamrows.json diff --git a/bigquery/api/streaming_test.py b/bigquery/api/streaming_test.py index 1325a85b4abb..29160231e2fe 100644 --- a/bigquery/api/streaming_test.py +++ b/bigquery/api/streaming_test.py @@ -13,20 +13,19 @@ # """Tests for export_table_to_gcs.""" import json -import os -from tests import capture_stdout, CloudBaseTest +from testing import capture_stdout, CloudTest from . import streaming -class TestStreaming(CloudBaseTest): +class TestStreaming(CloudTest): dataset_id = 'test_dataset' table_id = 'test_table' def test_stream_row_to_bigquery(self): with open( - os.path.join(self.resource_path, 'streamrows.json'), + self.resource_path('streamrows.json'), 'r') as rows_file: rows = json.load(rows_file) @@ -35,7 +34,7 @@ def test_stream_row_to_bigquery(self): with capture_stdout() as stdout: streaming.main( - self.project_id, + self.config.GCLOUD_PROJECT, self.dataset_id, self.table_id, num_retries=5) diff --git a/bigquery/api/sync_query_test.py b/bigquery/api/sync_query_test.py index 07ddb1cd07d7..975095990424 100644 --- a/bigquery/api/sync_query_test.py +++ b/bigquery/api/sync_query_test.py @@ -13,12 +13,12 @@ # import json -from tests import capture_stdout, CloudBaseTest +from testing import capture_stdout, CloudTest from .sync_query import main -class TestSyncQuery(CloudBaseTest): +class TestSyncQuery(CloudTest): def test_sync_query(self): query = ( @@ -27,7 +27,7 @@ def test_sync_query(self): with capture_stdout() as stdout: main( - project_id=self.project_id, + project_id=self.config.GCLOUD_PROJECT, query=query, timeout=30, num_retries=5) diff --git a/blog/introduction_to_data_models_in_cloud_datastore/blog_test.py b/blog/introduction_to_data_models_in_cloud_datastore/blog_test.py index a0dbcfdceaf5..3475b212b440 100644 --- a/blog/introduction_to_data_models_in_cloud_datastore/blog_test.py +++ b/blog/introduction_to_data_models_in_cloud_datastore/blog_test.py @@ -12,14 +12,14 @@ # limitations under the License. # from nose.plugins.attrib import attr -from tests import CloudBaseTest +from testing import CloudTest from .blog import main @attr('slow') -class BlogTestCase(CloudBaseTest): +class BlogTestCase(CloudTest): """Simple test case that ensures the blog code doesn't throw any errors.""" def test_main(self): - main(self.project_id) + main(self.config.GCLOUD_PROJECT) diff --git a/blog/introduction_to_data_models_in_cloud_datastore/wiki_test.py b/blog/introduction_to_data_models_in_cloud_datastore/wiki_test.py index 53f2e059a47a..17cfe5396120 100644 --- a/blog/introduction_to_data_models_in_cloud_datastore/wiki_test.py +++ b/blog/introduction_to_data_models_in_cloud_datastore/wiki_test.py @@ -12,14 +12,14 @@ # limitations under the License. # from nose.plugins.attrib import attr -from tests import CloudBaseTest +from testing import CloudTest from .wiki import main @attr('slow') -class WikiTestCase(CloudBaseTest): +class WikiTestCase(CloudTest): """Simple test case that ensures the wiki code doesn't throw any errors.""" def test_main(self): - main(self.project_id) + main(self.config.GCLOUD_PROJECT) diff --git a/cloud_logging/api/list_logs_test.py b/cloud_logging/api/list_logs_test.py index c5f79b8c12f1..0f5d7d598b07 100644 --- a/cloud_logging/api/list_logs_test.py +++ b/cloud_logging/api/list_logs_test.py @@ -14,16 +14,16 @@ import re import unittest -import tests +import testing from . import list_logs -class TestListLogs(tests.CloudBaseTest): +class TestListLogs(testing.CloudTest): def test_main(self): - with tests.capture_stdout() as stdout: - list_logs.main(self.project_id) + with testing.capture_stdout() as stdout: + list_logs.main(self.config.GCLOUD_PROJECT) output = stdout.getvalue().strip() diff --git a/compute/api/create_instance_test.py b/compute/api/create_instance_test.py index 1374d821b9d3..9bf852d78870 100644 --- a/compute/api/create_instance_test.py +++ b/compute/api/create_instance_test.py @@ -14,19 +14,19 @@ import re from nose.plugins.attrib import attr -import tests +import testing from .create_instance import main @attr('slow') -class TestComputeGettingStarted(tests.CloudBaseTest): +class TestComputeGettingStarted(testing.CloudTest): def test_main(self): - with tests.capture_stdout() as mock_stdout: + with testing.capture_stdout() as mock_stdout: main( - self.project_id, - self.bucket_name, + self.config.GCLOUD_PROJECT, + self.config.CLOUD_STORAGE_BUCKET, 'us-central1-f', 'test-instance', wait=False) @@ -35,7 +35,7 @@ def test_main(self): expected_output = re.compile( (r'Instances in project %s and zone us-central1-.* - test-instance' - r'.*Deleting instance.*done..$') % self.project_id, + r'.*Deleting instance.*done..$') % self.config.GCLOUD_PROJECT, re.DOTALL) self.assertRegexpMatches( stdout, diff --git a/datastore/api/snippets_test.py b/datastore/api/snippets_test.py index 1ccccc7dd826..24b45e3575d9 100644 --- a/datastore/api/snippets_test.py +++ b/datastore/api/snippets_test.py @@ -15,7 +15,7 @@ import time from gcloud import datastore -from tests import CloudBaseTest, mark_flaky +from testing import CloudTest, mark_flaky from . import snippets @@ -44,11 +44,11 @@ def put_multi(*args, **kwargs): @mark_flaky -class DatastoreSnippetsTest(CloudBaseTest): +class DatastoreSnippetsTest(CloudTest): def setUp(self): super(DatastoreSnippetsTest, self).setUp() - self.client = datastore.Client(self.project_id) + self.client = datastore.Client(self.config.GCLOUD_PROJECT) self.to_delete_entities = [] self.to_delete_keys = [] diff --git a/datastore/api/tasks_test.py b/datastore/api/tasks_test.py index 8c4b89d3cf5b..58452f899b17 100644 --- a/datastore/api/tasks_test.py +++ b/datastore/api/tasks_test.py @@ -12,17 +12,17 @@ # limitations under the License. from gcloud import datastore -from tests import CloudBaseTest, mark_flaky +from testing import CloudTest, mark_flaky from . import tasks @mark_flaky -class DatastoreTasksTest(CloudBaseTest): +class DatastoreTasksTest(CloudTest): def setUp(self): super(DatastoreTasksTest, self).setUp() - self.client = datastore.Client(self.project_id) + self.client = datastore.Client(self.config.GCLOUD_PROJECT) def tearDown(self): super(DatastoreTasksTest, self).tearDown() @@ -31,7 +31,7 @@ def tearDown(self): [x.key for x in self.client.query(kind='Task').fetch()]) def test_create_client(self): - tasks.create_client(self.project_id) + tasks.create_client(self.config.GCLOUD_PROJECT) def test_add_task(self): task_key = tasks.add_task(self.client, 'Test task') diff --git a/lib/README.md b/lib/README.md deleted file mode 100644 index 9dbd703f9fb8..000000000000 --- a/lib/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory is just for preventing the vendor lib throwing an error. diff --git a/managed_vms/django_cloudsql/__init__.py b/managed_vms/__init__.py similarity index 100% rename from managed_vms/django_cloudsql/__init__.py rename to managed_vms/__init__.py diff --git a/managed_vms/tests/__init__.py b/managed_vms/analytics/__init__.py similarity index 100% rename from managed_vms/tests/__init__.py rename to managed_vms/analytics/__init__.py diff --git a/managed_vms/cloudsql/__init__.py b/managed_vms/cloudsql/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/cloudsql/main_test.py b/managed_vms/cloudsql/main_test.py new file mode 100644 index 000000000000..66d7eb3f9601 --- /dev/null +++ b/managed_vms/cloudsql/main_test.py @@ -0,0 +1,30 @@ +# Copyright 2015 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. + +from testing import CloudTest + +from . import main + + +class CloudSqlTest(CloudTest): + + def test_index(self): + main.db.create_all() + + main.app.testing = True + client = main.app.test_client() + + r = client.get('/', environ_base={'REMOTE_ADDR': '127.0.0.1'}) + self.assertEqual(r.status_code, 200) + self.assertTrue('127.0' in r.data.decode('utf-8')) diff --git a/managed_vms/datastore/README.md b/managed_vms/datastore/README.md index 62da94e5dbd8..7cedaff5c919 100644 --- a/managed_vms/datastore/README.md +++ b/managed_vms/datastore/README.md @@ -14,7 +14,7 @@ When running locally, you can use the [Google Cloud SDK](https://cloud.google.co $ gcloud init -Set the ``GCLOUD_DATASET_ID`` environment variable to your Project ID before starting your application: +Set the ``GCLOUD_PROJECT`` environment variable to your Project ID before starting your application: - $ export GCLOUD_DATASET_ID=[your-project-id] + $ export GCLOUD_PROJECT=[your-project-id] $ python main.py diff --git a/managed_vms/datastore/__init__.py b/managed_vms/datastore/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/datastore/app.yaml b/managed_vms/datastore/app.yaml index 1f8ff06ebfdb..78ba13172469 100644 --- a/managed_vms/datastore/app.yaml +++ b/managed_vms/datastore/app.yaml @@ -7,5 +7,5 @@ runtime_config: # [START env_variables] env_variables: - GCLOUD_DATASET_ID: your-project-id + GCLOUD_PROJECT: your-project-id # [END env_variables] diff --git a/managed_vms/datastore/main.py b/managed_vms/datastore/main.py index f4fd9bac4ad0..c924ae6d4533 100644 --- a/managed_vms/datastore/main.py +++ b/managed_vms/datastore/main.py @@ -13,6 +13,7 @@ # limitations under the License. import datetime +import os import socket from flask import Flask, request @@ -34,7 +35,7 @@ def is_ipv6(addr): # [START example] @app.route('/') def index(): - ds = datastore.Client() + ds = datastore.Client(os.environ['GCLOUD_PROJECT']) user_ip = request.remote_addr diff --git a/managed_vms/tests/memcache_test.py b/managed_vms/datastore/main_test.py similarity index 70% rename from managed_vms/tests/memcache_test.py rename to managed_vms/datastore/main_test.py index 1c69da13ba4f..e883e7251d68 100644 --- a/managed_vms/tests/memcache_test.py +++ b/managed_vms/datastore/main_test.py @@ -12,18 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +from testing import CloudTest -import requests +from . import main -from .runserver import RunServerTestCase - -class MemcacheTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'memcache') +class DatastoreTest(CloudTest): def test_index(self): - r = requests.get(self.server_url) + main.app.testing = True + client = main.app.test_client() + + r = client.get('/', environ_base={'REMOTE_ADDR': '127.0.0.1'}) self.assertEqual(r.status_code, 200) - self.assertTrue('Value is' in r.text) + self.assertTrue('127.0' in r.data.decode('utf-8')) diff --git a/managed_vms/disk/__init__.py b/managed_vms/disk/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/disk/main.py b/managed_vms/disk/main.py index f470bf7aec06..ee5c9ed5018e 100644 --- a/managed_vms/disk/main.py +++ b/managed_vms/disk/main.py @@ -13,6 +13,7 @@ # limitations under the License. import os +import socket from flask import Flask, request @@ -20,12 +21,28 @@ app = Flask(__name__) +def is_ipv6(addr): + """Checks if a given address is an IPv6 address.""" + try: + socket.inet_pton(socket.AF_INET6, addr) + return True + except socket.error: + return False + + # [START example] @app.route('/') def index(): instance_id = os.environ.get('GAE_MODULE_INSTANCE', '1') + user_ip = request.remote_addr + # Keep only the first two octets of the IP address. + if is_ipv6(user_ip): + user_ip = ':'.join(user_ip.split(':')[:2]) + else: + user_ip = '.'.join(user_ip.split('.')[:2]) + with open('/tmp/seen.txt', 'a') as f: f.write('{}\n'.format(user_ip)) diff --git a/managed_vms/tests/cloudsql_test.py b/managed_vms/disk/main_test.py similarity index 70% rename from managed_vms/tests/cloudsql_test.py rename to managed_vms/disk/main_test.py index 3714f84a3f5f..15aa04917887 100644 --- a/managed_vms/tests/cloudsql_test.py +++ b/managed_vms/disk/main_test.py @@ -12,18 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +from testing import CloudTest -import requests +from . import main -from .runserver import RunServerTestCase - -class CloudSqlTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'cloudsql') +class DiskTest(CloudTest): def test_index(self): - r = requests.get(self.server_url) + main.app.testing = True + client = main.app.test_client() + + r = client.get('/', environ_base={'REMOTE_ADDR': '127.0.0.1'}) self.assertEqual(r.status_code, 200) - self.assertTrue('127.0.0.1' in r.text) + self.assertTrue('127.0' in r.data.decode('utf-8')) diff --git a/managed_vms/extending_runtime/__init__.py b/managed_vms/extending_runtime/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/tests/extending_runtime_test.py b/managed_vms/extending_runtime/main_test.py similarity index 63% rename from managed_vms/tests/extending_runtime_test.py rename to managed_vms/extending_runtime/main_test.py index fdce4886e012..583ebbad0a8d 100644 --- a/managed_vms/tests/extending_runtime_test.py +++ b/managed_vms/extending_runtime/main_test.py @@ -13,23 +13,24 @@ # limitations under the License. import os -import platform from nose.plugins.skip import SkipTest -import requests +from testing import CloudTest -from .runserver import RunServerTestCase +from . import main -if platform.system() != 'Linux': - raise SkipTest("Extending runtime test will only execute on Linux.") +class ExtendingRuntimeTest(CloudTest): + def test_index(self): + if not os.path.exists('/usr/games/fortune'): + raise SkipTest( + 'Extending runtime test will only execute if fortune is' + 'installed') -class ExtendingRuntimeTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'extending_runtime') + main.app.testing = True + client = main.app.test_client() - def test_index(self): - r = requests.get(self.server_url) + r = client.get('/') self.assertEqual(r.status_code, 200) - self.assertTrue(len(r.text)) + self.assertTrue(len(r.data)) diff --git a/managed_vms/hello_world/__init__.py b/managed_vms/hello_world/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/tests/hello_world_test.py b/managed_vms/hello_world/main_test.py similarity index 73% rename from managed_vms/tests/hello_world_test.py rename to managed_vms/hello_world/main_test.py index ca6f0b22581d..34a3ab507b9d 100644 --- a/managed_vms/tests/hello_world_test.py +++ b/managed_vms/hello_world/main_test.py @@ -12,17 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +from testing import CloudTest -import requests +from . import main -from .runserver import RunServerTestCase - -class HelloWorldTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'hello_world') +class HelloWorldTest(CloudTest): def test_index(self): - r = requests.get(self.server_url) + main.app.testing = True + client = main.app.test_client() + + r = client.get('/') self.assertEqual(r.status_code, 200) + self.assertTrue('Hello World' in r.data.decode('utf-8')) diff --git a/managed_vms/hello_world_compat/__init__.py b/managed_vms/hello_world_compat/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/tests/datastore_test.py b/managed_vms/hello_world_compat/main_test.py similarity index 70% rename from managed_vms/tests/datastore_test.py rename to managed_vms/hello_world_compat/main_test.py index f148ffa386ba..34a3ab507b9d 100644 --- a/managed_vms/tests/datastore_test.py +++ b/managed_vms/hello_world_compat/main_test.py @@ -12,18 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +from testing import CloudTest -import requests +from . import main -from .runserver import RunServerTestCase - -class DatastoreTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'datastore') +class HelloWorldTest(CloudTest): def test_index(self): - r = requests.get(self.server_url) + main.app.testing = True + client = main.app.test_client() + + r = client.get('/') self.assertEqual(r.status_code, 200) - self.assertTrue('127.0.0.1' in r.text) + self.assertTrue('Hello World' in r.data.decode('utf-8')) diff --git a/managed_vms/mailgun/__init__.py b/managed_vms/mailgun/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/memcache/__init__.py b/managed_vms/memcache/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/tests/static_files_test.py b/managed_vms/memcache/main_test.py similarity index 66% rename from managed_vms/tests/static_files_test.py rename to managed_vms/memcache/main_test.py index 090bf8d47e3c..5cc4fb852c51 100644 --- a/managed_vms/tests/static_files_test.py +++ b/managed_vms/memcache/main_test.py @@ -12,20 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +from testing import CloudTest -import requests +from . import main -from .runserver import RunServerTestCase - -class StaticFilesTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'static_files') +class MemcacheTest(CloudTest): def test_index(self): - r = requests.get(self.server_url) + main.memcache_client.set('counter', 0) + main.app.testing = True + client = main.app.test_client() + + r = client.get('/') self.assertEqual(r.status_code, 200) + self.assertTrue('1' in r.data.decode('utf-8')) - r = requests.get(self.server_url + 'static/main.css') + r = client.get('/') self.assertEqual(r.status_code, 200) + self.assertTrue('2' in r.data.decode('utf-8')) diff --git a/managed_vms/pubsub/__init__.py b/managed_vms/pubsub/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/tests/pubsub_test.py b/managed_vms/pubsub/main_test.py similarity index 66% rename from managed_vms/tests/pubsub_test.py rename to managed_vms/pubsub/main_test.py index bb4c22c8d99e..b34662134549 100644 --- a/managed_vms/tests/pubsub_test.py +++ b/managed_vms/pubsub/main_test.py @@ -13,51 +13,54 @@ # limitations under the License. import base64 +import json import os -import requests +from testing import CloudTest -from .runserver import RunServerTestCase +from . import main -class PubSubTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'pubsub') +class PubSubTest(CloudTest): + def setUp(self): + super(PubSubTest, self).setUp() + main.app.testing = True + self.client = main.app.test_client() def test_index(self): - r = requests.get(self.server_url) + r = self.client.get('/') self.assertEqual(r.status_code, 200) def test_post_index(self): - r = requests.post(self.server_url, data={'payload': 'Test payload'}) + r = self.client.post('/', data={'payload': 'Test payload'}) self.assertEqual(r.status_code, 200) def test_push_endpoint(self): - url = self.server_url + 'pubsub/push?token=' + \ - os.environ['PUBSUB_VERIFICATION_TOKEN'] - r = requests.post( + url = '/pubsub/push?token=' + os.environ['PUBSUB_VERIFICATION_TOKEN'] + + r = self.client.post( url, - json={ + data=json.dumps({ "message": { "data": base64.b64encode( u'Test message'.encode('utf-8') ).decode('utf-8') } - } + }) ) self.assertEqual(r.status_code, 200) # Make sure the message is visible on the home page. - r = requests.get(self.server_url) + r = self.client.get('/') self.assertEqual(r.status_code, 200) - self.assertTrue('Test message' in r.text) + self.assertTrue('Test message' in r.data.decode('utf-8')) def test_push_endpoint_errors(self): # no token - r = requests.post(self.server_url + 'pubsub/push') + r = self.client.post('/pubsub/push') self.assertEqual(r.status_code, 400) # invalid token - r = requests.post(self.server_url + 'pubsub/push?token=bad') + r = self.client.post('/pubsub/push?token=bad') self.assertEqual(r.status_code, 400) diff --git a/managed_vms/sendgrid/__init__.py b/managed_vms/sendgrid/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/static_files/__init__.py b/managed_vms/static_files/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/static_files/main_test.py b/managed_vms/static_files/main_test.py new file mode 100644 index 000000000000..9861d6e953ea --- /dev/null +++ b/managed_vms/static_files/main_test.py @@ -0,0 +1,30 @@ +# Copyright 2015 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. + +from testing import CloudTest + +from . import main + + +class StaticFilesTest(CloudTest): + + def test_index(self): + main.app.testing = True + client = main.app.test_client() + + r = client.get('/') + self.assertEqual(r.status_code, 200) + + r = client.get('/static/main.css') + self.assertEqual(r.status_code, 200) diff --git a/managed_vms/storage/README.md b/managed_vms/storage/README.md index e182c5f40d32..6b7d977f76b7 100644 --- a/managed_vms/storage/README.md +++ b/managed_vms/storage/README.md @@ -29,5 +29,5 @@ When running locally, you can use the [Google Cloud SDK](https://cloud.google.co Then set environment variables before starting your application: $ export GCLOUD_PROJECT=[your-project-id] - $ export GCLOUD_STORAGE_BUCKET=[your-bucket-name] + $ export CLOUD_STORAGE_BUCKET=[your-bucket-name] $ python main.py diff --git a/managed_vms/storage/__init__.py b/managed_vms/storage/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/storage/app.yaml b/managed_vms/storage/app.yaml index 6f6f6d57c4b7..d03a94e30b88 100644 --- a/managed_vms/storage/app.yaml +++ b/managed_vms/storage/app.yaml @@ -8,5 +8,5 @@ runtime_config: #[START env] env_variables: GCLOUD_PROJECT: your-project-id - GCLOUD_STORAGE_BUCKET: your-bucket-name + CLOUD_STORAGE_BUCKET: your-bucket-name #[END env] diff --git a/managed_vms/storage/main.py b/managed_vms/storage/main.py index b8f338b9372c..26ebb55f7ed8 100644 --- a/managed_vms/storage/main.py +++ b/managed_vms/storage/main.py @@ -15,7 +15,7 @@ # [START app] import os -from flask import current_app, Flask, request +from flask import Flask, request from gcloud import storage # [start config] @@ -23,7 +23,7 @@ # Configure this environment variable via app.yaml -app.config['GCLOUD_STORAGE_BUCKET'] = os.environ['GCLOUD_STORAGE_BUCKET'] +CLOUD_STORAGE_BUCKET = os.environ['CLOUD_STORAGE_BUCKET'] # [end config] @@ -53,7 +53,7 @@ def upload(): gcs = storage.Client() # Get the bucket that the file will be uploaded to. - bucket = gcs.get_bucket(current_app.config['GCLOUD_STORAGE_BUCKET']) + bucket = gcs.get_bucket(CLOUD_STORAGE_BUCKET) # Create a new blob and upload the file's content. blob = bucket.blob(uploaded_file.filename) diff --git a/managed_vms/tests/storage_test.py b/managed_vms/storage/main_test.py similarity index 62% rename from managed_vms/tests/storage_test.py rename to managed_vms/storage/main_test.py index fc0cccfd4ee6..3037ffdf63d1 100644 --- a/managed_vms/tests/storage_test.py +++ b/managed_vms/storage/main_test.py @@ -12,33 +12,31 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os - import requests +from six import BytesIO +from testing import CloudTest -from .runserver import RunServerTestCase +from . import main -class StaticFilesTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'storage') +class StorageTest(CloudTest): + def setUp(self): + super(StorageTest, self).setUp() + main.app.testing = True + self.client = main.app.test_client() def test_index(self): - r = requests.get(self.server_url) + r = self.client.get('/') self.assertEqual(r.status_code, 200) def test_upload(self): # Upload a simple file - file_content = "This is some test content." - - r = requests.post( - self.server_url + 'upload', - files={ - 'file': ( - 'example.txt', - file_content, - 'text/plain' - ) + file_content = b"This is some test content." + + r = self.client.post( + '/upload', + data={ + 'file': (BytesIO(file_content), 'example.txt') } ) @@ -46,6 +44,6 @@ def test_upload(self): # The app should return the public cloud storage URL for the uploaded # file. Download and verify it. - cloud_storage_url = r.text + cloud_storage_url = r.data.decode('utf-8') r = requests.get(cloud_storage_url) - self.assertEqual(r.text, file_content) + self.assertEqual(r.text.encode('utf-8'), file_content) diff --git a/managed_vms/tests/disk_test.py b/managed_vms/tests/disk_test.py deleted file mode 100644 index 28552e0a523d..000000000000 --- a/managed_vms/tests/disk_test.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2015 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. - -import os - -import requests - -from .runserver import RunServerTestCase - - -class DiskTest(RunServerTestCase): - application_path = os.path.join( - os.path.dirname(__file__), '..', 'disk') - - def test_index(self): - r = requests.get(self.server_url) - self.assertEqual(r.status_code, 200) - self.assertTrue('127.0.0.1' in r.text) - self.assertTrue(os.path.exists('/tmp/seen.txt')) diff --git a/managed_vms/tests/runserver.py b/managed_vms/tests/runserver.py deleted file mode 100644 index 09089d2ee4e4..000000000000 --- a/managed_vms/tests/runserver.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2015 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. - -import logging -import multiprocessing -import os -import sys -import time -import unittest - -import requests -from werkzeug.serving import run_simple - - -logging.getLogger("requests").setLevel(logging.WARNING) - - -def run_app(path, port, entrypoint): - path = os.path.realpath(path) - sys.path.insert(1, path) - os.chdir(path) - - module_name, wsgi_app_name = entrypoint.rsplit('.', 1) - - module = __import__(module_name) - wsgi_app = getattr(module, wsgi_app_name) - - wsgi_app.debug = True - run_simple('localhost', port, wsgi_app, use_debugger=True) - - -def run_app_multiprocessing(path, port=43125, entrypoint='main.app'): - process = multiprocessing.Process( - target=run_app, args=(path, port, entrypoint)) - process.start() - - try: - _wait_for_server(port) - except: - process.terminate() - raise - - return process - - -def _wait_for_server(port): - start = time.time() - while True: - try: - requests.get('http://localhost:{}/_ah/health'.format(port)) - # Break on first successful request, regardless of status, as it - # means the server is accepting connections. - break - except requests.ConnectionError: - if time.time() - start > 5: - raise RuntimeError('Server failed to respond to requests.') - - -class RunServerTestCase(unittest.TestCase): - server_host = 'locahost' - server_port = 43125 - server_url = 'http://localhost:43125/' - - application_path = None - application_entrypoint = 'main.app' - _server_process = None - - @classmethod - def setUpClass(cls): - cls._server_process = run_app_multiprocessing( - cls.application_path, - entrypoint=cls.application_entrypoint) - - @classmethod - def tearDownClass(cls): - if cls._server_process: - cls._server_process.terminate() diff --git a/managed_vms/twilio/__init__.py b/managed_vms/twilio/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/websockets/__init__.py b/managed_vms/websockets/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/managed_vms/websockets/app.yaml b/managed_vms/websockets/app.yaml index bdbc261e352e..2f6511b7a315 100644 --- a/managed_vms/websockets/app.yaml +++ b/managed_vms/websockets/app.yaml @@ -4,8 +4,10 @@ vm: true # Use a special gunicorn worker class to support websockets. entrypoint: gunicorn -b :$PORT -b :65080 -k flask_sockets.worker main:app +# We must use python 2 because flask-sockets depends on gevent which +# doesn't currently have Python 3 support. runtime_config: - python_version: 3 + python_version: 2 # [START network] network: diff --git a/monitoring/api/auth_test.py b/monitoring/api/auth_test.py index 6a0aa356613d..5bd05c0f4a0f 100644 --- a/monitoring/api/auth_test.py +++ b/monitoring/api/auth_test.py @@ -13,16 +13,16 @@ import re -import tests +import testing from . import auth -class TestTimeseriesList(tests.CloudBaseTest): +class TestTimeseriesList(testing.CloudTest): def test_main(self): - with tests.capture_stdout() as stdout: - auth.main(self.project_id) + with testing.capture_stdout() as stdout: + auth.main(self.config.GCLOUD_PROJECT) output = stdout.getvalue().strip() diff --git a/python-docs-samples.json.enc b/python-docs-samples.json.enc deleted file mode 100644 index 9c34df7c1096edfec3f76836035103562e10e4e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1248 zcmV<61RwilW0ub~2$Wb@{+e(Rb_MIPK8jaJ`z5^;B*=TOk%!wDg7-Al&peYMttX#6 z3DhFv-GP9eCLnn$GG&ok7O8=FTb57-tpsWZ01G z2MAP5WS_oSX}sH}RDrw~W?N)i%E-XU+(`-B(1bgOE*Glm#E6YvJ#CLpyWOojbxS(P z`*>9&^U?_-r4G0$gC+HYqMX+*JAaDl3;*%pAdou@=F``Z44KE!zv!bV!ta}RC3J{(l@*~?0psH) zktNDoSPlp}9P%%m7Y>W3(Hs@z^emyt-K`q^=E2#x>7tT>AxE$NB-#%pXJJ$uiyjIZ z+L3W5LTNzvYoawO)#n{`_xvH~+9xFtJ|&B+sAK}l@gD54DPl-d6Q7&wmTCKw=>N|c zUQQ`V{cgvjc`91~T?v^6k`E9>TH`BU4e8)g<{Q*R5esV&HFF~dDmrw4?#C3kSnQe) zTPoDqS!@>Y)p#inR`ID}+-<&cgt7E^nJnMXPKeXc^fc~KAv#yFs!Tz4{Ejz|v>6_q z?{r1^Nso3=*-NA>)*?fj_2C2Gm^7=TeeU>`?&3PozrxI&@E4^_IvwgNlF~>m`w~sN zeCe2wnh&xz5}j}lT6sh<|JYq<){fCsZ!1k<036M*A@BTJ?A&oXV>2L-dv*BA<{-1k zc0=^8tkUm9!wnNeI(5_urGJ<(g_X$a!#Gc$e>y}Hr7A<4|Jgqfjm&M62o*SvEYB=n zNFZ#ZE}hjmn{)_)3=_&^Qxygt=G^jfSIFQMnmcq~04V#@C&NZ*M}UvFMvyVvrEMY{ zimT_N7NhpW7r?N01q#2`%0&3p)1^SMF86~S*F!yY6|uLO(!G&6h4l?TUIQd=r@ElP zJ7EsVWE-ll%u0)NG*Cw{WrWA-9q}a4Dz{I%R=)BVp9f)$;T;jB0#5IfwjGo`H;g1dHqb(2!LMhF zaMriny;FuG*M{SZ6;py-GTm>SIihLB z!hje;Ng!s%`4$;${cAa#Q({f&70_00ymkPe4EH7nwkHYQf&OnI^*h}?DCJwoN0KzC z%G^q_s8)q*`}IgzX~J-e97JN)@wn=n=F941A;R8|J~`=q?g5;z=k~24MVOvVQNFZg zGMcV`@N@Y80t_=E!(2i`jZRS~5iH5)DSZZQOa%Ky7_Fmw{-s}6XT4V%Jf1#ST!hM9 zeie=_r;5)Dp>s2*57w?%{waj3j(%))jBCWRUP?uU*%|aa9;$~F^Ll~sSIuS&%L{gm KQ0(lVI2S8q-DC#< diff --git a/requirements-py27-dev.txt b/requirements-py27-dev.txt new file mode 100644 index 000000000000..66a2b53c0620 --- /dev/null +++ b/requirements-py27-dev.txt @@ -0,0 +1,28 @@ +beautifulsoup4==4.4.1 +coverage==4.1b2 +Flask==0.10.1 +funcsigs==0.4 +itsdangerous==0.24 +Jinja2==2.8 +MarkupSafe==0.23 +mock==1.3.0 +nose==1.3.7 +nose-exclude==0.4.1 +nosegae==0.5.8 +pbr==1.8.1 +PyYAML==3.11 +waitress==0.8.10 +WebOb==1.6.0a0 +WebTest==2.0.20 +Werkzeug==0.11.3 +nose-timer==0.6.0 +Flask-SQLAlchemy==2.1 +PyMySQL==0.7.1 +python-memcached==1.57 +PyCrypto==2.6.1 +flaky==3.1.0 +Django==1.9.2 +twilio==6.3.dev0 +sendgrid==1.6.22 +Flask-Sockets==0.2.0 +mysql-python==1.2.5 diff --git a/requirements-dev.txt b/requirements-py34-dev.txt similarity index 81% rename from requirements-dev.txt rename to requirements-py34-dev.txt index 6aef1a1659df..e9b43e36f825 100644 --- a/requirements-dev.txt +++ b/requirements-py34-dev.txt @@ -15,9 +15,12 @@ waitress==0.8.10 WebOb==1.6.0a0 WebTest==2.0.20 Werkzeug==0.11.3 -nose-timer==0.5.0 +nose-timer==0.6.0 Flask-SQLAlchemy==2.1 PyMySQL==0.7.1 python-memcached==1.57 PyCrypto==2.6.1 -flaky==3.0.3 +flaky==3.1.0 +Django==1.9.2 +twilio==6.3.dev0 +sendgrid==1.6.22 diff --git a/scripts/check_requirements.py b/scripts/check_requirements.py deleted file mode 100755 index ecc8295f0881..000000000000 --- a/scripts/check_requirements.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2013 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. - -""" -Checks dependencies in requirements.txt to ensure they are the latest version. -""" - -import argparse -import sys - -from update_requirements import get_package_info, read_requirements - - -def check_req(req): - info = get_package_info(req.project_name) - newest_version = info['version'] - current_spec = req.specs[0] if req.specs else ('==', 'unspecified') - if current_spec[1] != newest_version: - return req, newest_version - - -def main(req_file): - reqs = read_requirements(req_file) - outdated_reqs = filter(None, [check_req(req) for req in reqs]) - - if outdated_reqs: - for req in outdated_reqs: - print("{} is out of date, latest version is {}".format(*req)) - sys.exit(1) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - 'requirements_file', - help='Path the the requirements.txt file to check.') - - args = parser.parse_args() - - main(args.requirements_file) diff --git a/scripts/encrypt-secrets.sh b/scripts/encrypt-secrets.sh new file mode 100755 index 000000000000..c836438540b4 --- /dev/null +++ b/scripts/encrypt-secrets.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Copyright 2015 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. + +echo "Enter password for encryption: " +read password + +tar cvf secrets.tar testing/resources/{service-account.json,test-env.sh} +openssl aes-256-cbc -k "$password" -in secrets.tar -out secrets.tar.enc +rm secrets.tar + +travis encrypt "secrets_password=$password" --add diff --git a/scripts/prepare-testing-project.sh b/scripts/prepare-testing-project.sh new file mode 100755 index 000000000000..1b62ea0f7f8f --- /dev/null +++ b/scripts/prepare-testing-project.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Copyright 2015 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. + +GCLOUD_PROJECT=$(gcloud config list project --format="value(core.project)" 2>/dev/null) + +echo "Configuring project $GCLOUD_PROJECT for system tests." + +echo "Creating cloud storage bucket." +gsutil mb gs://$GCLOUD_PROJECT +gsutil defacl set public-read gs://$GCLOUD_PROJECT + +echo "Creating bigquery resources." +gcloud alpha bigquery datasets create test_dataset +gcloud alpha bigquery datasets create ephemeral_test_dataset +gsutil cp tests/resources/data.csv gs://$GCLOUD_PROJECT/data.csv +gcloud alpha bigquery import \ + gs://$GCLOUD_PROJECT/data.csv \ + test_dataset/test_table \ + --schema-file tests/resources/schema.json + +echo "Creating datastore indexes." +gcloud preview app deploy -q datastore/api/index.yaml + +echo "Creating pubsub resources." +gcloud alpha pubsub topics create gae-mvm-pubsub-topic + +echo "To finish setup, follow this link to enable APIs." +echo "https://console.cloud.google.com/flows/enableapi?apiid=datastore,pubsub,storage_api,logging,plus,bigquery,cloudmonitoring,compute_component" diff --git a/scripts/docs-links.json b/scripts/resources/docs-links.json similarity index 100% rename from scripts/docs-links.json rename to scripts/resources/docs-links.json diff --git a/scripts/update_requirements.py b/scripts/update_requirements.py deleted file mode 100755 index e4f76a3c5ebe..000000000000 --- a/scripts/update_requirements.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2013 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. - -""" -Updates dependencies in requirements.txt to the latest version. -""" - -import argparse - -from pip.req.req_file import parse_requirements -from pkg_resources import Requirement -import requests - - -def get_package_info(package): - url = 'https://pypi.python.org/pypi/{}/json'.format(package) - r = requests.get(url) - r.raise_for_status() - return r.json()['info'] - - -def read_requirements(req_file): - return [x.req for x in parse_requirements(req_file, session={})] - - -def update_req(req): - info = get_package_info(req.project_name) - newest_version = info['version'] - current_spec = req.specs[0] if req.specs else ('==', 'unspecified') - new_spec = ('==', newest_version) - if current_spec != new_spec: - newreq = Requirement(req.unsafe_name, [new_spec], req.extras) - print('Updated {} from {} -> {}'.format( - req.project_name, - current_spec[1], - newest_version)) - return newreq - return req - - -def write_requirements(reqs, req_file): - with open(req_file, 'w') as f: - for req in reqs: - f.write('{}\n'.format(req)) - - -def main(req_file): - reqs = read_requirements(req_file) - reqs = [update_req(req) for req in reqs] - write_requirements(reqs, req_file) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - 'requirements_file', - help='Path the the requirements.txt file to update.') - - args = parser.parse_args() - - main(args.requirements_file) diff --git a/secrets.tar.enc b/secrets.tar.enc new file mode 100644 index 0000000000000000000000000000000000000000..24e60b17ab7835f709fa9c459d9e37f73218f14d GIT binary patch literal 9760 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] - -Current releases are listed here: - https://www.googleapis.com/storage/v1/b/appengine-sdks/o?prefix=featured -""" - -import json -import os -import StringIO -import sys -import urllib2 -import zipfile - -_SDK_URL = ( - 'https://www.googleapis.com/storage/v1/b/appengine-sdks/o?prefix=featured') - - -def get_gae_versions(): - try: - version_info_json = urllib2.urlopen(_SDK_URL).read() - except: - return {} - try: - version_info = json.loads(version_info_json) - except: - return {} - return version_info.get('items', {}) - - -def _version_tuple(v): - version_string = os.path.splitext(v['name'])[0].rpartition('_')[2] - return tuple(int(x) for x in version_string.split('.')) - - -def get_sdk_urls(sdk_versions): - python_releases = [ - v for v in sdk_versions - if v['name'].startswith('featured/google_appengine')] - current_releases = sorted( - python_releases, key=_version_tuple, reverse=True) - return [release['mediaLink'] for release in current_releases] - - -def main(argv): - if len(argv) > 2: - print('Usage: {} []'.format(argv[0])) - return 1 - dest_dir = argv[1] if len(argv) > 1 else '.' - if not os.path.exists(dest_dir): - os.makedirs(dest_dir) - - if os.path.exists(os.path.join(dest_dir, 'google_appengine')): - print('GAE SDK already installed at {}, exiting.'.format(dest_dir)) - return 0 - - sdk_versions = get_gae_versions() - if not sdk_versions: - print('Error fetching GAE SDK version info') - return 1 - sdk_urls = get_sdk_urls(sdk_versions) - for sdk_url in sdk_urls: - try: - sdk_contents = StringIO.StringIO(urllib2.urlopen(sdk_url).read()) - break - except: - pass - else: - print('Could not read SDK from any of {}'.format(sdk_urls)) - return 1 - sdk_contents.seek(0) - try: - zip_contents = zipfile.ZipFile(sdk_contents) - zip_contents.extractall(dest_dir) - print('GAE SDK Installed to {}.'.format(dest_dir)) - except: - print('Error extracting SDK contents') - return 1 - -if __name__ == '__main__': - sys.exit(main(sys.argv[:])) diff --git a/tests/scripts/travis-before-install.sh b/tests/scripts/travis-before-install.sh deleted file mode 100755 index eeae644adc4c..000000000000 --- a/tests/scripts/travis-before-install.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -ev - -# Install Google App Engine Python SDK -if [[ ! -d "${GAE_PYTHONPATH}" ]]; then - python tests/scripts/fetch_gae_sdk.py `dirname "${GAE_PYTHONPATH}"` -fi - -# Google Cloud Service account key. -# ENCRYPT YOUR PRIVATE KEY (If you need authentication) -# 1. Install and login to the Travis CLI: -# $ gem install travis -# $ travis login -# 2. Move your json private key to client_secrets.json -# 3. Run: -# $ travis encrypt-file client_secrets.json --add -# 4. Commit changes: -# $ git add client_secrets.json.enc -# $ git commit client_secrets.json.enc .travis.yml -openssl aes-256-cbc \ - -K $encrypted_4fda24e244ca_key \ - -iv $encrypted_4fda24e244ca_iv \ - -in ${TRAVIS_BUILD_DIR}/python-docs-samples.json.enc \ - -out ${TRAVIS_BUILD_DIR}/python-docs-samples.json -d diff --git a/tox.ini b/tox.ini index d754bc9ed360..bc7a3e9b045c 100644 --- a/tox.ini +++ b/tox.ini @@ -3,11 +3,22 @@ skipsdist = True envlist = pep8, reqcheck, gae, py27, py34 [testenv] -passenv = PYTHONPATH GOOGLE_* GCLOUD_* TEST_* TRAVIS* +passenv = + PYTHONPATH + GOOGLE_* + GCLOUD_* + TEST_* + CLOUD_* + TRAVIS* + SQLALCHEMY_DATABASE_URI + PUBSUB_* + GA_TRACKING_ID + MAILGUN_* + SENDGRID_* + TWILIO_* basepython = python2.7 deps = -rrequirements.txt - -rrequirements-dev.txt commonargs = --with-timer --with-coverage @@ -16,30 +27,38 @@ commonargs = --cover-inclusive --with-flaky --no-success-flaky-report + --exclude-dir=managed_vms/django_cloudsql + --exclude-dir=managed_vms/hello_world_django [testenv:reqcheck] -deps = - requests[security] commands = bash -c "find . -name requirements\*.txt |\ - xargs -n 1 ./scripts/check_requirements.py" -whitelist_externals = bash + xargs -P 4 -n 1 gcp-python-repo-tools check-requirements" +whitelist_externals = + bash + find + xargs + gcp-python-repo-tools [testenv:requpdate] -deps = - requests[security] commands = bash -c "find . -name requirements\*.txt |\ - xargs -n 1 ./scripts/update_requirements.py" -whitelist_externals = bash + xargs -P 4 -n 1 gcp-python-repo-tools update-requirements" +whitelist_externals = + bash + find + xargs + gcp-python-repo-tools [testenv:gae] deps = {[testenv]deps} - mysql-python==1.2.5 -commands = + -rrequirements-py27-dev.txt +commands = + # Create a lib directory, otherwise, the vendor library will explode. + mkdir lib nosetests --with-gae \ - --gae-app=tests/resources/app.yaml \ + --gae-app=appengine/resources/app.yaml \ --logging-level=INFO \ --with-xunit \ --xunit-testsuite-name gae \ @@ -48,11 +67,13 @@ commands = {posargs:appengine} setenv = PYTHONPATH={env:GAE_PYTHONPATH:} +whitelist_externals = mkdir [testenv:py27] deps = {[testenv]deps} -commands = + -rrequirements-py27-dev.txt +commands = nosetests \ --exclude-dir=appengine \ {[testenv]commonargs} \ @@ -62,15 +83,18 @@ commands = basepython = python3.4 deps = {[testenv]deps} + -rrequirements-py34-dev.txt commands = nosetests \ --exclude-dir=appengine \ + # Websockets doesn't work with py34 because of gevent dep. + --exclude-dir=managed_vms/websockets \ {[testenv]commonargs} \ {posargs:-a '!slow,!flaky'} [testenv:py27-all] deps = - {[testenv]deps} + {[testenv:py27]deps} commands = nosetests \ --exclude-dir=appengine \ @@ -83,10 +107,11 @@ commands = [testenv:py34-all] basepython = python3.4 deps = - {[testenv]deps} + {[testenv:py34]deps} commands = nosetests \ --exclude-dir=appengine \ + --exclude-dir=managed_vms/websockets \ {[testenv]commonargs} \ --with-xunit \ --xunit-testsuite-name py34 \