Catalog alignment
[sdc.git] / catalog-ui / src / app / ng2 / pages / composition / graph / utils / match-capability-requierment-utils.spec.ts
1 import { ComponentFixture, TestBed } from '@angular/core/testing';
2 import { Mock } from 'ts-mockery';
3 import {
4     CapabilitiesGroup,
5     Capability, ComponentInstance, CompositionCiLinkBase, CompositionCiNodeBase, CompositionCiNodeCp,
6     CompositionCiNodeVf, CompositionCiNodeVl,
7     Requirement, RequirementsGroup
8 } from '../../../../../models';
9 import { MatchCapabilitiesRequirementsUtils } from './match-capability-requierment-utils';
10
11 describe('match capability requirements utils service ', () => {
12
13     const bindableReq = Mock.of<Requirement>({
14         capability : 'tosca.capabilities.network.Bindable',
15         name: 'virtualBinding',
16         relationship: 'tosca.relationships.network.BindsTo',
17         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.virtualBinding',
18         ownerId : 'extcp0',
19         ownerName : 's'
20     });
21
22     const virtualLinkReq = Mock.of<Requirement>({
23         capability: 'tosca.capabilities.network.Linkable',
24         name: 'virtualLink',
25         relationship: 'tosca.relationships.network.LinksTo',
26         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.virtualLink',
27         ownerId : '',
28         ownerName : 's'
29     });
30
31     const storeAttachmentReq = Mock.of<Requirement>({
32         capability: 'tosca.capabilities.Attachment',
33         name: 'local_storage',
34         relationship: 'tosca.relationships.AttachesTo',
35         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.local_storage',
36         node: 'tosca.nodes.BlockStorage',
37         ownerId : '',
38         ownerName : 's'
39     });
40
41     const vlAttachmentReq = Mock.of<Requirement>({
42         capability: 'tosca.capabilities.Attachment',
43         name: 'local_storage',
44         relationship: 'tosca.relationships.AttachesTo',
45         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.local_storage',
46         node: 'tosca.nodes.BlockStorage',
47         ownerId : '',
48         ownerName : 's'
49     });
50
51     const extVirtualLinkReq = Mock.of<Requirement>({
52         capability: 'tosca.capabilities.network.Linkable',
53         name: 'external_virtualLink',
54         relationship: 'tosca.relationships.network.LinksTo',
55         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.external_virtualLink'
56     });
57
58     const dependencyReq = Mock.of<Requirement>({
59         capability: 'tosca.capabilities.Node',
60         name: 'dependency',
61         relationship: 'tosca.relationships.DependsOn',
62         uniqueId: 'eef99154-8039-4227-ba68-62a32e6b0d98.dependency'
63     });
64
65     const featureCap = Mock.of<Capability>({
66         type: 'tosca.capabilities.Node',
67         name: 'feature',
68         uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.feature',
69         maxOccurrences: 'UNBOUNDED',
70         minOccurrences: '1'
71     });
72
73     const internalConnPointCap = Mock.of<Capability>({
74         type: 'tosca.capabilities.Node',
75         name: 'internal_connectionPoint',
76         capabilitySources : ['org.openecomp.resource.cp.extCP'],
77         uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.internal_connectionPoint',
78         maxOccurrences: 'UNBOUNDED',
79         minOccurrences: '1'
80     });
81
82     const blockStoreAttachmentCap = Mock.of<Capability>({
83         type: 'tosca.capabilities.Attachment',
84         name: 'attachment',
85         capabilitySources: ['tosca.nodes.BlockStorage'],
86         uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.attachment',
87         maxOccurrences: 'UNBOUNDED',
88         minOccurrences: '1'
89     });
90
91     const bindingCap = Mock.of<Capability>({
92         type: 'tosca.capabilities.network.Bindable',
93         name: 'binding',
94         capabilitySources: ['tosca.nodes.Compute'],
95         uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.binding',
96         maxOccurrences: 'UNBOUNDED',
97         minOccurrences: '1',
98     });
99
100     const linkableCap = Mock.of<Capability>({
101         type: 'tosca.capabilities.network.Linkable',
102         capabilitySources: ['org.openecomp.resource.vl.extVL'],
103         uniqueId: 'capability.ddf1301e-866b-4fa3-bc4f-edbd81e532cd.virtual_linkable',
104         maxOccurrences: 'UNBOUNDED',
105         minOccurrences: '1'
106     });
107
108     const nodeCompute = Mock.of<CompositionCiNodeVf>({
109         name: 'Compute 0',
110         componentInstance: Mock.of<ComponentInstance>({
111             componentName: 'Compute',
112             uniqueId : 'compute0',
113             requirements: Mock.of<RequirementsGroup>({
114                 'tosca.capabilities.Node' : [ dependencyReq ],
115                 'tosca.capabilities.Attachment' : [ storeAttachmentReq ]
116             }),
117             capabilities: Mock.of<CapabilitiesGroup>({
118                 'tosca.capabilities.network.Bindable' : [ bindingCap ],
119                 'tosca.capabilities.Node' : [ featureCap ]
120             })
121         })
122     });
123
124     const nodeBlockStorage = Mock.of<CompositionCiNodeVf>({
125         name: 'BlockStorage 0',
126         componentInstance: Mock.of<ComponentInstance>({
127             componentName: 'BlockStorage',
128             uniqueId : 'blockstorage0',
129             requirements: Mock.of<RequirementsGroup>({
130                 'tosca.capabilities.Node' : [ dependencyReq ]
131             }),
132             capabilities: Mock.of<CapabilitiesGroup>({
133                 'tosca.capabilities.Attachment' : [ blockStoreAttachmentCap ],
134                 'tosca.capabilities.Node' : [ featureCap ]
135             })
136         })
137     });
138
139     const nodeVl = Mock.of<CompositionCiNodeVl>({
140         name: 'ExtVL 0',
141         componentInstance: Mock.of<ComponentInstance>({
142             componentName: 'BlockStorage',
143             uniqueId : 'extvl0',
144             requirements: Mock.of<RequirementsGroup>({
145                 'tosca.capabilities.Node' : [ dependencyReq ]
146             }),
147             capabilities: Mock.of<CapabilitiesGroup>({
148                 'tosca.capabilities.network.Linkable' : [ linkableCap ],
149                 'tosca.capabilities.Node' : [ featureCap ]
150             })
151         })
152     });
153
154     const nodeCp = Mock.of<CompositionCiNodeCp>({
155         name: 'ExtCP 0',
156         componentInstance: Mock.of<ComponentInstance>({
157             componentName: 'ExtCP',
158             uniqueId : 'extcp0',
159             requirements: Mock.of<RequirementsGroup>({
160                 'tosca.capabilities.network.Linkable' : [ virtualLinkReq ],
161                 'tosca.capabilities.network.Bindable' : [ bindableReq ]
162             }),
163             capabilities: Mock.of<CapabilitiesGroup>({
164                 'tosca.capabilities.Node' : [ featureCap ]
165             })
166         })
167     });
168
169     let service: MatchCapabilitiesRequirementsUtils;
170
171     beforeEach(() => {
172         TestBed.configureTestingModule({
173             imports: [],
174             providers: [MatchCapabilitiesRequirementsUtils]
175         });
176
177         service = TestBed.get(MatchCapabilitiesRequirementsUtils);
178     });
179
180     it('match capability requirements utils should be defined', () => {
181         console.log(JSON.stringify(service));
182         expect(service).toBeDefined();
183     });
184
185     describe('isMatch function ', () => {
186
187         it('capability type not equal to requirement capability, match is false', () => {
188             const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable11'});
189             const capability = Mock.of<Capability>({type: 'tosca.capabilities.network.Linkable'});
190             expect(service.isMatch(requirement, capability)).toBeFalsy();
191         });
192
193         it('capability type equal to requirement capability and requirement node not exist, match is true', () => {
194             const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable'});
195             const capability = Mock.of<Capability>({type: 'tosca.capabilities.network.Linkable'});
196             expect(service.isMatch(requirement, capability)).toBeTruthy();
197         });
198
199         it('is match - capability type equal to requirement capability and requirement node exist and includes in capability sources, match is true', () => {
200             const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable', node: 'node1'});
201             const capability = Mock.of<Capability>({
202                 type: 'tosca.capabilities.network.Linkable',
203                 capabilitySources: ['node1', 'node2', 'node3']
204             });
205             expect(service.isMatch(requirement, capability)).toBeTruthy();
206         });
207
208         it('no match - capability type equal to requirement capability and requirement node but not includes in capability sources, match is false', () => {
209             const requirement = Mock.of<Requirement>({capability: 'tosca.capabilities.network.Linkable', node: 'node4'});
210             const capability = Mock.of<Capability>({
211                 type: 'tosca.capabilities.network.Linkable',
212                 capabilitySources: ['node1', 'node2', 'node3']
213             });
214             expect(service.isMatch(requirement, capability)).toBeFalsy();
215         });
216     });
217
218     describe('hasUnfulfilledRequirementContainingMatch function ', () => {
219
220         it('node have no componentInstance, return false', () => {
221             const node = Mock.of<CompositionCiNodeVf>({componentInstance: undefined});
222             expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeFalsy();
223         });
224
225         it('node have componentInstance data but no unfulfilled requirements, return false', () => {
226             const node = Mock.of<CompositionCiNodeVf>({componentInstance: Mock.of<ComponentInstance>()});
227             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([]);
228             expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeFalsy();
229         });
230
231         it('node have componentInstance data and unfulfilled requirements but no match found, return false', () => {
232             const node = Mock.of<CompositionCiNodeVf>({componentInstance: Mock.of<ComponentInstance>()});
233             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
234             jest.spyOn(service, 'containsMatch').mockReturnValue(false);
235             expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeFalsy();
236         });
237
238         it('node have componentInstance data with unfulfilled requirements and match found, return true', () => {
239             const node = Mock.of<CompositionCiNodeVf>({componentInstance: Mock.of<ComponentInstance>()});
240             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
241             jest.spyOn(service, 'containsMatch').mockReturnValue(true);
242             expect(service.hasUnfulfilledRequirementContainingMatch(node, [], {}, [])).toBeTruthy();
243         });
244     });
245
246     describe('getMatches function ', () => {
247         let fromId: string;
248         let toId: string;
249
250         beforeEach(() => {
251             fromId = 'from_id';
252             toId = 'to_id';
253         });
254
255         it('node have no unfulfilled requirements, return empty match array', () => {
256             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([]);
257             expect(service.getMatches({}, {}, [], fromId, toId, true)).toHaveLength(0);
258         });
259
260         it('node have unfulfilled requirements but no capabilities, return empty match array', () => {
261             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
262             expect(service.getMatches({}, {}, [], fromId, toId, true)).toHaveLength(0);
263         });
264
265         it('node have unfulfilled requirements and capabilities but no match found, return empty match array', () => {
266             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
267             jest.spyOn(service, 'isMatch').mockReturnValue(false);
268             expect(service.getMatches({}, {}, [], fromId, toId, true)).toHaveLength(0);
269         });
270
271         it('node have 2 unfulfilled requirements and 2 capabilities and match found, return 4 matches', () => {
272             jest.spyOn(service, 'getUnfulfilledRequirements').mockReturnValue([Mock.of<Requirement>(), Mock.of<Requirement>()]);
273             const capabilities = {aaa: Mock.of<Capability>(), bbb: Mock.of<Capability>()};
274             jest.spyOn(service, 'isMatch').mockReturnValue(true);
275             expect(service.getMatches({}, capabilities, [], fromId, toId, true)).toHaveLength(4);
276         });
277     });
278
279     describe('Find matching nodes ===>', () => {
280
281        it('should find matching nodes with component instance', () => {
282            const nodes = [ nodeBlockStorage, nodeCompute, nodeVl ];
283            let matchingNodes: any;
284
285            // Compute can connect to Block Store
286            matchingNodes = service.findMatchingNodesToComponentInstance(nodeCompute.componentInstance, nodes, []);
287            expect(matchingNodes).toHaveLength(1);
288            expect(matchingNodes).toContain(nodeBlockStorage);
289
290            // Block Storage can connect to Compute
291            matchingNodes = service.findMatchingNodesToComponentInstance(nodeBlockStorage.componentInstance, nodes, []);
292            expect(matchingNodes).toHaveLength(1);
293            expect(matchingNodes).toContain(nodeCompute);
294
295            // Vl has no matches
296            matchingNodes = service.findMatchingNodesToComponentInstance(nodeVl.componentInstance, nodes, []);
297            expect(matchingNodes).toHaveLength(0);
298
299            // CP should be able to connect to VL and Compute
300            matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, []);
301            expect(matchingNodes).toHaveLength(2);
302            expect(matchingNodes).toContain(nodeCompute);
303            expect(matchingNodes).toContain(nodeVl);
304        });
305
306        it('try with empty list of nodes', () => {
307             const nodes = [ ];
308             let matchingNodes: any;
309
310             // Compute can connect to Block Store
311             matchingNodes = service.findMatchingNodesToComponentInstance(nodeCompute.componentInstance, nodes, []);
312             expect(matchingNodes).toHaveLength(0);
313         });
314
315        it('should detect fulfilled connection with compute node', () => {
316             const nodes = [ nodeBlockStorage, nodeCompute, nodeVl ];
317             let matchingNodes: any;
318             const link = {
319                 relation: {
320                     fromNode: 'extcp0',
321                     toNode: 'compute0',
322                     relationships: [{
323                         relation: {
324                             requirementOwnerId: 'extcp0',
325                             requirement: 'virtualBinding',
326                             relationship: {
327                                 type: 'tosca.relationships.network.BindsTo'
328                             }
329
330                         }
331                     }]
332                 }
333             };
334
335             const links = [link];
336             // CP should be able to connect to VL only since it already has a link with compute
337             matchingNodes = service.findMatchingNodesToComponentInstance(nodeCp.componentInstance, nodes, links as CompositionCiLinkBase[]);
338             expect(matchingNodes).toHaveLength(1);
339             expect(matchingNodes).toContain(nodeVl);
340         });
341     });
342 });