Skip to content

Commit 0234dde

Browse files
committed
Merge pull request #809 from docker/reorganize_tests
Reorganize tests
2 parents 5a1c7ed + 93a296f commit 0234dde

28 files changed

+3749
-3731
lines changed

Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,21 @@ build-dind-certs:
1717
test: flake8 unit-test unit-test-py3 integration-dind integration-dind-ssl
1818

1919
unit-test: build
20-
docker run docker-py py.test tests/test.py tests/utils_test.py
20+
docker run docker-py py.test tests/unit
2121

2222
unit-test-py3: build-py3
23-
docker run docker-py3 py.test tests/test.py tests/utils_test.py
23+
docker run docker-py3 py.test tests/unit
2424

2525
integration-test: build
26-
docker run -v /var/run/docker.sock:/var/run/docker.sock docker-py py.test tests/integration_test.py
26+
docker run -v /var/run/docker.sock:/var/run/docker.sock docker-py py.test tests/integration
2727

2828
integration-test-py3: build-py3
29-
docker run -v /var/run/docker.sock:/var/run/docker.sock docker-py3 py.test tests/integration_test.py
29+
docker run -v /var/run/docker.sock:/var/run/docker.sock docker-py3 py.test tests/integration
3030

3131
integration-dind: build build-py3
3232
docker run -d --name dpy-dind --env="DOCKER_HOST=tcp://localhost:2375" --privileged dockerswarm/dind:1.8.1 docker -d -H tcp://0.0.0.0:2375
33-
docker run --volumes-from dpy-dind --env="DOCKER_HOST=tcp://docker:2375" --link=dpy-dind:docker docker-py py.test tests/integration_test.py
34-
docker run --volumes-from dpy-dind --env="DOCKER_HOST=tcp://docker:2375" --link=dpy-dind:docker docker-py3 py.test tests/integration_test.py
33+
docker run --env="DOCKER_HOST=tcp://docker:2375" --link=dpy-dind:docker docker-py py.test tests/integration
34+
docker run --env="DOCKER_HOST=tcp://docker:2375" --link=dpy-dind:docker docker-py3 py.test tests/integration
3535
docker rm -vf dpy-dind
3636

3737
integration-dind-ssl: build-dind-certs build build-py3

tests/base.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,28 @@ def requires_api_version(version):
2121
),
2222
reason="API version is too low (< {0})".format(version)
2323
)
24+
25+
26+
class Cleanup(object):
27+
if sys.version_info < (2, 7):
28+
# Provide a basic implementation of addCleanup for Python < 2.7
29+
def __init__(self, *args, **kwargs):
30+
super(Cleanup, self).__init__(*args, **kwargs)
31+
self._cleanups = []
32+
33+
def tearDown(self):
34+
super(Cleanup, self).tearDown()
35+
ok = True
36+
while self._cleanups:
37+
fn, args, kwargs = self._cleanups.pop(-1)
38+
try:
39+
fn(*args, **kwargs)
40+
except KeyboardInterrupt:
41+
raise
42+
except:
43+
ok = False
44+
if not ok:
45+
raise
46+
47+
def addCleanup(self, function, *args, **kwargs):
48+
self._cleanups.append((function, args, kwargs))

tests/integration/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# flake8: noqa
2+
3+
# FIXME: crutch while we transition to the new folder architecture
4+
# Remove imports when merged in master and Jenkins is updated to find the
5+
# tests in the new location.
6+
from .api_test import *
7+
from .build_test import *
8+
from .container_test import *
9+
from .exec_test import *
10+
from .image_test import *
11+
from .network_test import *
12+
from .regression_test import *
13+
from .volume_test import *

tests/integration/api_test.py

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
import base64
2+
import json
3+
import os
4+
import shutil
5+
import tempfile
6+
import time
7+
import unittest
8+
import warnings
9+
10+
import docker
11+
import six
12+
13+
BUSYBOX = 'busybox:buildroot-2014.02'
14+
EXEC_DRIVER = []
15+
16+
17+
def exec_driver_is_native():
18+
global EXEC_DRIVER
19+
if not EXEC_DRIVER:
20+
c = docker_client()
21+
EXEC_DRIVER = c.info()['ExecutionDriver']
22+
c.close()
23+
return EXEC_DRIVER.startswith('native')
24+
25+
26+
def docker_client(**kwargs):
27+
return docker.Client(**docker_client_kwargs(**kwargs))
28+
29+
30+
def docker_client_kwargs(**kwargs):
31+
client_kwargs = docker.utils.kwargs_from_env(assert_hostname=False)
32+
client_kwargs.update(kwargs)
33+
return client_kwargs
34+
35+
36+
def setup_module():
37+
warnings.simplefilter('error')
38+
c = docker_client()
39+
try:
40+
c.inspect_image(BUSYBOX)
41+
except docker.errors.NotFound:
42+
os.write(2, "\npulling busybox\n".encode('utf-8'))
43+
for data in c.pull(BUSYBOX, stream=True):
44+
data = json.loads(data.decode('utf-8'))
45+
os.write(2, ("%c[2K\r" % 27).encode('utf-8'))
46+
status = data.get("status")
47+
progress = data.get("progress")
48+
detail = "{0} - {1}".format(status, progress).encode('utf-8')
49+
os.write(2, detail)
50+
os.write(2, "\npulled busybox\n".encode('utf-8'))
51+
52+
# Double make sure we now have busybox
53+
c.inspect_image(BUSYBOX)
54+
c.close()
55+
56+
57+
class BaseTestCase(unittest.TestCase):
58+
tmp_imgs = []
59+
tmp_containers = []
60+
tmp_folders = []
61+
tmp_volumes = []
62+
63+
def setUp(self):
64+
if six.PY2:
65+
self.assertRegex = self.assertRegexpMatches
66+
self.assertCountEqual = self.assertItemsEqual
67+
self.client = docker_client(timeout=60)
68+
self.tmp_imgs = []
69+
self.tmp_containers = []
70+
self.tmp_folders = []
71+
self.tmp_volumes = []
72+
self.tmp_networks = []
73+
74+
def tearDown(self):
75+
for img in self.tmp_imgs:
76+
try:
77+
self.client.remove_image(img)
78+
except docker.errors.APIError:
79+
pass
80+
for container in self.tmp_containers:
81+
try:
82+
self.client.stop(container, timeout=1)
83+
self.client.remove_container(container)
84+
except docker.errors.APIError:
85+
pass
86+
for network in self.tmp_networks:
87+
try:
88+
self.client.remove_network(network)
89+
except docker.errors.APIError:
90+
pass
91+
for folder in self.tmp_folders:
92+
shutil.rmtree(folder)
93+
94+
for volume in self.tmp_volumes:
95+
try:
96+
self.client.remove_volume(volume)
97+
except docker.errors.APIError:
98+
pass
99+
100+
self.client.close()
101+
102+
def run_container(self, *args, **kwargs):
103+
container = self.client.create_container(*args, **kwargs)
104+
self.tmp_containers.append(container)
105+
self.client.start(container)
106+
exitcode = self.client.wait(container)
107+
108+
if exitcode != 0:
109+
output = self.client.logs(container)
110+
raise Exception(
111+
"Container exited with code {}:\n{}"
112+
.format(exitcode, output))
113+
114+
return container
115+
116+
117+
#########################
118+
# INFORMATION TESTS #
119+
#########################
120+
121+
122+
class InformationTest(BaseTestCase):
123+
def test_version(self):
124+
res = self.client.version()
125+
self.assertIn('GoVersion', res)
126+
self.assertIn('Version', res)
127+
self.assertEqual(len(res['Version'].split('.')), 3)
128+
129+
def test_info(self):
130+
res = self.client.info()
131+
self.assertIn('Containers', res)
132+
self.assertIn('Images', res)
133+
self.assertIn('Debug', res)
134+
135+
def test_search(self):
136+
self.client = docker_client(timeout=10)
137+
res = self.client.search('busybox')
138+
self.assertTrue(len(res) >= 1)
139+
base_img = [x for x in res if x['name'] == 'busybox']
140+
self.assertEqual(len(base_img), 1)
141+
self.assertIn('description', base_img[0])
142+
143+
144+
#################
145+
# LINKS TESTS #
146+
#################
147+
148+
149+
class LinkTest(BaseTestCase):
150+
def test_remove_link(self):
151+
# Create containers
152+
container1 = self.client.create_container(
153+
BUSYBOX, 'cat', detach=True, stdin_open=True
154+
)
155+
container1_id = container1['Id']
156+
self.tmp_containers.append(container1_id)
157+
self.client.start(container1_id)
158+
159+
# Create Link
160+
# we don't want the first /
161+
link_path = self.client.inspect_container(container1_id)['Name'][1:]
162+
link_alias = 'mylink'
163+
164+
container2 = self.client.create_container(
165+
BUSYBOX, 'cat', host_config=self.client.create_host_config(
166+
links={link_path: link_alias}, network_mode='none'
167+
)
168+
)
169+
container2_id = container2['Id']
170+
self.tmp_containers.append(container2_id)
171+
self.client.start(container2_id)
172+
173+
# Remove link
174+
linked_name = self.client.inspect_container(container2_id)['Name'][1:]
175+
link_name = '%s/%s' % (linked_name, link_alias)
176+
self.client.remove_container(link_name, link=True)
177+
178+
# Link is gone
179+
containers = self.client.containers(all=True)
180+
retrieved = [x for x in containers if link_name in x['Names']]
181+
self.assertEqual(len(retrieved), 0)
182+
183+
# Containers are still there
184+
retrieved = [
185+
x for x in containers if x['Id'].startswith(container1_id) or
186+
x['Id'].startswith(container2_id)
187+
]
188+
self.assertEqual(len(retrieved), 2)
189+
190+
191+
#######################
192+
# PY SPECIFIC TESTS #
193+
#######################
194+
195+
class LoadConfigTest(BaseTestCase):
196+
def test_load_legacy_config(self):
197+
folder = tempfile.mkdtemp()
198+
self.tmp_folders.append(folder)
199+
cfg_path = os.path.join(folder, '.dockercfg')
200+
f = open(cfg_path, 'w')
201+
auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
202+
f.write('auth = {0}\n'.format(auth_))
203+
f.write('email = [email protected]')
204+
f.close()
205+
cfg = docker.auth.load_config(cfg_path)
206+
self.assertNotEqual(cfg[docker.auth.INDEX_NAME], None)
207+
cfg = cfg[docker.auth.INDEX_NAME]
208+
self.assertEqual(cfg['username'], 'sakuya')
209+
self.assertEqual(cfg['password'], 'izayoi')
210+
self.assertEqual(cfg['email'], '[email protected]')
211+
self.assertEqual(cfg.get('Auth'), None)
212+
213+
def test_load_json_config(self):
214+
folder = tempfile.mkdtemp()
215+
self.tmp_folders.append(folder)
216+
cfg_path = os.path.join(folder, '.dockercfg')
217+
f = open(os.path.join(folder, '.dockercfg'), 'w')
218+
auth_ = base64.b64encode(b'sakuya:izayoi').decode('ascii')
219+
email_ = '[email protected]'
220+
f.write('{{"{0}": {{"auth": "{1}", "email": "{2}"}}}}\n'.format(
221+
docker.auth.INDEX_URL, auth_, email_))
222+
f.close()
223+
cfg = docker.auth.load_config(cfg_path)
224+
self.assertNotEqual(cfg[docker.auth.INDEX_URL], None)
225+
cfg = cfg[docker.auth.INDEX_URL]
226+
self.assertEqual(cfg['username'], 'sakuya')
227+
self.assertEqual(cfg['password'], 'izayoi')
228+
self.assertEqual(cfg['email'], '[email protected]')
229+
self.assertEqual(cfg.get('Auth'), None)
230+
231+
232+
class AutoDetectVersionTest(unittest.TestCase):
233+
def test_client_init(self):
234+
client = docker_client(version='auto')
235+
client_version = client._version
236+
api_version = client.version(api_version=False)['ApiVersion']
237+
self.assertEqual(client_version, api_version)
238+
api_version_2 = client.version()['ApiVersion']
239+
self.assertEqual(client_version, api_version_2)
240+
client.close()
241+
242+
def test_auto_client(self):
243+
client = docker.AutoVersionClient(**docker_client_kwargs())
244+
client_version = client._version
245+
api_version = client.version(api_version=False)['ApiVersion']
246+
self.assertEqual(client_version, api_version)
247+
api_version_2 = client.version()['ApiVersion']
248+
self.assertEqual(client_version, api_version_2)
249+
client.close()
250+
with self.assertRaises(docker.errors.DockerException):
251+
docker.AutoVersionClient(**docker_client_kwargs(version='1.11'))
252+
253+
254+
class ConnectionTimeoutTest(unittest.TestCase):
255+
def setUp(self):
256+
self.timeout = 0.5
257+
self.client = docker.client.Client(base_url='http://192.168.10.2:4243',
258+
timeout=self.timeout)
259+
260+
def test_timeout(self):
261+
start = time.time()
262+
res = None
263+
# This call isn't supposed to complete, and it should fail fast.
264+
try:
265+
res = self.client.inspect_container('id')
266+
except:
267+
pass
268+
end = time.time()
269+
self.assertTrue(res is None)
270+
self.assertTrue(end - start < 2 * self.timeout)
271+
272+
273+
class UnixconnTest(unittest.TestCase):
274+
"""
275+
Test UNIX socket connection adapter.
276+
"""
277+
278+
def test_resource_warnings(self):
279+
"""
280+
Test no warnings are produced when using the client.
281+
"""
282+
283+
with warnings.catch_warnings(record=True) as w:
284+
warnings.simplefilter('always')
285+
286+
client = docker_client()
287+
client.images()
288+
client.close()
289+
del client
290+
291+
assert len(w) == 0, \
292+
"No warnings produced: {0}".format(w[0].message)

0 commit comments

Comments
 (0)