Skip to content

Commit 207c8cf

Browse files
author
Dean Troyer
committed
Test top-to-bottom: object-store containers
Replicate the object-store container command tests but use requests_mock to test the entire stack down to the requests module. These will be useful regressions tests when the existing object-store lib modules are moved to the low-level API object. Change-Id: Ibf25be46156eb1009f1b66f02f2073d3913b846d
1 parent 02320a5 commit 207c8cf

4 files changed

Lines changed: 353 additions & 8 deletions

File tree

openstackclient/tests/fakes.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,18 @@ def __init__(self, _stdout):
4747
self.stderr = sys.stderr
4848

4949

50+
class FakeClient(object):
51+
def __init__(self, **kwargs):
52+
self.endpoint = kwargs['endpoint']
53+
self.token = kwargs['token']
54+
55+
5056
class FakeClientManager(object):
5157
def __init__(self):
5258
self.compute = None
5359
self.identity = None
5460
self.image = None
55-
self.object = None
61+
self.object_store = None
5662
self.volume = None
5763
self.network = None
5864
self.session = None

openstackclient/tests/object/v1/fakes.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
from openstackclient.tests import utils
1818

1919

20+
ACCOUNT_ID = 'tqbfjotld'
21+
ENDPOINT = 'https://0.0.0.0:6482/v1/' + ACCOUNT_ID
22+
2023
container_name = 'bit-bucket'
2124
container_bytes = 1024
2225
container_count = 1
@@ -71,17 +74,11 @@
7174
}
7275

7376

74-
class FakeObjectv1Client(object):
75-
def __init__(self, **kwargs):
76-
self.endpoint = kwargs['endpoint']
77-
self.token = kwargs['token']
78-
79-
8077
class TestObjectv1(utils.TestCommand):
8178
def setUp(self):
8279
super(TestObjectv1, self).setUp()
8380

84-
self.app.client_manager.object_store = FakeObjectv1Client(
81+
self.app.client_manager.object_store = fakes.FakeClient(
8582
endpoint=fakes.AUTH_URL,
8683
token=fakes.AUTH_TOKEN,
8784
)
Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
import copy
15+
16+
from requests_mock.contrib import fixture
17+
18+
from keystoneclient import session
19+
from openstackclient.object.v1 import container
20+
from openstackclient.tests.object.v1 import fakes as object_fakes
21+
22+
23+
class TestObjectAll(object_fakes.TestObjectv1):
24+
25+
def setUp(self):
26+
super(TestObjectAll, self).setUp()
27+
28+
self.app.client_manager.session = session.Session()
29+
self.requests_mock = self.useFixture(fixture.Fixture())
30+
31+
# TODO(dtroyer): move this to object_fakes.TestObjectv1
32+
self.app.client_manager.object_store.endpoint = object_fakes.ENDPOINT
33+
34+
35+
class TestContainerCreate(TestObjectAll):
36+
37+
def setUp(self):
38+
super(TestContainerCreate, self).setUp()
39+
40+
# Get the command object to test
41+
self.cmd = container.CreateContainer(self.app, None)
42+
43+
def test_object_create_container_single(self):
44+
self.requests_mock.register_uri(
45+
'PUT',
46+
object_fakes.ENDPOINT + '/ernie',
47+
headers={'x-trans-id': '314159'},
48+
status_code=200,
49+
)
50+
51+
arglist = [
52+
'ernie',
53+
]
54+
verifylist = [(
55+
'containers', ['ernie'],
56+
)]
57+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
58+
59+
# DisplayCommandBase.take_action() returns two tuples
60+
columns, data = self.cmd.take_action(parsed_args)
61+
62+
collist = ('account', 'container', 'x-trans-id')
63+
self.assertEqual(collist, columns)
64+
datalist = [(
65+
object_fakes.ACCOUNT_ID,
66+
'ernie',
67+
'314159',
68+
)]
69+
self.assertEqual(datalist, list(data))
70+
71+
def test_object_create_container_more(self):
72+
self.requests_mock.register_uri(
73+
'PUT',
74+
object_fakes.ENDPOINT + '/ernie',
75+
headers={'x-trans-id': '314159'},
76+
status_code=200,
77+
)
78+
self.requests_mock.register_uri(
79+
'PUT',
80+
object_fakes.ENDPOINT + '/bert',
81+
headers={'x-trans-id': '42'},
82+
status_code=200,
83+
)
84+
85+
arglist = [
86+
'ernie',
87+
'bert',
88+
]
89+
verifylist = [(
90+
'containers', ['ernie', 'bert'],
91+
)]
92+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
93+
94+
# DisplayCommandBase.take_action() returns two tuples
95+
columns, data = self.cmd.take_action(parsed_args)
96+
97+
collist = ('account', 'container', 'x-trans-id')
98+
self.assertEqual(collist, columns)
99+
datalist = [
100+
(
101+
object_fakes.ACCOUNT_ID,
102+
'ernie',
103+
'314159',
104+
),
105+
(
106+
object_fakes.ACCOUNT_ID,
107+
'bert',
108+
'42',
109+
),
110+
]
111+
self.assertEqual(datalist, list(data))
112+
113+
114+
class TestContainerDelete(TestObjectAll):
115+
116+
def setUp(self):
117+
super(TestContainerDelete, self).setUp()
118+
119+
# Get the command object to test
120+
self.cmd = container.DeleteContainer(self.app, None)
121+
122+
def test_object_delete_container_single(self):
123+
self.requests_mock.register_uri(
124+
'DELETE',
125+
object_fakes.ENDPOINT + '/ernie',
126+
status_code=200,
127+
)
128+
129+
arglist = [
130+
'ernie',
131+
]
132+
verifylist = [(
133+
'containers', ['ernie'],
134+
)]
135+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
136+
137+
# Command.take_action() returns None
138+
ret = self.cmd.take_action(parsed_args)
139+
self.assertIsNone(ret)
140+
141+
def test_object_delete_container_more(self):
142+
self.requests_mock.register_uri(
143+
'DELETE',
144+
object_fakes.ENDPOINT + '/ernie',
145+
status_code=200,
146+
)
147+
self.requests_mock.register_uri(
148+
'DELETE',
149+
object_fakes.ENDPOINT + '/bert',
150+
status_code=200,
151+
)
152+
153+
arglist = [
154+
'ernie',
155+
'bert',
156+
]
157+
verifylist = [(
158+
'containers', ['ernie', 'bert'],
159+
)]
160+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
161+
162+
# Command.take_action() returns None
163+
ret = self.cmd.take_action(parsed_args)
164+
self.assertIsNone(ret)
165+
166+
167+
class TestContainerList(TestObjectAll):
168+
169+
def setUp(self):
170+
super(TestContainerList, self).setUp()
171+
172+
# Get the command object to test
173+
self.cmd = container.ListContainer(self.app, None)
174+
175+
def test_object_list_containers_no_options(self):
176+
return_body = [
177+
copy.deepcopy(object_fakes.CONTAINER),
178+
copy.deepcopy(object_fakes.CONTAINER_3),
179+
copy.deepcopy(object_fakes.CONTAINER_2),
180+
]
181+
self.requests_mock.register_uri(
182+
'GET',
183+
object_fakes.ENDPOINT + '?format=json',
184+
json=return_body,
185+
status_code=200,
186+
)
187+
188+
arglist = []
189+
verifylist = []
190+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
191+
192+
# Lister.take_action() returns two tuples
193+
columns, data = self.cmd.take_action(parsed_args)
194+
195+
collist = ('Name',)
196+
self.assertEqual(collist, columns)
197+
datalist = [
198+
(object_fakes.container_name, ),
199+
(object_fakes.container_name_3, ),
200+
(object_fakes.container_name_2, ),
201+
]
202+
self.assertEqual(datalist, list(data))
203+
204+
def test_object_list_containers_prefix(self):
205+
return_body = [
206+
copy.deepcopy(object_fakes.CONTAINER),
207+
copy.deepcopy(object_fakes.CONTAINER_3),
208+
]
209+
self.requests_mock.register_uri(
210+
'GET',
211+
object_fakes.ENDPOINT + '?format=json&prefix=bit',
212+
json=return_body,
213+
status_code=200,
214+
)
215+
216+
arglist = [
217+
'--prefix', 'bit',
218+
]
219+
verifylist = [
220+
('prefix', 'bit'),
221+
]
222+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
223+
224+
# Lister.take_action() returns two tuples
225+
columns, data = self.cmd.take_action(parsed_args)
226+
227+
collist = ('Name',)
228+
self.assertEqual(collist, columns)
229+
datalist = [
230+
(object_fakes.container_name, ),
231+
(object_fakes.container_name_3, ),
232+
]
233+
self.assertEqual(datalist, list(data))
234+
235+
236+
class TestContainerSave(TestObjectAll):
237+
238+
def setUp(self):
239+
super(TestContainerSave, self).setUp()
240+
241+
# Get the command object to test
242+
self.cmd = container.SaveContainer(self.app, None)
243+
244+
# TODO(dtroyer): need to mock out object_lib.save_object() to test this
245+
# def test_object_save_container(self):
246+
# return_body = [
247+
# copy.deepcopy(object_fakes.OBJECT),
248+
# copy.deepcopy(object_fakes.OBJECT_2),
249+
# ]
250+
# # Initial container list request
251+
# self.requests_mock.register_uri(
252+
# 'GET',
253+
# object_fakes.ENDPOINT + '/oscar?format=json',
254+
# json=return_body,
255+
# status_code=200,
256+
# )
257+
# # Individual object save requests
258+
# self.requests_mock.register_uri(
259+
# 'GET',
260+
# object_fakes.ENDPOINT + '/oscar/' + object_fakes.object_name_1,
261+
# json=object_fakes.OBJECT,
262+
# status_code=200,
263+
# )
264+
# self.requests_mock.register_uri(
265+
# 'GET',
266+
# object_fakes.ENDPOINT + '/oscar/' + object_fakes.object_name_2,
267+
# json=object_fakes.OBJECT_2,
268+
# status_code=200,
269+
# )
270+
#
271+
# arglist = [
272+
# 'oscar',
273+
# ]
274+
# verifylist = [(
275+
# 'container', 'oscar',
276+
# )]
277+
# parsed_args = self.check_parser(self.cmd, arglist, verifylist)
278+
#
279+
# # Command.take_action() returns None
280+
# ret = self.cmd.take_action(parsed_args)
281+
# self.assertIsNone(ret)
282+
283+
284+
class TestContainerShow(TestObjectAll):
285+
286+
def setUp(self):
287+
super(TestContainerShow, self).setUp()
288+
289+
# Get the command object to test
290+
self.cmd = container.ShowContainer(self.app, None)
291+
292+
def test_object_show_container(self):
293+
headers = {
294+
'x-container-meta-owner': object_fakes.ACCOUNT_ID,
295+
'x-container-object-count': '42',
296+
'x-container-bytes-used': '123',
297+
'x-container-read': 'qaz',
298+
'x-container-write': 'wsx',
299+
'x-container-sync-to': 'edc',
300+
'x-container-sync-key': 'rfv',
301+
}
302+
self.requests_mock.register_uri(
303+
'HEAD',
304+
object_fakes.ENDPOINT + '/ernie',
305+
headers=headers,
306+
status_code=200,
307+
)
308+
309+
arglist = [
310+
'ernie',
311+
]
312+
verifylist = [(
313+
'container', 'ernie',
314+
)]
315+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
316+
317+
# DisplayCommandBase.take_action() returns two tuples
318+
columns, data = self.cmd.take_action(parsed_args)
319+
320+
collist = (
321+
'account',
322+
'bytes_used',
323+
'container',
324+
'object_count',
325+
'read_acl',
326+
'sync_key',
327+
'sync_to',
328+
'write_acl',
329+
)
330+
self.assertEqual(collist, columns)
331+
datalist = [
332+
object_fakes.ACCOUNT_ID,
333+
'123',
334+
'ernie',
335+
'42',
336+
'qaz',
337+
'rfv',
338+
'edc',
339+
'wsx',
340+
]
341+
self.assertEqual(datalist, list(data))

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ discover
88
fixtures>=0.3.14
99
mock>=1.0
1010
oslosphinx>=2.2.0 # Apache-2.0
11+
requests-mock>=0.4.0 # Apache-2.0
1112
sphinx>=1.1.2,!=1.2.0,<1.3
1213
testrepository>=0.0.18
1314
testtools>=0.9.34

0 commit comments

Comments
 (0)