Skip to content

Commit 597763f

Browse files
busunkim96nicain
andauthored
fix: create separate bucket for iot gcs_file_to_device test (GoogleCloudPlatform#6732)
Co-authored-by: nicain <nicain.seattle@gmail.com>
1 parent 57e6dc4 commit 597763f

File tree

5 files changed

+110
-27
lines changed

5 files changed

+110
-27
lines changed

appengine/flexible/storage/main.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# [START gae_flex_storage_app]
1616
import logging
1717
import os
18+
from typing import Union
1819

1920
from flask import Flask, request
2021
from google.cloud import storage
@@ -26,7 +27,7 @@
2627

2728

2829
@app.route('/')
29-
def index():
30+
def index() -> str:
3031
return """
3132
<form method="POST" action="/upload" enctype="multipart/form-data">
3233
<input type="file" name="file">
@@ -36,7 +37,7 @@ def index():
3637

3738

3839
@app.route('/upload', methods=['POST'])
39-
def upload():
40+
def upload() -> str:
4041
"""Process the uploaded file and upload it to Google Cloud Storage."""
4142
uploaded_file = request.files.get('file')
4243

@@ -57,12 +58,17 @@ def upload():
5758
content_type=uploaded_file.content_type
5859
)
5960

61+
# Make the blob public. This is not necessary if the
62+
# entire bucket is public.
63+
# See https://cloud.google.com/storage/docs/access-control/making-data-public.
64+
blob.make_public()
65+
6066
# The public URL can be used to directly access the uploaded file via HTTP.
6167
return blob.public_url
6268

6369

6470
@app.errorhandler(500)
65-
def server_error(e):
71+
def server_error(e: Union[Exception, int]) -> str:
6672
logging.exception('An error occurred during a request.')
6773
return """
6874
An internal error occurred: <pre>{}</pre>

appengine/flexible/storage/main_test.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import os
16+
import uuid
17+
18+
import flask
19+
import flask.testing
20+
from google.cloud import storage
1521
import pytest
1622
import requests
1723
from six import BytesIO
@@ -20,24 +26,34 @@
2026

2127

2228
@pytest.fixture
23-
def client():
29+
def client() -> flask.testing.FlaskClient:
2430
main.app.testing = True
2531
return main.app.test_client()
2632

2733

28-
def test_index(client):
34+
def test_index(client: flask.testing.FlaskClient) -> None:
2935
r = client.get('/')
3036
assert r.status_code == 200
3137

3238

33-
def test_upload(client):
39+
@pytest.fixture(scope="module")
40+
def blob_name() -> str:
41+
name = f"gae-flex-storage-{uuid.uuid4()}"
42+
yield name
43+
44+
bucket = storage.Client().bucket(os.environ["CLOUD_STORAGE_BUCKET"])
45+
blob = bucket.blob(name)
46+
blob.delete()
47+
48+
49+
def test_upload(client: flask.testing.FlaskClient, blob_name: str) -> None:
3450
# Upload a simple file
3551
file_content = b"This is some test content."
3652

3753
r = client.post(
3854
'/upload',
3955
data={
40-
'file': (BytesIO(file_content), 'example.txt')
56+
'file': (BytesIO(file_content), blob_name)
4157
}
4258
)
4359

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7"],
26+
# Old samples are opted out of enforcing Python type hints
27+
# All new samples should feature them
28+
"enforce_type_hints": True,
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
# If you need to use a specific version of pip,
36+
# change pip_version_override to the string representation
37+
# of the version number, for example, "20.2.4"
38+
"pip_version_override": None,
39+
# A dictionary you want to inject into your test. Don't put any
40+
# secrets here. These values will override predefined values.
41+
"envs": {
42+
"CLOUD_STORAGE_BUCKET": "python-docs-samples-tests-public"
43+
},
44+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pytest==6.2.4
2+
google-cloud-storage==1.42.2

iot/api-client/gcs_file_to_device/gcs_send_to_device_test.py

+36-20
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
from google.cloud import pubsub
2222
from google.cloud import storage
23-
import mock
2423
import pytest
2524
import requests
2625

@@ -30,8 +29,6 @@
3029
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "manager")) # noqa
3130
import manager # noqa
3231

33-
34-
gcs_bucket = os.environ["CLOUD_STORAGE_BUCKET"]
3532
project_id = os.environ["GOOGLE_CLOUD_PROJECT"]
3633
service_account_json = os.environ["GOOGLE_APPLICATION_CREDENTIALS"]
3734

@@ -44,13 +41,36 @@
4441
destination_file_name = "destination-file.bin"
4542
gcs_file_name = "my-config"
4643

44+
storage_client = storage.Client()
45+
46+
47+
@pytest.fixture(scope="module")
48+
def test_bucket_name():
49+
bucket_name = "python-docs-samples-iot-{}".format(uuid.uuid4())
50+
51+
yield bucket_name
52+
53+
bucket = storage_client.bucket(bucket_name)
54+
bucket.delete(force=True)
55+
4756

4857
@pytest.fixture(scope="module")
49-
def test_blob():
58+
def test_bucket(test_bucket_name):
59+
"""Yields a bucket that is deleted after the test completes."""
60+
bucket = storage_client.bucket(test_bucket_name)
61+
62+
if not bucket.exists():
63+
bucket = storage_client.create_bucket(test_bucket_name)
64+
65+
yield bucket.name
66+
67+
68+
@pytest.fixture(scope="module")
69+
def test_blob(test_bucket):
5070
"""Provides a pre-existing blob in the test bucket."""
51-
bucket = storage.Client().bucket(gcs_bucket)
71+
bucket = storage_client.bucket(test_bucket)
5272
# Name of the blob
53-
blob = bucket.blob("iot_core_store_file_gcs")
73+
blob = bucket.blob("iot_core_store_file_gcs-{}".format(uuid.uuid4()))
5474
# Text in the blob
5575
blob.upload_from_string("This file on GCS will go to a device.")
5676

@@ -63,39 +83,35 @@ def test_blob():
6383
pass
6484

6585

66-
@mock.patch("google.cloud.storage.client.Client.create_bucket")
67-
def test_create_bucket(create_bucket_mock, capsys):
68-
# Unlike other tests for sending a config, this one mocks out the creation
69-
# because buckets are expensive, globally-namespaced objects.
70-
create_bucket_mock.return_value = mock.sentinel.bucket
71-
72-
gcs_to_device.create_bucket(gcs_bucket)
86+
def test_create_bucket(test_bucket_name, capsys):
87+
gcs_to_device.create_bucket(test_bucket_name)
7388

74-
create_bucket_mock.assert_called_with(gcs_bucket)
89+
out, _ = capsys.readouterr()
90+
assert f"Bucket {test_bucket_name} created" in out
7591

7692

77-
def test_upload_local_file(capsys):
93+
def test_upload_local_file(test_bucket, capsys):
7894
# Creates a temporary source file that gets uploaded
7995
# to GCS. All other tests use the blob in test_blob().
8096
with tempfile.NamedTemporaryFile() as source_file:
8197
source_file.write(b"This is a source file.")
8298

83-
gcs_to_device.upload_local_file(gcs_bucket, gcs_file_name, source_file.name)
99+
gcs_to_device.upload_local_file(test_bucket, gcs_file_name, source_file.name)
84100

85101
out, _ = capsys.readouterr()
86102
assert "File {} uploaded as {}.".format(source_file.name, gcs_file_name) in out
87103

88104

89-
def test_make_file_public(test_blob):
90-
gcs_to_device.make_file_public(gcs_bucket, test_blob.name)
105+
def test_make_file_public(test_bucket, test_blob):
106+
gcs_to_device.make_file_public(test_bucket, test_blob.name)
91107

92108
r = requests.get(test_blob.public_url)
93109
# Test for the content of the file to verify that
94110
# it's publicly accessible.
95111
assert r.text == "This file on GCS will go to a device."
96112

97113

98-
def test_send_to_device(capsys):
114+
def test_send_to_device(test_bucket, capsys):
99115
manager.create_iot_topic(project_id, topic_id)
100116
manager.open_registry(
101117
service_account_json, project_id, cloud_region, pubsub_topic, registry_id
@@ -106,7 +122,7 @@ def test_send_to_device(capsys):
106122
)
107123

108124
gcs_to_device.send_to_device(
109-
gcs_bucket,
125+
test_bucket,
110126
gcs_file_name,
111127
destination_file_name,
112128
project_id,

0 commit comments

Comments
 (0)