Skip to content

Commit 74ba429

Browse files
authored
Better CI (#34)
unittests run samples use builder.py for CI
1 parent 30152d1 commit 74ba429

File tree

6 files changed

+251
-30
lines changed

6 files changed

+251
-30
lines changed

builder.json

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"name": "aws-iot-device-sdk-python-v2",
3+
"hosts": {
4+
"al2012": {
5+
"enabled": false,
6+
"_comment": "al2012 can't currently pull builder.py from github. SSL: CERTIFICATE_VERIFY_FAILED"
7+
},
8+
"linux": {
9+
"architectures": {
10+
"x86": {
11+
"enabled": false,
12+
"_comment": "this 'x86' machine actually uses 64bit python, no point in running it"
13+
}
14+
}
15+
},
16+
"windows": {
17+
"architectures": {
18+
"x86": {
19+
"enabled": false,
20+
"_comment": "this 'x86' machine actually uses 64bit python, no point in running it"
21+
}
22+
}
23+
},
24+
"manylinux": {
25+
"post_build_steps": [
26+
["echo", "------ Python 3.6 ------"],
27+
["/opt/python/cp36-cp36m/bin/python", "-m", "pip", "install", "--upgrade", "pip", "setuptools"],
28+
["/opt/python/cp36-cp36m/bin/python", "-m", "pip", "install", ".", "--verbose"],
29+
["/opt/python/cp36-cp36m/bin/python", "-m", "pip", "install", "boto3", "autopep8"],
30+
["/opt/python/cp36-cp36m/bin/python", "-m", "unittest", "discover", "--verbose"],
31+
["echo", "------ Python 3.5 ------"],
32+
["/opt/python/cp35-cp35m/bin/python", "-m", "pip", "install", "--upgrade", "pip", "setuptools"],
33+
["/opt/python/cp35-cp35m/bin/python", "-m", "pip", "install", ".", "--verbose"],
34+
["/opt/python/cp35-cp35m/bin/python", "-m", "pip", "install", "boto3", "autopep8"],
35+
["/opt/python/cp35-cp35m/bin/python", "-m", "unittest", "discover", "--verbose"],
36+
["echo", "------ Python 3.4 ------"],
37+
["/opt/python/cp34-cp34m/bin/python", "-m", "pip", "install", "--upgrade", "pip", "setuptools"],
38+
["/opt/python/cp34-cp34m/bin/python", "-m", "pip", "install", ".", "--verbose"],
39+
["/opt/python/cp34-cp34m/bin/python", "-m", "pip", "install", "boto3", "autopep8"],
40+
["/opt/python/cp34-cp34m/bin/python", "-m", "unittest", "discover", "--verbose"],
41+
["echo", "------ Python 2.7 narrow-unicode ------"],
42+
["/opt/python/cp27-cp27m/bin/python", "-m", "pip", "install", "--upgrade", "pip", "setuptools"],
43+
["/opt/python/cp27-cp27m/bin/python", "-m", "pip", "install", ".", "--verbose"],
44+
["/opt/python/cp27-cp27m/bin/python", "-m", "pip", "install", "boto3", "autopep8"],
45+
["/opt/python/cp27-cp27m/bin/python", "-m", "unittest", "discover", "--verbose"],
46+
["echo", "------ Python 2.7 wide-unicode ------"],
47+
["/opt/python/cp27-cp27mu/bin/python", "-m", "pip", "install", "--upgrade", "pip", "setuptools"],
48+
["/opt/python/cp27-cp27mu/bin/python", "-m", "pip", "install", ".", "--verbose"],
49+
["/opt/python/cp27-cp27mu/bin/python", "-m", "pip", "install", "boto3", "autopep8"],
50+
["/opt/python/cp27-cp27mu/bin/python", "-m", "unittest", "discover", "--verbose"]
51+
],
52+
"run_tests": false,
53+
"_comment": "manylinux has all its own build steps, turn off 'tests' which is where normal build steps are declared. using data to program sucks"
54+
}
55+
},
56+
"targets": {
57+
"android": {
58+
"enabled": false,
59+
"_comment": "disabled until we have a reason to support python on android"
60+
}
61+
},
62+
"compilers": {
63+
"_comment": "don't need compiler variants because awsiot is pure python. It will use precompiled awscrt wheels pulled from pip.",
64+
"clang": { "enabled": false },
65+
"gcc": {
66+
"versions": {
67+
"_comment": "run gcc 4.8 because that's what the linux wheels were made with",
68+
"5": { "enabled": false },
69+
"6": { "enabled": false },
70+
"7": { "enabled": false },
71+
"8": { "enabled": false }
72+
}
73+
},
74+
"msvc": {
75+
"versions": {
76+
"_comment": "run msvc 2015 because that's what the windows wheels were made with",
77+
"2017": { "enabled": false }
78+
}
79+
}
80+
},
81+
"upstream": [],
82+
"downstream": [],
83+
"_comment": "doing everything in 'test' step so that manylinux can turn off tests and do its stuff in the 'post_build_step'. using data to program really sucks",
84+
"build": [
85+
["{python}", "-c", "print('ignore this fake build step')"]
86+
],
87+
"test": [
88+
["{python}", "-m", "pip", "install", "--upgrade", "pip", "setuptools"],
89+
["{python}", "-m", "pip", "install", ".", "--verbose"],
90+
["{python}", "-m", "pip", "install", "boto3", "autopep8"],
91+
["{python}", "-m", "unittest", "discover", "--verbose"]
92+
]
93+
}

codebuild/install_and_run_samples.yml

Lines changed: 0 additions & 29 deletions
This file was deleted.

samples/basic_discovery.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)
6060

6161
tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(args.certificate_path, args.private_key_path)
62-
tls_options.override_default_trust_store_from_path(None, args.root_ca_path)
62+
if args.root_ca_path:
63+
tls_options.override_default_trust_store_from_path(None, args.root_ca_path)
6364
tls_context = io.ClientTlsContext(tls_options)
6465

6566
socket_options = io.SocketOptions()

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[pep8]
2+
max-line-length = 120
3+
aggressive = 2

test/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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+
# A copy of the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0
8+
#
9+
# or in the 'license' file accompanying this file. This file is distributed
10+
# on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
12+
# permissions and limitations under the License.

test/test_samples.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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+
# A copy of the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0
8+
#
9+
# or in the 'license' file accompanying this file. This file is distributed
10+
# on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
# express or implied. See the License for the specific language governing
12+
# permissions and limitations under the License.
13+
from __future__ import absolute_import, print_function
14+
import awsiot
15+
import boto3
16+
import botocore.exceptions
17+
import os.path
18+
import shutil
19+
import subprocess
20+
import sys
21+
import tempfile
22+
import unittest
23+
import uuid
24+
import warnings
25+
26+
27+
class Config:
28+
cache = None
29+
30+
def __init__(self, endpoint, cert, key, region):
31+
self.endpoint = endpoint
32+
self.region = region
33+
self.cert_bytes = cert
34+
self.key_bytes = key
35+
36+
self._tmp_dirpath = tempfile.mkdtemp()
37+
self.cert_filepath = os.path.join(self._tmp_dirpath, 'certificate.pem')
38+
with open(self.cert_filepath, 'wb') as cert_file:
39+
cert_file.write(cert)
40+
41+
self.key_filepath = os.path.join(self._tmp_dirpath, 'privatekey.pem')
42+
with open(self.key_filepath, 'wb') as key_file:
43+
key_file.write(key)
44+
45+
def __del__(self):
46+
shutil.rmtree(self._tmp_dirpath)
47+
48+
@staticmethod
49+
def get():
50+
"""Raises SkipTest if credentials aren't set up correctly"""
51+
if Config.cache:
52+
return Config.cache
53+
54+
# boto3 caches the HTTPS connection for the API calls, which appears to the unit test
55+
# framework as a leak, so ignore it, that's not what we're testing here
56+
try:
57+
warnings.simplefilter('ignore', ResourceWarning)
58+
except NameError: # Python 2 has no ResourceWarning
59+
pass
60+
61+
try:
62+
secrets = boto3.client('secretsmanager')
63+
response = secrets.get_secret_value(SecretId='unit-test/endpoint')
64+
endpoint = response['SecretString']
65+
response = secrets.get_secret_value(SecretId='unit-test/certificate')
66+
cert = response['SecretString'].encode('utf8')
67+
response = secrets.get_secret_value(SecretId='unit-test/privatekey')
68+
key = response['SecretString'].encode('utf8')
69+
region = secrets.meta.region_name
70+
Config.cache = Config(endpoint, cert, key, region)
71+
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as ex:
72+
raise unittest.SkipTest("No credentials")
73+
74+
return Config.cache
75+
76+
77+
def create_client_id():
78+
return 'aws-crt-python-unit-test-{0}'.format(uuid.uuid4())
79+
80+
81+
class SamplesTest(unittest.TestCase):
82+
83+
def _run(self, args, stdout_checker):
84+
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
85+
stdout, stderr = process.communicate()
86+
stdout = stdout.decode()
87+
try:
88+
self.assertEqual(0, process.returncode)
89+
stdout_checker(stdout)
90+
except Exception as e:
91+
# print output and rethrow exception
92+
print(subprocess.list2cmdline(args))
93+
print("--- stdout ---")
94+
for line in stdout.splitlines():
95+
print(line)
96+
print("--- stderr ---")
97+
for line in stderr.splitlines():
98+
print(line)
99+
print("--- end ---")
100+
101+
raise e
102+
103+
def test_pubsub(self):
104+
config = Config.get()
105+
args = [
106+
sys.executable,
107+
"samples/pubsub.py",
108+
"--endpoint", config.endpoint,
109+
"--cert", config.cert_filepath,
110+
"--key", config.key_filepath,
111+
"--client-id", create_client_id(),
112+
"--count", "1",
113+
#"--verbosity", "Trace",
114+
]
115+
116+
def stdout_checker(stdout):
117+
# check for last line printed by sample
118+
last_line = stdout.splitlines()[-1]
119+
self.assertTrue(last_line.startswith("Disconnected!"))
120+
121+
self._run(args, stdout_checker)
122+
123+
def test_basic_discovery_response_only(self):
124+
config = Config.get()
125+
args = [
126+
sys.executable,
127+
"samples/basic_discovery.py",
128+
"--print-discover-resp-only",
129+
"--region", config.region,
130+
"--cert", config.cert_filepath,
131+
"--key", config.key_filepath,
132+
"--thing-name", "aws-sdk-crt-unit-test",
133+
"-v", "Trace",
134+
]
135+
136+
def stdout_checker(stdout):
137+
# check for last line printed by sample
138+
last_line = stdout.splitlines()[-1]
139+
self.assertTrue(last_line.startswith("awsiot.greengrass_discovery.DiscoverResponse("))
140+
141+
self._run(args, stdout_checker)

0 commit comments

Comments
 (0)