Projet

Général

Profil

0001-cook-add-unit-tests-for-cook.py-32886.patch

Nicolas Roche, 10 mai 2019 18:59

Télécharger (15,3 ko)

Voir les différences:

Subject: [PATCH 1/3] cook: add unit tests for cook.py (#32886)

 tests/test_cook.py | 377 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 369 insertions(+), 8 deletions(-)
tests/test_cook.py
1 1
import pytest
2
import mock
2
import json
3 3
import StringIO
4
from mock import call, mock_open, patch, Mock
4 5

  
6
from django.contrib.auth.models import User
7
from django.contrib.contenttypes.models import ContentType
5 8
from django.core.management.base import CommandError
6 9

  
7
from hobo.environment.models import ServiceBase
10
from hobo.environment.models import (Authentic, BiJoe, Chrono, Combo, Corbo, Fargo,
11
    Hobo, Passerelle, ServiceBase, Variable, Wcs, Welco)
8 12
from hobo.environment.management.commands.cook import Command
13
from hobo.profile.models import AttributeDefinition
9 14

  
10 15

  
11 16
def test_check_action(monkeypatch):
......
55 60
        command.check_action(action, action_args)
56 61
    assert 'has no valid certificate' in str(e_info.value)
57 62

  
58
@mock.patch('hobo.environment.management.commands.cook.open')
63
def test_handle():
64
    kwargs = {'verbosity': 'verbosity value',
65
              'timeout': 'timeout value',
66
              'permissive': 'permissive value'}
67
    command = Command()
68
    command.run_cook = Mock()
69

  
70
    command.handle('recipe_me.json', **kwargs)
71
    assert command.verbosity == 'verbosity value'
72
    assert command.timeout == 'timeout value'
73
    assert command.permissive == 'permissive value'
74
    assert command.run_cook.mock_calls == [call('recipe_me.json')]
75

  
76
@patch('hobo.environment.management.commands.cook.open')
77
@patch('hobo.environment.management.commands.cook.notify_agents')
78
def test_run_cook(mocked_notify_agents, mocked_open):
79
    receipe = """{
80
  "steps": [
81
    {"create-hobo": {
82
      "url": "https://entrouvert.org/"
83
    }}
84
  ]
85
}"""
86
    command = Command()
87
    command.permissive = False
88
    command.must_notify = True
89
    command.timeout = 42
90
    command.check_action = Mock()
91
    command.create_hobo = Mock()
92
    mocked_notify_agents = Mock()
93
    command.wait_operationals = Mock()
94

  
95
    mocked_open.side_effect = [StringIO.StringIO(receipe)]
96
    command.run_cook('recipe_me.json')
97
    assert command.check_action.mock_calls == [
98
        call(u'create-hobo', {u'url': u'https://entrouvert.org/'})]
99
    assert command.create_hobo.mock_calls == [call(url=u'https://entrouvert.org/')]
100
    assert mocked_notify_agents.mock_calls == []
101
    assert command.wait_operationals.mock_calls == [call(timeout=42)]
102

  
103
@patch('hobo.environment.management.commands.cook.open')
59 104
def test_having_several_action_args(mocked_open):
60
    """load variables from a file"""
61 105
    receipe = """{
62 106
  "steps": [
63 107
    {"create-authentic": {
......
66 110
    }}
67 111
  ]
68 112
}"""
69
    expected_a2 = "[call(title=u'Connexion', url=u'https://entrouvert.org/')]"
70

  
71 113
    command = Command()
72 114
    command.permissive = True
73
    command.create_authentic = mock.MagicMock()
115
    command.create_authentic = Mock()
74 116

  
75 117
    mocked_open.side_effect = [StringIO.StringIO(receipe)]
76 118
    command.run_cook('recipe_me.json')
77
    assert str(command.create_authentic.mock_calls) == expected_a2
119
    assert command.create_authentic.mock_calls == [
120
        call(title=u'Connexion', url=u'https://entrouvert.org/')]
121

  
122
@patch('hobo.environment.management.commands.cook.open')
123
def test_load_variables_from(mocked_open):
124
    """load variables from a file"""
125
    receipe = """{
126
  "load-variables-from": "variables.json",
127
  "variables": {
128
    "domain": "entrouvert.org",
129
    "bar": "bar2"
130
  },
131
  "steps": [
132
    {"create-hobo": {
133
      "url": "https://${domain}/"
134
    }},
135
    {"create-authentic": {
136
      "url": "https://${foo}/"
137
    }},
138
    {"create-combo": {
139
      "url": "https://${bar}/",
140
      "not_a_string": []
141
    }}
142
  ]
143
}"""
144
    variables = """{
145
  "foo": "foo1",
146
  "bar": "bar1"
147
}"""
148
    command = Command()
149
    command.permissive = True
150
    command.create_hobo = Mock()
151
    command.create_authentic = Mock()
152
    command.create_combo = Mock()
153

  
154
    mocked_open.side_effect = [StringIO.StringIO(receipe),
155
                               StringIO.StringIO(variables)]
156
    command.run_cook('recipe_me.json')
157
    assert command.create_hobo.mock_calls == [call(url=u'https://entrouvert.org/')]
158
    assert command.create_authentic.mock_calls == [call(url=u'https://foo1/')]
159
    assert command.create_combo.mock_calls == [
160
        call(not_a_string=[], url=u'https://bar2/')]
161

  
162
def test_wait_operationals(db, monkeypatch):
163
    service1 = Mock()
164
    service2 = Mock()
165
    obj1 = Mock()
166
    obj2 = Mock()
167

  
168
    def do_nothing(*args, **kwargs):
169
        pass
170

  
171
    obj1.check_operational = do_nothing
172
    obj2.check_operational = do_nothing
173
    obj1.base_url = 'url1'
174
    obj2.base_url = 'url2'
175

  
176
    service1.objects.all = Mock(return_value=[obj1])
177
    service2.objects.all = Mock(return_value=[obj2])
178
    monkeypatch.setattr(
179
        'hobo.environment.management.commands.cook.AVAILABLE_SERVICES',
180
        [service1, service2])
181
    command = Command()
182

  
183
    # already operational
184
    obj1.last_operational_success_timestamp = 'some date'
185
    obj2.last_operational_success_timestamp = 'some date'
186
    command.wait_operationals(2)
187
    assert True
188

  
189
    # not operational
190
    obj2.last_operational_success_timestamp = None
191
    with pytest.raises(CommandError) as e_info:
192
        command.wait_operationals(.6)
193
    assert str(e_info).find('CommandError: timeout waiting for url2') != -1
194

  
195
def test_set_variable(db):
196
    command = Command()
197

  
198
    command.set_variable('foo', 'bar')
199
    value = Variable.objects.get(name='foo').value
200
    label = Variable.objects.get(name='foo').label
201
    assert value == 'bar'
202
    assert label == 'foo'
203

  
204
    command.set_variable('foo', 'bar', label='FOO')
205
    value = Variable.objects.get(name='foo').value
206
    label = Variable.objects.get(name='foo').label
207
    assert value == 'bar'
208
    assert label == 'FOO'
209

  
210
    command.set_variable('foo', ['bar', 'baz'])
211
    value = Variable.objects.get(name='foo').value
212
    assert value == '["bar", "baz"]'
213

  
214
    command.set_variable('foo', {'key1': 'bar', 'key2': 'baz'})
215
    value = Variable.objects.get(name='foo').value
216
    ordered_dump = json.dumps(json.loads(value), sort_keys=True)
217
    assert  ordered_dump == '{"key1": "bar", "key2": "baz"}'
218

  
219
def test_set_attribute(db):
220
    command = Command()
221
    command.set_attribute('foo_name', 'foo_label')
222
    values = AttributeDefinition.objects.filter(name='foo_name')
223
    assert values.count() == 1
224
    assert values[0].label == 'foo_label'
225
    assert values[0].disabled is False
226

  
227
    command.set_attribute('foo_name', 'foo_label', disabled=True)
228
    values = AttributeDefinition.objects.filter(name='foo_name')
229
    assert values.count() == 1
230
    assert values[0].label == 'foo_label'
231
    assert values[0].disabled is True
232

  
233
def test_disable_attribute(db):
234
    command = Command()
235
    command.set_attribute('foo_name', 'foo_label')
236
    values = AttributeDefinition.objects.filter(name='foo_name')
237
    assert values.count() == 1
238
    assert values[0].label == 'foo_label'
239
    assert values[0].disabled is False
240

  
241
    command.disable_attribute('foo_name')
242
    values = AttributeDefinition.objects.filter(name='foo_name')
243
    assert values[0].disabled is True
244

  
245
    command.disable_attribute('not_defined')
246
    values = AttributeDefinition.objects.filter(name='not_defined')
247
    assert values.count() == 0
248

  
249
def test_enable_attribute(db):
250
    command = Command()
251
    command.set_attribute('foo_name', 'foo_label', disabled=True)
252
    values = AttributeDefinition.objects.filter(name='foo_name')
253
    assert values.count() == 1
254
    assert values[0].label == 'foo_label'
255
    assert values[0].disabled is True
256

  
257
    command.enable_attribute('foo_name')
258
    values = AttributeDefinition.objects.filter(name='foo_name')
259
    assert values[0].disabled is False
260

  
261
    command.enable_attribute('not_defined')
262
    values = AttributeDefinition.objects.filter(name='not_defined')
263
    assert values.count() == 0
264

  
265
def test_create_superuser(db):
266
    command = Command()
267
    command.create_superuser()
268
    assert User.objects.count() == 1
269
    user = User.objects.all()[0]
270
    assert user.username == 'admin'
271
    assert user.is_superuser is True
272

  
273
def test_create_site(db):
274
    """
275
    code redondant ?
276
      service_type=obj_type,
277
      service_pk=obj.id,
278
    """
279
    command = Command()
280
    base_url = 'http://entrouvert.org'
281
    title = 'site title'
282
    slug = None
283
    template_name = ''
284
    variables = {'foo': {'label': 'FOO', 'value': {'key': 'bar'}}}
285
    command.create_site(Combo, base_url, title, slug, template_name,
286
                        variables)
287

  
288
    # Combo object
289
    assert Combo.objects.count() == 1
290
    combo = Combo.objects.all()[0]
291
    assert combo.title == title
292
    assert combo.base_url == base_url + '/'
293
    assert combo.template_name == ''
294

  
295
    # ContentType object
296
    obj_type = ContentType.objects.get_for_model(Combo)
297

  
298
    # Variables
299
    variable = Variable.objects.get(name='foo')
300
    assert variable.label == 'FOO'
301
    assert variable.value == '{"key": "bar"}'
302
    assert variable.service_type == obj_type
303
    assert variable.service_pk == combo.id
304

  
305
    with pytest.raises(CommandError) as e_info:
306
        command.create_site(Combo, 'unvalid_url', 'site title', 'a slug', '', '')
307
    assert 'Enter a valid URL.' in str(e_info.value)
308

  
309
@patch('hobo.environment.management.commands.cook.connection')
310
@patch('hobo.environment.management.commands.cook.call_command')
311
@patch('hobo.environment.management.commands.cook.TenantMiddleware')
312
def test_create_hobo_primary(mocked_TenantMiddleware, mocked_call_command,
313
                             mocked_connection):
314
    command = Command()
315
    command.create_site = Mock()
316
    tenant = Mock()
317
    tenant.schema_name = 'public'
318
    tenant.get_directory = Mock(return_value='/foo')
319
    mocked_connection.get_tenant = Mock(return_value=tenant)
320
    mocked_connection.set_tenant = Mock()
321
    mocked_TenantMiddleware.get_tenant_by_hostname = Mock(return_value=tenant)
322
    mocked_call_command.side_effect = CommandError
323

  
324
    mocked_open = mock_open()
325
    with patch('hobo.environment.management.commands.cook.open', mocked_open,
326
               create=True):
327
        command.create_hobo('http://entrouvert.org/and_much')
328
    assert command.create_site.mock_calls == []
329
    assert mocked_call_command.mock_calls == [
330
        call('create_hobo_tenant', 'entrouvert.org')]
331
    assert len(mocked_connection.set_tenant.mock_calls) == 1
332
    assert mocked_open.mock_calls == [
333
        call('/foo/base_url', 'w'),
334
        call().write('http://entrouvert.org/and_much'),
335
        call().close()]
336

  
337
@patch('hobo.environment.management.commands.cook.connection')
338
@patch('hobo.environment.management.commands.cook.call_command')
339
@patch('hobo.environment.management.commands.cook.TenantMiddleware')
340
def test_create_hobo_not_primary(mocked_TenantMiddleware, mocked_call_command,
341
                                 mocked_connection):
342
    command = Command()
343
    command.create_site = Mock()
344
    tenant = Mock()
345
    tenant.schema_name = 'other than public'
346
    tenant.get_directory = Mock(return_value='/foo')
347
    mocked_connection.get_tenant = Mock(return_value=tenant)
348
    mocked_connection.set_tenant = Mock()
349
    mocked_TenantMiddleware.get_tenant_by_hostname = Mock(return_value=tenant)
350

  
351
    mocked_open = mock_open()
352
    with patch('hobo.environment.management.commands.cook.open', mocked_open,
353
               create=True):
354
        command.create_hobo('http://entrouvert.org/and_much')
355
    assert command.create_site.mock_calls == [
356
        call(Hobo, 'http://entrouvert.org/and_much', None, u'hobo-none',
357
             template_name='', variables=None)]
358
    assert mocked_call_command.mock_calls == []
359
    assert len(mocked_connection.set_tenant.mock_calls) == 1
360
    assert mocked_open.mock_calls == []
361

  
362
def test_create_services():
363
    command = Command()
364
    command.create_site = Mock()
365
    command.create_authentic('url', 'title')
366
    command.create_combo('url', 'title')
367
    command.create_wcs('url', 'title')
368
    command.create_passerelle('url', 'title')
369
    command.create_fargo('url', 'title')
370
    command.create_welco('url', 'title')
371
    command.create_chrono('url', 'title')
372
    command.create_corbo('url', 'title')
373
    command.create_bijoe('url', 'title')
374

  
375
    assert len(command.create_site.mock_calls) == 9
376
    assert command.create_site.mock_calls == [
377
        call(Authentic, 'url', 'title', None, '', None),
378
        call(Combo, 'url', 'title', None, '', None),
379
        call(Wcs, 'url', 'title', None, '', None),
380
        call(Passerelle, 'url', 'title', None, '', None),
381
        call(Fargo, 'url', 'title', None, '', None),
382
        call(Welco, 'url', 'title', None, '', None),
383
        call(Chrono, 'url', 'title', None, '', None),
384
        call(Corbo, 'url', 'title', None, '', None),
385
        call(BiJoe, 'url', 'title', None, '', None)]
386

  
387
def test_set_idp(db):
388
    command = Command()
389

  
390
    # exceptions maybe we should handle into cook.py ?
391
    with pytest.raises(Authentic.DoesNotExist,
392
                       match='Authentic matching query does not exist'):
393
        command.set_idp('url')
394
    with pytest.raises(IndexError, match='list index out of range'):
395
        command.set_idp()
396

  
397
    # objects sorted on title: [obj1, obj2]
398
    obj1, ignored = Authentic.objects.get_or_create(
399
        slug='slug1', defaults={'title': 'bar'})
400
    obj2, ignored = Authentic.objects.get_or_create(
401
        slug='slug2', defaults={'title': 'foo', 'base_url': 'http://example.org'})
402
    assert obj1.use_as_idp_for_self is False
403
    assert obj2.use_as_idp_for_self is False
404

  
405
    # set first
406
    command.set_idp('')
407
    obj = Authentic.objects.get(title='bar')
408
    assert obj.use_as_idp_for_self is True
409

  
410
    # set using url
411
    command.set_idp('http://example.org/')
412
    obj = Authentic.objects.get(title='foo')
413
    assert obj.use_as_idp_for_self is True
414

  
415
@patch('hobo.environment.management.commands.cook.set_theme')
416
@patch('hobo.environment.management.commands.cook.connection')
417
@patch('hobo.agent.common.management.commands.hobo_deploy.Command.configure_theme')
418
def test_set_theme(mocked_configure_theme, mocked_connection, mocked_set_theme):
419
    mocked_connection.get_tenant = Mock(return_value='the tenant')
420
    command = Command()
421
    command.set_theme('the theme')
422

  
423
    assert mocked_set_theme.mock_calls == [call('the theme')]
424
    assert len(mocked_connection.get_tenant.mock_calls) == 1
425
    assert mocked_configure_theme.mock_calls == [
426
        call({'variables': {'theme': 'the theme'}}, 'the tenant')]
427

  
428
@patch('hobo.environment.management.commands.cook.connection')
429
def test_cook(mocked_connection):
430
    mocked_connection.get_tenant = Mock(return_value='the tenant')
431
    mocked_connection.set_tenant = Mock()
432
    command = Command()
433
    command.run_cook = Mock()
434
    command.cook('a-recipe-file.json')
435

  
436
    assert len(mocked_connection.get_tenant.mock_calls) == 1
437
    assert command.run_cook.mock_calls == [call('a-recipe-file.json')]
438
    assert mocked_connection.set_tenant.mock_calls == [call('the tenant')]
78
-