Use tmpdir when using mock catalog of tests
[dcaegen2/platform/cli.git] / dcae-cli / dcae_cli / catalog / mock / tests / test_mock_catalog.py
1 # ============LICENSE_START=======================================================
2 # org.onap.dcae
3 # ================================================================================
4 # Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
5 # ================================================================================
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #      http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 # ============LICENSE_END=========================================================
18 #
19 # ECOMP is a trademark and service mark of AT&T Intellectual Property.
20
21 # -*- coding: utf-8 -*-
22 '''
23 Tests the mock catalog
24 '''
25 import json
26 from copy import deepcopy
27 from functools import partial
28
29 import pytest
30
31 from sqlalchemy.exc import IntegrityError
32
33 from dcae_cli.catalog.mock.catalog import MockCatalog, MissingEntry, DuplicateEntry, _get_unique_format_things
34 from dcae_cli.catalog.mock import catalog
35
36
37 _c1_spec = {'self': {'name': 'std.comp_one',
38                     'version': '1.0.0',
39                     'description': 'comp1',
40                     'component_type': 'docker'},
41           'streams': {'publishes': [{'format': 'std.format_one',
42                                      'version': '1.0.0',
43                                      'config_key': 'pub1',
44                                      'type': 'http'}],
45                       'subscribes': [{'format': 'std.format_one',
46                                       'version': '1.0.0',
47                                       'route': '/sub1',
48                                       'type': 'http'}]},
49           'services': {'calls': [{'request': {'format': 'std.format_one',
50                                               'version': '1.0.0'},
51                                   'response': {'format': 'std.format_one',
52                                                'version': '1.0.0'},
53                                   'config_key': 'call1'}],
54                        'provides': [{'request': {'format': 'std.format_one',
55                                                  'version': '1.0.0'},
56                                      'response': {'format': 'std.format_one',
57                                                   'version': '1.0.0'},
58                                      'route': '/prov1'}]},
59           'parameters': [{"name": "foo",
60                           "value": 1,
61                           "description": "the foo thing"},
62                          {"name": "bar",
63                           "value": 2,
64                           "description": "the bar thing"}
65                           ],
66           'artifacts': [{ "uri": "foo-image", "type": "docker image" }],
67           'auxilary': {
68             "healthcheck": {
69                 "type": "http",
70                 "endpoint": "/health",
71                 "interval": "15s",
72                 "timeout": "1s"
73                 }
74               }
75            }
76
77 _c2_spec = {'self': {'name': 'std.comp_two',
78                           'version': '1.0.0',
79                           'description': 'comp2',
80                           'component_type': 'docker'},
81           'streams': {'publishes': [],
82                       'subscribes': [{'format': 'std.format_one',
83                                       'version': '1.0.0',
84                                       'route': '/sub1',
85                                       'type': 'http'}]},
86           'services': {'calls': [],
87                        'provides': [{'request': {'format': 'std.format_one',
88                                                  'version': '1.0.0'},
89                                      'response': {'format': 'std.format_one',
90                                                   'version': '1.0.0'},
91                                      'route': '/prov1'}]},
92           'parameters': [],
93           'artifacts': [{ "uri": "bar-image", "type": "docker image" }],
94           'auxilary': {
95             "healthcheck": {
96                 "type": "http",
97                 "endpoint": "/health",
98                 "interval": "15s",
99                 "timeout": "1s"
100                 }
101               }
102            }
103
104
105 _c2v2_spec = {'self': {'name': 'std.comp_two',
106                           'version': '2.0.0',
107                           'description': 'comp2',
108                           'component_type': 'docker'},
109           'streams': {'publishes': [],
110                       'subscribes': [{'format': 'std.format_one',
111                                       'version': '1.0.0',
112                                       'route': '/sub1',
113                                       'type': 'http'}]},
114           'services': {'calls': [],
115                        'provides': [{'request': {'format': 'std.format_one',
116                                                  'version': '1.0.0'},
117                                      'response': {'format': 'std.format_one',
118                                                   'version': '1.0.0'},
119                                      'route': '/prov1'}]},
120           'parameters': [],
121           'artifacts': [{ "uri": "baz-image", "type": "docker image" }],
122           'auxilary': {
123             "healthcheck": {
124                 "type": "http",
125                 "endpoint": "/health",
126                 "interval": "15s",
127                 "timeout": "1s"
128                 }
129               }
130            }
131
132
133 _c3_spec = {'self': {'name': 'std.comp_three',
134                           'version': '3.0.0',
135                           'description': 'comp3',
136                           'component_type': 'docker'},
137           'streams': {'publishes': [],
138                       'subscribes': [{'format': 'std.format_two',
139                                       'version': '1.5.0',
140                                       'route': '/sub1',
141                                       'type': 'http'}]},
142           'services': {'calls': [],
143                        'provides': [{'request': {'format': 'std.format_one',
144                                                  'version': '1.0.0'},
145                                      'response': {'format': 'std.format_two',
146                                                   'version': '1.5.0'},
147                                      'route': '/prov1'}]},
148           'parameters': [],
149           'artifacts': [{ "uri": "bazinga-image", "type": "docker image" }],
150           'auxilary': {
151             "healthcheck": {
152                 "type": "http",
153                 "endpoint": "/health",
154                 "interval": "15s",
155                 "timeout": "1s"
156                 }
157               }
158            }
159
160
161 _df1_spec = {
162           "self": {
163               "name": "std.format_one",
164               "version": "1.0.0",
165               "description": "df1"
166           },
167           "dataformatversion": "1.0.0",
168           "jsonschema": {
169               "$schema": "http://json-schema.org/draft-04/schema#",
170                       "type": "object",
171               "properties": {
172                   "raw-text": {
173                       "type": "string"
174                   }
175               },
176               "required": ["raw-text"],
177               "additionalProperties": False
178           }
179         }
180 _df2_spec = {
181           "self": {
182               "name": "std.format_two",
183               "version": "1.5.0",
184               "description": "df2"
185           },
186           "dataformatversion": "1.0.0",
187           "jsonschema": {
188               "$schema": "http://json-schema.org/draft-04/schema#",
189                       "type": "object",
190               "properties": {
191                   "raw-text": {
192                       "type": "string"
193                   }
194               },
195               "required": ["raw-text"],
196               "additionalProperties": False
197           }
198        }
199 _df2v2_spec  = {
200           "self": {
201               "name": "std.format_two",
202               "version": "2.0.0",
203               "description": "df2"
204           },
205           "dataformatversion": "1.0.0",
206           "jsonschema": {
207               "$schema": "http://json-schema.org/draft-04/schema#",
208                       "type": "object",
209               "properties": {
210                   "raw-text": {
211                       "type": "string"
212                   }
213               },
214               "required": ["raw-text"],
215               "additionalProperties": False
216           }
217             }
218
219 _cdap_spec={
220    "self":{
221       "name":"std.cdap_comp",
222       "version":"0.0.0",
223       "description":"cdap test component",
224       "component_type":"cdap"
225    },
226    "streams":{
227       "publishes":[
228          {
229             "format":"std.format_one",
230             "version":"1.0.0",
231             "config_key":"pub1",
232             "type": "http"
233          }
234       ],
235       "subscribes":[
236          {
237             "format":"std.format_two",
238             "version":"1.5.0",
239             "route":"/sub1",
240             "type": "http"
241          }
242       ]
243    },
244    "services":{
245       "calls":[
246
247       ],
248       "provides":[
249          {
250             "request":{
251                "format":"std.format_one",
252                "version":"1.0.0"
253             },
254             "response":{
255                "format":"std.format_two",
256                "version":"1.5.0"
257             },
258             "service_name":"baphomet",
259             "service_endpoint":"rises",
260             "verb":"GET"
261          }
262       ]
263    },
264    "parameters": {
265        "app_config" : [],
266        "app_preferences" : [],
267        "program_preferences" : []
268    },
269    "artifacts": [{"uri": "bahpomet.com", "type": "jar"}],
270    "auxilary": {
271         "streamname":"streamname",
272         "artifact_version":"6.6.6",
273         "artifact_name": "test_name",
274         "programs" : [{"program_type" : "flows", "program_id" : "flow_id"}]
275         }
276
277 }
278
279
280 def test_component_basic(mock_cli_config, mock_db_url, catalog=None):
281     '''Tests basic component usage of MockCatalog'''
282     if catalog is None:
283         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
284                 enforce_image=False, db_url=mock_db_url)
285     else:
286         mc = catalog
287
288     c1_spec = deepcopy(_c1_spec)
289     df1_spec = deepcopy(_df1_spec)
290     df2_spec = deepcopy(_df2_spec)
291
292     user = "test_component_basic"
293
294     # success
295     mc.add_format(df2_spec, user)
296
297     # duplicate
298     with pytest.raises(DuplicateEntry):
299         mc.add_format(df2_spec, user)
300
301     # component relies on df1_spec which hasn't been added
302     with pytest.raises(MissingEntry):
303         mc.add_component(user, c1_spec)
304
305     # add df1 and comp1
306     mc.add_format(df1_spec, user)
307     mc.add_component(user, c1_spec)
308
309     with pytest.raises(DuplicateEntry):
310         mc.add_component(user, c1_spec)
311
312     cname, cver = mc.verify_component('std.comp_one', version=None)
313     assert cver == '1.0.0'
314
315
316 def test_format_basic(mock_cli_config, mock_db_url, catalog=None):
317     '''Tests basic data format usage of MockCatalog'''
318     if catalog is None:
319         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
320                 db_url=mock_db_url)
321     else:
322         mc = catalog
323
324     user = "test_format_basic"
325
326     df1_spec = deepcopy(_df1_spec)
327     df2_spec = deepcopy(_df2_spec)
328
329     # success
330     mc.add_format(df1_spec, user)
331
332     # duplicate is bad
333     with pytest.raises(DuplicateEntry):
334         mc.add_format(df1_spec, user)
335
336     # allow update of same version
337     new_descr = 'a new description'
338     df1_spec['self']['description'] = new_descr
339     mc.add_format(df1_spec, user, update=True)
340
341     # adding a new version is kosher
342     new_ver = '2.0.0'
343     df1_spec['self']['version'] = new_ver
344     mc.add_format(df1_spec, user)
345
346     # can't update a format that doesn't exist
347     with pytest.raises(MissingEntry):
348         mc.add_format(df2_spec, user, update=True)
349
350     # get spec and make sure it's updated
351     spec = mc.get_format_spec(df1_spec['self']['name'], version=None)
352     assert spec['self']['version'] == new_ver
353     assert spec['self']['description'] == new_descr
354
355
356 def test_discovery(mock_cli_config, mock_db_url, catalog=None):
357     '''Tests creation of discovery objects'''
358     if catalog is None:
359         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
360                 enforce_image=False, db_url=mock_db_url)
361     else:
362         mc = catalog
363
364     user = "test_discovery"
365
366     c1_spec = deepcopy(_c1_spec)
367     df1_spec = deepcopy(_df1_spec)
368     c2_spec = deepcopy(_c2_spec)
369
370     mc.add_format(df1_spec, user)
371     mc.add_component(user, c1_spec)
372     mc.add_component(user, c2_spec)
373
374     params, interfaces = mc.get_discovery_for_docker(c1_spec['self']['name'], c1_spec['self']['version'])
375     assert params == {'bar': 2, 'foo': 1}
376     assert interfaces == {'call1': [('std.comp_two', '1.0.0')], 'pub1': [('std.comp_two', '1.0.0')]}
377
378
379 def _spec_tuple(dd):
380     '''Returns a (name, version, component type) tuple from a given component spec dict'''
381     return dd['self']['name'], dd['self']['version'], dd['self']['component_type']
382
383
384 def _comp_tuple_set(*dds):
385     '''Runs a set of component spec tuples'''
386     return set(map(_spec_tuple, dds))
387
388
389 def _format_tuple(dd):
390     '''Returns a (name, version) tuple from a given data format spec dict'''
391     return dd['self']['name'], dd['self']['version']
392
393
394 def _format_tuple_set(*dds):
395     '''Runs a set of data format spec tuples'''
396     return set(map(_format_tuple, dds))
397
398
399 def test_comp_list(mock_cli_config, mock_db_url, catalog=None):
400     '''Tests the list functionality of the catalog'''
401     if catalog is None:
402         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
403                 enforce_image=False, db_url=mock_db_url)
404     else:
405         mc = catalog
406
407     user = "test_comp_list"
408
409     df1_spec = deepcopy(_df1_spec)
410     df2_spec = deepcopy(_df2_spec)
411     df2v2_spec = deepcopy(_df2v2_spec)
412
413     c1_spec = deepcopy(_c1_spec)
414     c2_spec = deepcopy(_c2_spec)
415     c2v2_spec = deepcopy(_c2v2_spec)
416     c3_spec = deepcopy(_c3_spec)
417
418     mc.add_format(df1_spec, user)
419     mc.add_format(df2_spec, user)
420     mc.add_format(df2v2_spec, user)
421     mc.add_component(user, c1_spec)
422     mc.add_component(user, c2_spec)
423     mc.add_component(user, c2v2_spec)
424     mc.add_component(user, c3_spec)
425
426     mc.add_component(user,_cdap_spec)
427
428     def components_to_specs(components):
429         return [ json.loads(c["spec"]) for c in components ]
430
431     # latest by default. only v2 of c2
432     components = mc.list_components()
433     specs = components_to_specs(components)
434     assert _comp_tuple_set(*specs) == _comp_tuple_set(c1_spec, c2v2_spec, c3_spec, _cdap_spec)
435
436     # all components
437     components = mc.list_components(latest=False)
438     specs = components_to_specs(components)
439     assert _comp_tuple_set(*specs) == _comp_tuple_set(c1_spec, c2_spec, c2v2_spec, c3_spec, _cdap_spec)
440
441     components = mc.list_components(subscribes=[('std.format_one', None)])
442     specs = components_to_specs(components)
443     assert _comp_tuple_set(*specs) == _comp_tuple_set(c1_spec, c2v2_spec)
444
445     # no comps subscribe to latest std.format_two
446     components = mc.list_components(subscribes=[('std.format_two', None)])
447     assert not components
448
449     components = mc.list_components(subscribes=[('std.format_two', '1.5.0')])
450     specs = components_to_specs(components)
451     assert _comp_tuple_set(*specs) == _comp_tuple_set(c3_spec, _cdap_spec)
452
453     # raise if format doesn't exist
454     with pytest.raises(MissingEntry):
455         mc.list_components(subscribes=[('std.format_two', '5.0.0')])
456
457     components = mc.list_components(publishes=[('std.format_one', None)])
458     specs = components_to_specs(components)
459     assert _comp_tuple_set(*specs) == _comp_tuple_set(c1_spec, _cdap_spec)
460
461     components = mc.list_components(calls=[(('std.format_one', None), ('std.format_one', None)), ])
462     specs = components_to_specs(components)
463     assert _comp_tuple_set(*specs) == _comp_tuple_set(c1_spec)
464
465     # raise if format doesn't exist
466     with pytest.raises(MissingEntry):
467         mc.list_components(calls=[(('std.format_one', '5.0.0'), ('std.format_one', None)), ])
468
469     components = mc.list_components(provides=[(('std.format_one', '1.0.0'), ('std.format_two', '1.5.0')), ])
470     specs = components_to_specs(components)
471     assert _comp_tuple_set(*specs) == _comp_tuple_set(c3_spec, _cdap_spec)
472
473     # test for listing published components
474
475     name_pub = c1_spec["self"]["name"]
476     version_pub = c1_spec["self"]["version"]
477     mc.publish_component(user, name_pub, version_pub)
478     components = mc.list_components(only_published=True)
479     specs = components_to_specs(components)
480     assert _comp_tuple_set(*specs) == _comp_tuple_set(c1_spec)
481
482     components = mc.list_components(only_published=False)
483     assert len(components) == 4
484
485
486 def test_format_list(mock_cli_config, mock_db_url, catalog=None):
487     '''Tests the list functionality of the catalog'''
488     if catalog is None:
489         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
490                 enforce_image=False, db_url=mock_db_url)
491     else:
492         mc = catalog
493
494     user = "test_format_list"
495
496     df1_spec = deepcopy(_df1_spec)
497     df2_spec = deepcopy(_df2_spec)
498     df2v2_spec = deepcopy(_df2v2_spec)
499
500     mc.add_format(df1_spec, user)
501     mc.add_format(df2_spec, user)
502     mc.add_format(df2v2_spec, user)
503
504     def formats_to_specs(components):
505         return [ json.loads(c["spec"]) for c in components ]
506
507     # latest by default. ensure only v2 of df2 makes it
508     formats = mc.list_formats()
509     specs = formats_to_specs(formats)
510     assert _format_tuple_set(*specs) == _format_tuple_set(df1_spec, df2v2_spec)
511
512     # list all
513     formats = mc.list_formats(latest=False)
514     specs = formats_to_specs(formats)
515     assert _format_tuple_set(*specs) == _format_tuple_set(df1_spec, df2_spec, df2v2_spec)
516
517     # test listing of published formats
518
519     name_pub = df1_spec["self"]["name"]
520     version_pub = df1_spec["self"]["version"]
521
522     mc.publish_format(user, name_pub, version_pub)
523     formats = mc.list_formats(only_published=True)
524     specs = formats_to_specs(formats)
525     assert _format_tuple_set(*specs) == _format_tuple_set(df1_spec)
526
527     formats = mc.list_formats(only_published=False)
528     assert len(formats) == 2
529
530
531 def test_component_add_cdap(mock_cli_config, mock_db_url, catalog=None):
532     '''Adds a mock CDAP application'''
533     if catalog is None:
534         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
535                 db_url=mock_db_url)
536     else:
537         mc = catalog
538
539     user = "test_component_add_cdap"
540
541     df1_spec = deepcopy(_df1_spec)
542     df2_spec = deepcopy(_df2_spec)
543
544     mc.add_format(df1_spec, user)
545     mc.add_format(df2_spec, user)
546
547     mc.add_component(user, _cdap_spec)
548
549     name, version, _ = _spec_tuple(_cdap_spec)
550     jar_out, cdap_config_out, spec_out = mc.get_cdap(name, version)
551
552     assert _cdap_spec["artifacts"][0]["uri"] == jar_out
553     assert _cdap_spec["auxilary"] == cdap_config_out
554     assert _cdap_spec == spec_out
555
556
557 def test_get_discovery_from_spec(mock_cli_config, mock_db_url):
558     mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
559             enforce_image=False, db_url=mock_db_url)
560
561     user = "test_get_discovery_from_spec"
562
563     c1_spec_updated = deepcopy(_c1_spec)
564     c1_spec_updated["streams"]["publishes"][0] = {
565             'format': 'std.format_one',
566             'version': '1.0.0',
567             'config_key': 'pub1',
568             'type': 'http'
569             }
570     c1_spec_updated["streams"]["subscribes"][0] = {
571             'format': 'std.format_one',
572             'version': '1.0.0',
573             'route': '/sub1',
574             'type': 'http'
575             }
576
577     # Case when c1 doesn't exist
578
579     mc.add_format(_df1_spec, user)
580     mc.add_component(user, _c2_spec)
581     actual_params, actual_interface_map, actual_dmaap_config_keys \
582             = mc.get_discovery_from_spec(user, c1_spec_updated, None)
583
584     assert actual_params == {'bar': 2, 'foo': 1}
585     assert actual_interface_map == { 'pub1': [('std.comp_two', '1.0.0')],
586             'call1': [('std.comp_two', '1.0.0')] }
587     assert actual_dmaap_config_keys == ([], [])
588
589     # Case when c1 already exist
590
591     mc.add_component(user,_c1_spec)
592
593     c1_spec_updated["services"]["calls"][0]["config_key"] = "callme"
594     actual_params, actual_interface_map, actual_dmaap_config_keys \
595             = mc.get_discovery_from_spec(user, c1_spec_updated, None)
596
597     assert actual_params == {'bar': 2, 'foo': 1}
598     assert actual_interface_map == { 'pub1': [('std.comp_two', '1.0.0')],
599             'callme': [('std.comp_two', '1.0.0')] }
600     assert actual_dmaap_config_keys == ([], [])
601
602     # Case where add in dmaap streams
603     # TODO: Add in subscribes test case after spec gets pushed
604
605     c1_spec_updated["streams"]["publishes"][0] = {
606             'format': 'std.format_one',
607             'version': '1.0.0',
608             'config_key': 'pub1',
609             'type': 'message router'
610             }
611
612     actual_params, actual_interface_map, actual_dmaap_config_keys \
613             = mc.get_discovery_from_spec(user, c1_spec_updated, None)
614
615     assert actual_params == {'bar': 2, 'foo': 1}
616     assert actual_interface_map == { 'callme': [('std.comp_two', '1.0.0')] }
617     assert actual_dmaap_config_keys == (["pub1"], [])
618
619     # Case when cdap spec doesn't exist
620
621     cdap_spec = deepcopy(_cdap_spec)
622     cdap_spec["streams"]["publishes"][0] = {
623             'format': 'std.format_one',
624             'version': '1.0.0',
625             'config_key': 'pub1',
626             'type': 'http'
627             }
628     cdap_spec["streams"]["subscribes"][0] = {
629             'format': 'std.format_two',
630             'version': '1.5.0',
631             'route': '/sub1',
632             'type': 'http'
633             }
634
635     mc.add_format(_df2_spec, user)
636     actual_params, actual_interface_map, actual_dmaap_config_keys \
637             = mc.get_discovery_from_spec(user, cdap_spec, None)
638
639     assert actual_params == {'program_preferences': [], 'app_config': {}, 'app_preferences': {}}
640     assert actual_interface_map == {'pub1': [('std.comp_two', '1.0.0'), ('std.comp_one', '1.0.0')]}
641     assert actual_dmaap_config_keys == ([], [])
642
643
644 def test_get_unpublished_formats(mock_cli_config, mock_db_url, catalog=None):
645     if catalog is None:
646         mc = MockCatalog(db_name='dcae_cli.test.db', purge_existing=True,
647                 enforce_image=False, db_url=mock_db_url)
648     else:
649         mc = catalog
650
651     user = "test_get_unpublished_formats"
652
653     mc.add_format(_df1_spec, user)
654     mc.add_component(user, _c1_spec)
655
656     # detect unpublished formats
657
658     name_to_pub = _c1_spec["self"]["name"]
659     version_to_pub = _c1_spec["self"]["version"]
660     formats = mc.get_unpublished_formats(name_to_pub, version_to_pub)
661     assert [('std.format_one', '1.0.0')] == formats
662
663     # all formats published
664
665     mc.publish_format(user, _df1_spec["self"]["name"], _df1_spec["self"]["version"])
666     formats = mc.get_unpublished_formats(name_to_pub, version_to_pub)
667     assert len(formats) == 0
668
669
670 def test_get_unique_format_things():
671     def create_tuple(entry):
672         return (entry["name"], entry["version"])
673
674     def get_orm(name, version):
675         return ("ORM", name, version)
676
677     entries = [{"name": "abc", "version": 123},
678             {"name": "abc", "version": 123},
679             {"name": "abc", "version": 123},
680             {"name": "def", "version": 456},
681             {"name": "def", "version": 456}]
682
683     get_unique_fake_format = partial(_get_unique_format_things, create_tuple,
684             get_orm)
685     expected = [("ORM", "abc", 123), ("ORM", "def", 456)]
686
687     assert sorted(expected) == sorted(get_unique_fake_format(entries))
688
689
690 def test_filter_latest():
691     orms = [('std.empty.get', '1.0.0'), ('std.unknown', '1.0.0'),
692             ('std.unknown', '1.0.1'), ('std.empty.get', '1.0.1')]
693
694     assert list(catalog._filter_latest(orms)) == [('std.empty.get', '1.0.1'), \
695             ('std.unknown', '1.0.1')]
696
697
698 def test_raise_if_duplicate():
699     class FakeOrig(object):
700         args = ["unique", "duplicate"]
701
702     url = "sqlite"
703     orig = FakeOrig()
704     error = IntegrityError("Error about uniqueness", None, orig)
705
706     with pytest.raises(catalog.DuplicateEntry):
707         catalog._raise_if_duplicate(url, error)
708
709     # Couldn't find psycopg2.IntegrityError constructor nor way
710     # to set pgcode so decided to mock it.
711     class FakeOrigPostgres(object):
712         pgcode = "23505"
713
714     url = "postgres"
715     orig = FakeOrigPostgres()
716     error = IntegrityError("Error about uniqueness", None, orig)
717
718     with pytest.raises(catalog.DuplicateEntry):
719         catalog._raise_if_duplicate(url, error)
720
721
722 def test_get_docker_image_from_spec():
723     assert "foo-image" == catalog._get_docker_image_from_spec(_c1_spec)
724
725 def test_get_cdap_jar_from_spec():
726     assert "bahpomet.com" == catalog._get_cdap_jar_from_spec(_cdap_spec)
727
728
729 def test_build_config_keys_map():
730     stub_spec = {
731           'streams': {
732               'publishes': [
733                   {'format': 'std.format_one', 'version': '1.0.0',
734                       'config_key': 'pub1', 'type': 'http'},
735                   {'format': 'std.format_one', 'version': '1.0.0',
736                       'config_key': 'pub2', 'type': 'message_router'}
737                   ],
738               'subscribes': [
739                   {'format': 'std.format_one', 'version': '1.0.0', 'route': '/sub1',
740                       'type': 'http'},
741                   {'format': 'std.format_one', 'version': '1.0.0',
742                       'config_key': 'sub2', 'type': 'message_router'}
743                   ]
744               },
745           'services': {
746               'calls': [
747                   {'request': {'format': 'std.format_one', 'version': '1.0.0'},
748                    'response': {'format': 'std.format_one', 'version': '1.0.0'},
749                    'config_key': 'call1'}
750                   ],
751               'provides': [
752                   {'request': {'format': 'std.format_one', 'version': '1.0.0'},
753                    'response': {'format': 'std.format_one', 'version': '1.0.0'},
754                    'route': '/prov1'}
755                   ]
756               }
757           }
758
759     grouping = catalog.build_config_keys_map(stub_spec)
760     expected = {'call1': {'group': 'services_calls'}, 'pub1': {'type': 'http', 'group': 'streams_publishes'}, 'sub2': {'type': 'message_router', 'group': 'streams_subscribes'}, 'pub2': {'type': 'message_router', 'group': 'streams_publishes'}}
761     assert expected == grouping
762
763
764 def test_get_data_router_subscriber_route():
765     spec = {"streams": {"subscribes": [ { "type": "data_router", "config_key":
766         "alpha", "route": "/alpha" }, { "type": "message_router", "config_key":
767         "beta" } ]}}
768
769     assert "/alpha" == catalog.get_data_router_subscriber_route(spec, "alpha")
770
771     with pytest.raises(catalog.MissingEntry):
772         catalog.get_data_router_subscriber_route(spec, "beta")
773
774     with pytest.raises(catalog.MissingEntry):
775         catalog.get_data_router_subscriber_route(spec, "gamma")
776
777
778 if __name__ == '__main__':
779     '''Test area'''
780     pytest.main([__file__, ])