Projet

Général

Profil

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

Nicolas Roche, 10 mai 2019 11:01

Télécharger (16 ko)

Voir les différences:

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

 tests/test_cook.py | 397 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 390 insertions(+), 7 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
    expected = [call('recipe_me.json')]
65

  
66
    kwargs = {'verbosity': 'verbosity value',
67
              'timeout': 'timeout value',
68
              'permissive': 'permissive value'}
69
    command = Command()
70
    command.run_cook = Mock()
71

  
72
    command.handle('recipe_me.json', **kwargs)
73
    assert command.verbosity == 'verbosity value'
74
    assert command.timeout == 'timeout value'
75
    assert command.permissive == 'permissive value'
76
    assert command.run_cook.mock_calls == expected
77

  
78
@patch('hobo.environment.management.commands.cook.open')
79
@patch('hobo.environment.management.commands.cook.notify_agents')
80
def test_run_cook(mocked_notify_agents, mocked_open):
81
    receipe = """{
82
  "steps": [
83
    {"create-hobo": {
84
      "url": "https://entrouvert.org/"
85
    }}
86
  ]
87
}"""
88
    expected1 = [call(u'create-hobo', {u'url': u'https://entrouvert.org/'})]
89
    expected2 = [call(url=u'https://entrouvert.org/')]
90
    expected3 = []
91
    expected4 = [call(timeout=42)]
92

  
93
    command = Command()
94
    command.permissive = False
95
    command.must_notify = True
96
    command.timeout = 42
97
    command.check_action = Mock()
98
    command.create_hobo = Mock()
99
    mocked_notify_agents = Mock()
100
    command.wait_operationals = Mock()
101

  
102
    mocked_open.side_effect = [StringIO.StringIO(receipe)]
103
    command.run_cook('recipe_me.json')
104
    assert command.check_action.mock_calls == expected1
105
    assert command.create_hobo.mock_calls == expected2
106
    assert mocked_notify_agents.mock_calls == expected3
107
    assert command.wait_operationals.mock_calls == expected4
108

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

  
71 121
    command = Command()
72 122
    command.permissive = True
73
    command.create_authentic = mock.MagicMock()
123
    command.create_authentic = Mock()
74 124

  
75 125
    mocked_open.side_effect = [StringIO.StringIO(receipe)]
76 126
    command.run_cook('recipe_me.json')
77
    assert str(command.create_authentic.mock_calls) == expected_a2
127
    assert command.create_authentic.mock_calls == expected_a2
128

  
129
@patch('hobo.environment.management.commands.cook.open')
130
def test_load_variables_from(mocked_open):
131
    """load variables from a file"""
132
    receipe = """{
133
  "load-variables-from": "variables.json",
134
  "variables": {
135
    "domain": "entrouvert.org",
136
    "bar": "bar2"
137
  },
138
  "steps": [
139
    {"create-hobo": {
140
      "url": "https://${domain}/"
141
    }},
142
    {"create-authentic": {
143
      "url": "https://${foo}/"
144
    }},
145
    {"create-combo": {
146
      "url": "https://${bar}/",
147
      "not_a_string": []
148
    }}
149
  ]
150
}"""
151
    variables = """{
152
  "foo": "foo1",
153
  "bar": "bar1"
154
}"""
155
    expected_hobo = [call(url=u'https://entrouvert.org/')]
156
    expected_a2 = [call(url=u'https://foo1/')]
157
    expected_combo = [call(not_a_string=[], url=u'https://bar2/')]
158

  
159
    command = Command()
160
    command.permissive = True
161
    command.create_hobo = Mock()
162
    command.create_authentic = Mock()
163
    command.create_combo = Mock()
164

  
165
    mocked_open.side_effect = [StringIO.StringIO(receipe),
166
                               StringIO.StringIO(variables)]
167
    command.run_cook('recipe_me.json')
168
    assert command.create_hobo.mock_calls == expected_hobo
169
    assert command.create_authentic.mock_calls == expected_a2
170
    assert command.create_combo.mock_calls == expected_combo
171

  
172
def test_wait_operationals(db, monkeypatch):
173
    service1 = Mock()
174
    service2 = Mock()
175
    obj1 = Mock()
176
    obj2 = Mock()
177

  
178
    def do_nothing(*args, **kwargs):
179
        pass
180

  
181
    obj1.check_operational = do_nothing
182
    obj2.check_operational = do_nothing
183
    obj1.base_url = 'url1'
184
    obj2.base_url = 'url2'
185

  
186
    service1.objects.all = Mock(return_value = [obj1])
187
    service2.objects.all = Mock(return_value = [obj2])
188
    monkeypatch.setattr(
189
        'hobo.environment.management.commands.cook.AVAILABLE_SERVICES',
190
        [service1, service2])
191
    command = Command()
192

  
193
    # already operational
194
    obj1.last_operational_success_timestamp = 'some date'
195
    obj2.last_operational_success_timestamp = 'some date'
196
    command.wait_operationals(2)
197
    assert True
198

  
199
    # not operational
200
    obj2.last_operational_success_timestamp = None
201
    with pytest.raises(CommandError) as e_info:
202
        command.wait_operationals(.6)
203
    assert str(e_info).find('CommandError: timeout waiting for url2') != -1
204

  
205
def test_set_variable(db):
206
    command = Command()
207

  
208
    command.set_variable('foo', 'bar')
209
    value = Variable.objects.get(name='foo').value
210
    label = Variable.objects.get(name='foo').label
211
    assert value == 'bar'
212
    assert label == 'foo'
213

  
214
    command.set_variable('foo', 'bar', label='FOO')
215
    value = Variable.objects.get(name='foo').value
216
    label = Variable.objects.get(name='foo').label
217
    assert value == 'bar'
218
    assert label == 'FOO'
219

  
220
    command.set_variable('foo', ['bar', 'baz'])
221
    value = Variable.objects.get(name='foo').value
222
    assert value == '["bar", "baz"]'
223

  
224
    command.set_variable('foo', {'key1': 'bar', 'key2': 'baz'})
225
    value = Variable.objects.get(name='foo').value
226
    ordered_dump = json.dumps(json.loads(value), sort_keys=True)
227
    assert  ordered_dump == '{"key1": "bar", "key2": "baz"}'
228

  
229
def test_set_attribute(db):
230
    command = Command()
231
    command.set_attribute('foo_name', 'foo_label')
232
    values = AttributeDefinition.objects.filter(name='foo_name')
233
    assert values.count() == 1
234
    assert values[0].label == 'foo_label'
235
    assert values[0].disabled is False
236

  
237
    command.set_attribute('foo_name', 'foo_label', disabled=True)
238
    values = AttributeDefinition.objects.filter(name='foo_name')
239
    assert values.count() == 1
240
    assert values[0].label == 'foo_label'
241
    assert values[0].disabled is True
242

  
243
def test_disable_attribute(db):
244
    command = Command()
245
    command.set_attribute('foo_name', 'foo_label')
246
    values = AttributeDefinition.objects.filter(name='foo_name')
247
    assert values.count() == 1
248
    assert values[0].label == 'foo_label'
249
    assert values[0].disabled is False
250

  
251
    command.disable_attribute('foo_name')
252
    values = AttributeDefinition.objects.filter(name='foo_name')
253
    assert values[0].disabled is True
254

  
255
    command.disable_attribute('not_defined')
256
    values = AttributeDefinition.objects.filter(name='not_defined')
257
    assert values.count() == 0
258

  
259
def test_enable_attribute(db):
260
    command = Command()
261
    command.set_attribute('foo_name', 'foo_label', disabled=True)
262
    values = AttributeDefinition.objects.filter(name='foo_name')
263
    assert values.count() == 1
264
    assert values[0].label == 'foo_label'
265
    assert values[0].disabled is True
266

  
267
    command.enable_attribute('foo_name')
268
    values = AttributeDefinition.objects.filter(name='foo_name')
269
    assert values[0].disabled is False
270

  
271
    command.enable_attribute('not_defined')
272
    values = AttributeDefinition.objects.filter(name='not_defined')
273
    assert values.count() == 0
274

  
275
def test_create_superuser(db):
276
    command = Command()
277
    command.create_superuser()
278
    assert User.objects.count() == 1
279
    user = User.objects.all()[0]
280
    assert user.username == 'admin'
281
    assert user.is_superuser is True
282

  
283
def test_create_site(db):
284
    """
285
    code redondant ?
286
      service_type=obj_type,
287
      service_pk=obj.id,
288
    """
289
    command = Command()
290
    base_url = 'http://entrouvert.org'
291
    title = 'site title'
292
    slug = None
293
    template_name = ''
294
    variables = {'foo': {'label': 'FOO', 'value': {'key': 'bar'}}}
295
    command.create_site(Combo, base_url, title, slug, template_name,
296
                        variables)
297

  
298
    # Combo object
299
    assert Combo.objects.count() == 1
300
    combo = Combo.objects.all()[0]
301
    assert combo.title == title
302
    assert combo.base_url == base_url + '/'
303
    assert combo.template_name == ''
304

  
305
    # ContentType object
306
    obj_type = ContentType.objects.get_for_model(Combo)
307

  
308
    # Variables
309
    variable = Variable.objects.get(name='foo')
310
    assert variable.label == 'FOO'
311
    assert variable.value == '{"key": "bar"}'
312
    assert variable.service_type == obj_type
313
    assert variable.service_pk == combo.id
314

  
315
    with pytest.raises(CommandError) as e_info:
316
        command.create_site(Combo, 'unvalid_url', 'site title', 'a slug', '', '')
317
    assert 'Enter a valid URL.' in str(e_info.value)
318

  
319
@patch('hobo.environment.management.commands.cook.connection')
320
@patch('hobo.environment.management.commands.cook.call_command')
321
@patch('hobo.environment.management.commands.cook.TenantMiddleware')
322
def test_create_hobo_primary(mocked_TenantMiddleware, mocked_call_command,
323
                             mocked_connection):
324
    expected1 = []
325
    expected2 = [call('create_hobo_tenant', 'entrouvert.org')]
326
    expected3 = [call('/bof/base_url', 'w'),
327
                 call().write('http://entrouvert.org/and_much'),
328
                 call().close()]
329

  
330
    command = Command()
331
    command.create_site = Mock()
332
    tenant = Mock()
333
    tenant.schema_name = 'public'
334
    tenant.get_directory = Mock(return_value='/bof')
335
    mocked_connection.get_tenant = Mock(return_value=tenant)
336
    mocked_connection.set_tenant = Mock()
337
    mocked_TenantMiddleware.get_tenant_by_hostname = Mock(return_value=tenant)
338
    mocked_call_command.side_effect = CommandError
339

  
340
    mocked_open = mock_open()
341
    with patch('hobo.environment.management.commands.cook.open', mocked_open,
342
                    create=True):
343
        command.create_hobo('http://entrouvert.org/and_much')
344
    assert command.create_site.mock_calls == expected1
345
    assert mocked_call_command.mock_calls == expected2
346
    assert len(mocked_connection.set_tenant.mock_calls) == 1
347
    assert mocked_open.mock_calls == expected3
348

  
349
@patch('hobo.environment.management.commands.cook.connection')
350
@patch('hobo.environment.management.commands.cook.call_command')
351
@patch('hobo.environment.management.commands.cook.TenantMiddleware')
352
def test_create_hobo_not_primary(mocked_TenantMiddleware, mocked_call_command,
353
                     mocked_connection):
354
    command = Command()
355
    command.create_site = Mock()
356
    tenant = Mock()
357
    tenant.schema_name = 'public'
358
    tenant.get_directory = Mock(return_value='/bof')
359
    mocked_connection.get_tenant = Mock(return_value=tenant)
360
    mocked_connection.set_tenant = Mock()
361
    mocked_TenantMiddleware.get_tenant_by_hostname = Mock(return_value=tenant)
362

  
363
    expected1 = [call(Hobo, 'http://entrouvert.org/and_much', None, u'hobo-none',
364
                      template_name='', variables=None)]
365
    expected2 = []
366
    expected3 = []
367

  
368
    tenant.schema_name = 'other than public'
369
    mocked_open = mock_open()
370
    with patch('hobo.environment.management.commands.cook.open', mocked_open,
371
                    create=True):
372
        command.create_hobo('http://entrouvert.org/and_much')
373
    assert command.create_site.mock_calls == expected1
374
    assert mocked_call_command.mock_calls == expected2
375
    assert len(mocked_connection.set_tenant.mock_calls) == 1
376
    assert mocked_open.mock_calls == expected3
377

  
378
def test_create_services():
379
    expected = [call(Authentic, 'url', 'title', None, '', None),
380
                call(Combo, 'url', 'title', None, '', None),
381
                call(Wcs, 'url', 'title', None, '', None),
382
                call(Passerelle, 'url', 'title', None, '', None),
383
                call(Fargo, 'url', 'title', None, '', None),
384
                call(Welco, 'url', 'title', None, '', None),
385
                call(Chrono, 'url', 'title', None, '', None),
386
                call(Corbo, 'url', 'title', None, '', None),
387
                call(BiJoe, 'url', 'title', None, '', None)]
388

  
389
    command = Command()
390
    command.create_site = Mock()
391
    command.create_authentic('url', 'title')
392
    command.create_combo('url', 'title')
393
    command.create_wcs('url', 'title')
394
    command.create_passerelle('url', 'title')
395
    command.create_fargo('url', 'title')
396
    command.create_welco('url', 'title')
397
    command.create_chrono('url', 'title')
398
    command.create_corbo('url', 'title')
399
    command.create_bijoe('url', 'title')
400

  
401
    assert len(command.create_site.mock_calls) == 9
402
    assert command.create_site.mock_calls == expected
403

  
404
def test_set_idp(db):
405
    command = Command()
406

  
407
    # exceptions maybe we should handle into cook.py ?
408
    with pytest.raises(Authentic.DoesNotExist,
409
                       match='Authentic matching query does not exist'):
410
        command.set_idp('url')
411
    with pytest.raises(IndexError, match='list index out of range'):
412
        command.set_idp()
413

  
414
    # objects sorted on title: [obj1, obj2]
415
    obj1, ignored = Authentic.objects.get_or_create(
416
        slug='slug1', defaults={'title': 'bar'})
417
    obj2, ignored = Authentic.objects.get_or_create(
418
        slug='slug2', defaults={'title': 'foo', 'base_url': 'http://example.org'})
419
    assert obj1.use_as_idp_for_self is False
420
    assert obj2.use_as_idp_for_self is False
421

  
422
    # set first
423
    command.set_idp('')
424
    obj = Authentic.objects.get(title='bar')
425
    assert obj.use_as_idp_for_self is True
426

  
427
    # set using url
428
    command.set_idp('http://example.org/')
429
    obj = Authentic.objects.get(title='foo')
430
    assert obj.use_as_idp_for_self is True
431

  
432
@patch('hobo.environment.management.commands.cook.set_theme')
433
@patch('hobo.environment.management.commands.cook.connection')
434
@patch('hobo.agent.common.management.commands.hobo_deploy.Command.configure_theme')
435
def test_set_theme(mocked_configure_theme, mocked_connection, mocked_set_theme):
436
    expected1 = [call('the theme')]
437
    expected2 = [call({'variables': {'theme': 'the theme'}}, 'the tenant')]
438

  
439
    mocked_connection.get_tenant = Mock(return_value='the tenant')
440
    command = Command()
441
    command.set_theme('the theme')
442

  
443
    assert mocked_set_theme.mock_calls == expected1
444
    assert len(mocked_connection.get_tenant.mock_calls) == 1
445
    assert mocked_configure_theme.mock_calls == expected2
446

  
447
@patch('hobo.environment.management.commands.cook.connection')
448
def test_cook(mocked_connection):
449
    expected1 = [call('a-recipe-file.json')]
450
    expected2 = [call('the tenant')]
451

  
452
    mocked_connection.get_tenant = Mock(return_value='the tenant')
453
    mocked_connection.set_tenant = Mock()
454
    command = Command()
455
    command.run_cook = Mock()
456
    command.cook('a-recipe-file.json')
457

  
458
    assert len(mocked_connection.get_tenant.mock_calls) == 1
459
    assert command.run_cook.mock_calls == expected1
460
    assert mocked_connection.set_tenant.mock_calls == expected2
78
-