blob: d10df1c94eed18f61cee95e6fa04a84ce5a72efc [file] [log] [blame]
Sean Condonf4f54a12018-10-10 23:25:46 +01001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the 'License');
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an 'AS IS' BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Sean Condonc13d9562019-04-18 13:24:42 +010016import {async, ComponentFixture, TestBed} from '@angular/core/testing';
Sean Condonf4f54a12018-10-10 23:25:46 +010017
Sean Condonc13d9562019-04-18 13:24:42 +010018import {ForceSvgComponent} from './forcesvg.component';
Sean Condon64060ff2019-05-30 15:48:11 +010019import {
20 FnService, IconService,
21 LionService,
22 LogService, SvgUtilService,
23 UrlFnService,
24 WebSocketService
25} from 'gui2-fw-lib';
Sean Condon0c577f62018-11-18 22:40:05 +000026import {DraggableDirective} from './draggable/draggable.directive';
27import {ActivatedRoute, Params} from '@angular/router';
28import {of} from 'rxjs';
Sean Condonff85fbe2019-03-16 14:28:46 +000029import {DeviceNodeSvgComponent} from './visuals/devicenodesvg/devicenodesvg.component';
30import {SubRegionNodeSvgComponent} from './visuals/subregionnodesvg/subregionnodesvg.component';
31import {HostNodeSvgComponent} from './visuals/hostnodesvg/hostnodesvg.component';
32import {LinkSvgComponent} from './visuals/linksvg/linksvg.component';
Sean Condonc13d9562019-04-18 13:24:42 +010033import {Device, Host, Link, LinkType, Region} from './models';
Sean Condon64060ff2019-05-30 15:48:11 +010034import {ChangeDetectorRef, SimpleChange} from '@angular/core';
35import {TopologyService} from '../../topology.service';
Sean Condon0c577f62018-11-18 22:40:05 +000036
37class MockActivatedRoute extends ActivatedRoute {
38 constructor(params: Params) {
39 super();
40 this.queryParams = of(params);
41 }
42}
43
Sean Condon64060ff2019-05-30 15:48:11 +010044class MockIconService {
45 loadIconDef() { }
46}
47
48class MockSvgUtilService {
49
50 cat7() {
51 const tcid = 'd3utilTestCard';
52
53 function getColor(id, muted, theme) {
54 // NOTE: since we are lazily assigning domain ids, we need to
55 // get the color from all 4 scales, to keep the domains
56 // in sync.
57 const ln = '#5b99d2';
58 const lm = '#9ebedf';
59 const dn = '#5b99d2';
60 const dm = '#9ebedf';
61 if (theme === 'dark') {
62 return muted ? dm : dn;
63 } else {
64 return muted ? lm : ln;
65 }
66 }
67
68 return {
69 // testCard: testCard,
70 getColor: getColor,
71 };
72 }
73}
74
75class MockUrlFnService { }
76
77class MockWebSocketService {
78 createWebSocket() { }
79 isConnected() { return false; }
80 unbindHandlers() { }
81 bindHandlers() { }
82}
83
84class MockTopologyService {
85 public instancesIndex: Map<string, number>;
86 constructor() {
87 this.instancesIndex = new Map();
88 }
89}
90
Sean Condonf4f54a12018-10-10 23:25:46 +010091describe('ForceSvgComponent', () => {
Sean Condon71910542019-02-16 18:16:42 +000092 let fs: FnService;
Sean Condon0c577f62018-11-18 22:40:05 +000093 let ar: MockActivatedRoute;
94 let windowMock: Window;
95 let logServiceSpy: jasmine.SpyObj<LogService>;
Sean Condonf4f54a12018-10-10 23:25:46 +010096 let component: ForceSvgComponent;
97 let fixture: ComponentFixture<ForceSvgComponent>;
Sean Condonb77768e2019-05-04 20:23:42 +010098 const openflowSampleData = require('./tests/test-module-topo2CurrentRegion.json');
99 const openflowRegionData: Region = <Region><unknown>(openflowSampleData.payload);
100
101 const odtnSampleData = require('./tests/test-OdtnConfig-topo2CurrentRegion.json');
102 const odtnRegionData: Region = <Region><unknown>(odtnSampleData.payload);
103
Sean Condonc13d9562019-04-18 13:24:42 +0100104 const emptyRegion: Region = <Region>{devices: [ [], [], [] ], hosts: [ [], [], [] ], links: []};
Sean Condonf4f54a12018-10-10 23:25:46 +0100105
Sean Condon64060ff2019-05-30 15:48:11 +0100106 beforeEach(() => {
Sean Condon0c577f62018-11-18 22:40:05 +0000107 const logSpy = jasmine.createSpyObj('LogService', ['info', 'debug', 'warn', 'error']);
108 ar = new MockActivatedRoute({ 'debug': 'txrx' });
109
110 windowMock = <any>{
111 location: <any>{
112 hostname: 'foo',
113 host: 'foo',
114 port: '80',
115 protocol: 'http',
116 search: { debug: 'true' },
117 href: 'ws://foo:123/onos/ui/websock/path',
118 absUrl: 'ws://foo:123/onos/ui/websock/path'
119 }
120 };
121
Sean Condon64060ff2019-05-30 15:48:11 +0100122 const bundleObj = {
123 'core.view.Topo': {
124 test: 'test1'
125 }
126 };
127 const mockLion = (key) => {
128 return bundleObj[key] || '%' + key + '%';
129 };
130
Sean Condon71910542019-02-16 18:16:42 +0000131 fs = new FnService(ar, logSpy, windowMock);
132
Sean Condonf4f54a12018-10-10 23:25:46 +0100133 TestBed.configureTestingModule({
Sean Condon0c577f62018-11-18 22:40:05 +0000134 declarations: [
135 ForceSvgComponent,
136 DeviceNodeSvgComponent,
137 HostNodeSvgComponent,
138 SubRegionNodeSvgComponent,
Sean Condon50855cf2018-12-23 15:37:42 +0000139 LinkSvgComponent,
Sean Condon64060ff2019-05-30 15:48:11 +0100140 DraggableDirective
Sean Condon0c577f62018-11-18 22:40:05 +0000141 ],
142 providers: [
143 { provide: LogService, useValue: logSpy },
Sean Condon64060ff2019-05-30 15:48:11 +0100144 { provide: ActivatedRoute, useValue: ar },
145 { provide: FnService, useValue: fs },
146 { provide: ChangeDetectorRef, useClass: ChangeDetectorRef },
147 { provide: UrlFnService, useClass: MockUrlFnService },
148 { provide: WebSocketService, useClass: MockWebSocketService },
149 { provide: LionService, useFactory: (() => {
150 return {
151 bundle: ((bundleId) => mockLion),
152 ubercache: new Array(),
153 loadCbs: new Map<string, () => void>([])
154 };
155 })
156 },
157 { provide: IconService, useClass: MockIconService },
158 { provide: SvgUtilService, useClass: MockSvgUtilService },
159 { provide: TopologyService, useClass: MockTopologyService },
Sean Condon71910542019-02-16 18:16:42 +0000160 { provide: 'Window', useValue: windowMock },
Sean Condon0c577f62018-11-18 22:40:05 +0000161 ]
Sean Condonf4f54a12018-10-10 23:25:46 +0100162 })
163 .compileComponents();
Sean Condon0c577f62018-11-18 22:40:05 +0000164 logServiceSpy = TestBed.get(LogService);
Sean Condonf4f54a12018-10-10 23:25:46 +0100165
Sean Condonf4f54a12018-10-10 23:25:46 +0100166 fixture = TestBed.createComponent(ForceSvgComponent);
Sean Condon0c577f62018-11-18 22:40:05 +0000167 component = fixture.debugElement.componentInstance;
Sean Condonf4f54a12018-10-10 23:25:46 +0100168 fixture.detectChanges();
169 });
170
171 it('should create', () => {
172 expect(component).toBeTruthy();
173 });
Sean Condonc13d9562019-04-18 13:24:42 +0100174
Sean Condonb77768e2019-05-04 20:23:42 +0100175 it('load sample files', () => {
176 expect(openflowSampleData).toBeTruthy();
177 expect(openflowSampleData.payload).toBeTruthy();
178 expect(openflowSampleData.payload.id).toBe('(root)');
179
180 expect(odtnSampleData).toBeTruthy();
181 expect(odtnSampleData.payload).toBeTruthy();
182 expect(odtnSampleData.payload.id).toBe('(root)');
Sean Condonc13d9562019-04-18 13:24:42 +0100183 });
184
185 it('should read sample data payload as Region', () => {
Sean Condonb77768e2019-05-04 20:23:42 +0100186 expect(openflowRegionData).toBeTruthy();
Sean Condonc13d9562019-04-18 13:24:42 +0100187 // console.log(regionData);
Sean Condonb77768e2019-05-04 20:23:42 +0100188 expect(openflowRegionData.id).toBe('(root)');
189 expect(openflowRegionData.devices).toBeTruthy();
190 expect(openflowRegionData.devices.length).toBe(3);
191 expect(openflowRegionData.devices[2].length).toBe(10);
192 expect(openflowRegionData.hosts.length).toBe(3);
193 expect(openflowRegionData.hosts[2].length).toBe(20);
194 expect(openflowRegionData.links.length).toBe(44);
Sean Condonc13d9562019-04-18 13:24:42 +0100195 });
196
197 it('should read device246 correctly', () => {
Sean Condonb77768e2019-05-04 20:23:42 +0100198 const device246: Device = openflowRegionData.devices[2][0];
Sean Condonc13d9562019-04-18 13:24:42 +0100199 expect(device246.id).toBe('of:0000000000000246');
200 expect(device246.nodeType).toBe('device');
201 expect(device246.type).toBe('switch');
202 expect(device246.online).toBe(true);
203 expect(device246.master).toBe('10.192.19.68');
204 expect(device246.layer).toBe('def');
205
206 expect(device246.props.managementAddress).toBe('10.192.19.69');
207 expect(device246.props.protocol).toBe('OF_13');
208 expect(device246.props.driver).toBe('ofdpa-ovs');
209 expect(device246.props.latitude).toBe('40.15');
210 expect(device246.props.name).toBe('s246');
211 expect(device246.props.locType).toBe('geo');
212 expect(device246.props.channelId).toBe('10.192.19.69:59980');
213 expect(device246.props.longitude).toBe('-121.679');
214
215 expect(device246.location.locType).toBe('geo');
216 expect(device246.location.latOrY).toBe(40.15);
217 expect(device246.location.longOrX).toBe(-121.679);
218 });
219
220 it('should read host 3 correctly', () => {
Sean Condonb77768e2019-05-04 20:23:42 +0100221 const host3: Host = openflowRegionData.hosts[2][0];
Sean Condonc13d9562019-04-18 13:24:42 +0100222 expect(host3.id).toBe('00:88:00:00:00:03/110');
223 expect(host3.nodeType).toBe('host');
224 expect(host3.layer).toBe('def');
225 expect(host3.configured).toBe(false);
226 expect(host3.ips.length).toBe(3);
227 expect(host3.ips[0]).toBe('fe80::288:ff:fe00:3');
228 expect(host3.ips[1]).toBe('2000::102');
229 expect(host3.ips[2]).toBe('10.0.1.2');
230 });
231
232 it('should read link 3-205 correctly', () => {
Sean Condonb77768e2019-05-04 20:23:42 +0100233 const link3_205: Link = openflowRegionData.links[0];
Sean Condonc13d9562019-04-18 13:24:42 +0100234 expect(link3_205.id).toBe('00:AA:00:00:00:03/None~of:0000000000000205/6');
235 expect(link3_205.epA).toBe('00:AA:00:00:00:03/None');
236 expect(link3_205.epB).toBe('of:0000000000000205');
237 expect(String(LinkType[link3_205.type])).toBe('2');
238 expect(link3_205.portA).toBe(undefined);
239 expect(link3_205.portB).toBe('6');
240
241 expect(link3_205.rollup).toBeTruthy();
242 expect(link3_205.rollup.length).toBe(1);
243 expect(link3_205.rollup[0].id).toBe('00:AA:00:00:00:03/None~of:0000000000000205/6');
244 expect(link3_205.rollup[0].epA).toBe('00:AA:00:00:00:03/None');
245 expect(link3_205.rollup[0].epB).toBe('of:0000000000000205');
246 expect(String(LinkType[link3_205.rollup[0].type])).toBe('2');
247 expect(link3_205.rollup[0].portA).toBe(undefined);
248 expect(link3_205.rollup[0].portB).toBe('6');
249
250 });
251
252 it('should handle regionData change - empty Region', () => {
253 component.ngOnChanges(
254 {'regionData' : new SimpleChange(<Region>{}, emptyRegion, true)});
255
256 expect(component.graph.nodes.length).toBe(0);
257 });
258
Sean Condonb77768e2019-05-04 20:23:42 +0100259 it('should know how to format names', () => {
260 expect(ForceSvgComponent.extractNodeName('00:AA:00:00:00:03/None', undefined))
Sean Condonc13d9562019-04-18 13:24:42 +0100261 .toEqual('00:AA:00:00:00:03/None');
262
Sean Condonb77768e2019-05-04 20:23:42 +0100263 expect(ForceSvgComponent.extractNodeName('00:AA:00:00:00:03/161', '161'))
264 .toEqual('00:AA:00:00:00:03');
Sean Condonc13d9562019-04-18 13:24:42 +0100265
Sean Condonb77768e2019-05-04 20:23:42 +0100266 // Like epB of first example in sampleData file - endPtStr contains port number
267 expect(ForceSvgComponent.extractNodeName('of:0000000000000206/6', '6'))
268 .toEqual('of:0000000000000206');
269
270 // Like epB of second example in sampleData file - endPtStr does not contain port number
271 expect(ForceSvgComponent.extractNodeName('of:0000000000000206', '6'))
Sean Condonc13d9562019-04-18 13:24:42 +0100272 .toEqual('of:0000000000000206');
273 });
274
Sean Condonb77768e2019-05-04 20:23:42 +0100275 it('should handle openflow regionData change - sample Region', () => {
276 component.regionData = openflowRegionData;
Sean Condonc13d9562019-04-18 13:24:42 +0100277 component.ngOnChanges(
Sean Condonb77768e2019-05-04 20:23:42 +0100278 {'regionData' : new SimpleChange(<Region>{}, openflowRegionData, true)});
Sean Condonc13d9562019-04-18 13:24:42 +0100279
280 expect(component.graph.nodes.length).toBe(30);
281
282 expect(component.graph.links.length).toBe(44);
283
284 });
Sean Condonb77768e2019-05-04 20:23:42 +0100285
286 it('should handle odtn regionData change - sample odtn Region', () => {
287 component.regionData = odtnRegionData;
288 component.ngOnChanges(
289 {'regionData' : new SimpleChange(<Region>{}, odtnRegionData, true)});
290
291 expect(component.graph.nodes.length).toBe(2);
292
293 expect(component.graph.links.length).toBe(6);
294
295 });
Sean Condonf4f54a12018-10-10 23:25:46 +0100296});