blob: fb8f42c30664cdf4c73dd688c8294edd825f735b [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 Condon71910542019-02-16 18:16:42 +000029import {MapSvgComponent} from '../mapsvg/mapsvg.component';
Sean Condonff85fbe2019-03-16 14:28:46 +000030import {DeviceNodeSvgComponent} from './visuals/devicenodesvg/devicenodesvg.component';
31import {SubRegionNodeSvgComponent} from './visuals/subregionnodesvg/subregionnodesvg.component';
32import {HostNodeSvgComponent} from './visuals/hostnodesvg/hostnodesvg.component';
33import {LinkSvgComponent} from './visuals/linksvg/linksvg.component';
Sean Condonc13d9562019-04-18 13:24:42 +010034import {Device, Host, Link, LinkType, Region} from './models';
Sean Condon64060ff2019-05-30 15:48:11 +010035import {ChangeDetectorRef, SimpleChange} from '@angular/core';
36import {TopologyService} from '../../topology.service';
Sean Condon0c577f62018-11-18 22:40:05 +000037
38class MockActivatedRoute extends ActivatedRoute {
39 constructor(params: Params) {
40 super();
41 this.queryParams = of(params);
42 }
43}
44
Sean Condon64060ff2019-05-30 15:48:11 +010045class MockIconService {
46 loadIconDef() { }
47}
48
49class MockSvgUtilService {
50
51 cat7() {
52 const tcid = 'd3utilTestCard';
53
54 function getColor(id, muted, theme) {
55 // NOTE: since we are lazily assigning domain ids, we need to
56 // get the color from all 4 scales, to keep the domains
57 // in sync.
58 const ln = '#5b99d2';
59 const lm = '#9ebedf';
60 const dn = '#5b99d2';
61 const dm = '#9ebedf';
62 if (theme === 'dark') {
63 return muted ? dm : dn;
64 } else {
65 return muted ? lm : ln;
66 }
67 }
68
69 return {
70 // testCard: testCard,
71 getColor: getColor,
72 };
73 }
74}
75
76class MockUrlFnService { }
77
78class MockWebSocketService {
79 createWebSocket() { }
80 isConnected() { return false; }
81 unbindHandlers() { }
82 bindHandlers() { }
83}
84
85class MockTopologyService {
86 public instancesIndex: Map<string, number>;
87 constructor() {
88 this.instancesIndex = new Map();
89 }
90}
91
Sean Condonf4f54a12018-10-10 23:25:46 +010092describe('ForceSvgComponent', () => {
Sean Condon71910542019-02-16 18:16:42 +000093 let fs: FnService;
Sean Condon0c577f62018-11-18 22:40:05 +000094 let ar: MockActivatedRoute;
95 let windowMock: Window;
96 let logServiceSpy: jasmine.SpyObj<LogService>;
Sean Condonf4f54a12018-10-10 23:25:46 +010097 let component: ForceSvgComponent;
98 let fixture: ComponentFixture<ForceSvgComponent>;
Sean Condonc13d9562019-04-18 13:24:42 +010099 const sampledata = require('./tests/test-module-topo2CurrentRegion.json');
100 const regionData: Region = <Region><unknown>(sampledata.payload);
101 const emptyRegion: Region = <Region>{devices: [ [], [], [] ], hosts: [ [], [], [] ], links: []};
Sean Condonf4f54a12018-10-10 23:25:46 +0100102
Sean Condon64060ff2019-05-30 15:48:11 +0100103 beforeEach(() => {
Sean Condon0c577f62018-11-18 22:40:05 +0000104 const logSpy = jasmine.createSpyObj('LogService', ['info', 'debug', 'warn', 'error']);
105 ar = new MockActivatedRoute({ 'debug': 'txrx' });
106
107 windowMock = <any>{
108 location: <any>{
109 hostname: 'foo',
110 host: 'foo',
111 port: '80',
112 protocol: 'http',
113 search: { debug: 'true' },
114 href: 'ws://foo:123/onos/ui/websock/path',
115 absUrl: 'ws://foo:123/onos/ui/websock/path'
116 }
117 };
118
Sean Condon64060ff2019-05-30 15:48:11 +0100119 const bundleObj = {
120 'core.view.Topo': {
121 test: 'test1'
122 }
123 };
124 const mockLion = (key) => {
125 return bundleObj[key] || '%' + key + '%';
126 };
127
Sean Condon71910542019-02-16 18:16:42 +0000128 fs = new FnService(ar, logSpy, windowMock);
129
Sean Condonf4f54a12018-10-10 23:25:46 +0100130 TestBed.configureTestingModule({
Sean Condon0c577f62018-11-18 22:40:05 +0000131 declarations: [
132 ForceSvgComponent,
133 DeviceNodeSvgComponent,
134 HostNodeSvgComponent,
135 SubRegionNodeSvgComponent,
Sean Condon50855cf2018-12-23 15:37:42 +0000136 LinkSvgComponent,
Sean Condon64060ff2019-05-30 15:48:11 +0100137 DraggableDirective
Sean Condon0c577f62018-11-18 22:40:05 +0000138 ],
139 providers: [
140 { provide: LogService, useValue: logSpy },
Sean Condon64060ff2019-05-30 15:48:11 +0100141 { provide: ActivatedRoute, useValue: ar },
142 { provide: FnService, useValue: fs },
143 { provide: ChangeDetectorRef, useClass: ChangeDetectorRef },
144 { provide: UrlFnService, useClass: MockUrlFnService },
145 { provide: WebSocketService, useClass: MockWebSocketService },
146 { provide: LionService, useFactory: (() => {
147 return {
148 bundle: ((bundleId) => mockLion),
149 ubercache: new Array(),
150 loadCbs: new Map<string, () => void>([])
151 };
152 })
153 },
154 { provide: IconService, useClass: MockIconService },
155 { provide: SvgUtilService, useClass: MockSvgUtilService },
156 { provide: TopologyService, useClass: MockTopologyService },
Sean Condon71910542019-02-16 18:16:42 +0000157 { provide: 'Window', useValue: windowMock },
Sean Condon0c577f62018-11-18 22:40:05 +0000158 ]
Sean Condonf4f54a12018-10-10 23:25:46 +0100159 })
160 .compileComponents();
Sean Condon0c577f62018-11-18 22:40:05 +0000161 logServiceSpy = TestBed.get(LogService);
Sean Condonf4f54a12018-10-10 23:25:46 +0100162
Sean Condonf4f54a12018-10-10 23:25:46 +0100163 fixture = TestBed.createComponent(ForceSvgComponent);
Sean Condon0c577f62018-11-18 22:40:05 +0000164 component = fixture.debugElement.componentInstance;
Sean Condonf4f54a12018-10-10 23:25:46 +0100165 fixture.detectChanges();
166 });
167
168 it('should create', () => {
169 expect(component).toBeTruthy();
170 });
Sean Condonc13d9562019-04-18 13:24:42 +0100171
172 it('load sample file', () => {
173 expect(sampledata).toBeTruthy();
174 expect(sampledata.payload).toBeTruthy();
175 expect(sampledata.payload.id).toBe('(root)');
176 });
177
178 it('should read sample data payload as Region', () => {
179 expect(regionData).toBeTruthy();
180 // console.log(regionData);
181 expect(regionData.id).toBe('(root)');
182 expect(regionData.devices).toBeTruthy();
183 expect(regionData.devices.length).toBe(3);
184 expect(regionData.devices[2].length).toBe(10);
185 expect(regionData.hosts.length).toBe(3);
186 expect(regionData.hosts[2].length).toBe(20);
187 expect(regionData.links.length).toBe(44);
188 });
189
190 it('should read device246 correctly', () => {
191 const device246: Device = regionData.devices[2][0];
192 expect(device246.id).toBe('of:0000000000000246');
193 expect(device246.nodeType).toBe('device');
194 expect(device246.type).toBe('switch');
195 expect(device246.online).toBe(true);
196 expect(device246.master).toBe('10.192.19.68');
197 expect(device246.layer).toBe('def');
198
199 expect(device246.props.managementAddress).toBe('10.192.19.69');
200 expect(device246.props.protocol).toBe('OF_13');
201 expect(device246.props.driver).toBe('ofdpa-ovs');
202 expect(device246.props.latitude).toBe('40.15');
203 expect(device246.props.name).toBe('s246');
204 expect(device246.props.locType).toBe('geo');
205 expect(device246.props.channelId).toBe('10.192.19.69:59980');
206 expect(device246.props.longitude).toBe('-121.679');
207
208 expect(device246.location.locType).toBe('geo');
209 expect(device246.location.latOrY).toBe(40.15);
210 expect(device246.location.longOrX).toBe(-121.679);
211 });
212
213 it('should read host 3 correctly', () => {
214 const host3: Host = regionData.hosts[2][0];
215 expect(host3.id).toBe('00:88:00:00:00:03/110');
216 expect(host3.nodeType).toBe('host');
217 expect(host3.layer).toBe('def');
218 expect(host3.configured).toBe(false);
219 expect(host3.ips.length).toBe(3);
220 expect(host3.ips[0]).toBe('fe80::288:ff:fe00:3');
221 expect(host3.ips[1]).toBe('2000::102');
222 expect(host3.ips[2]).toBe('10.0.1.2');
223 });
224
225 it('should read link 3-205 correctly', () => {
226 const link3_205: Link = regionData.links[0];
227 expect(link3_205.id).toBe('00:AA:00:00:00:03/None~of:0000000000000205/6');
228 expect(link3_205.epA).toBe('00:AA:00:00:00:03/None');
229 expect(link3_205.epB).toBe('of:0000000000000205');
230 expect(String(LinkType[link3_205.type])).toBe('2');
231 expect(link3_205.portA).toBe(undefined);
232 expect(link3_205.portB).toBe('6');
233
234 expect(link3_205.rollup).toBeTruthy();
235 expect(link3_205.rollup.length).toBe(1);
236 expect(link3_205.rollup[0].id).toBe('00:AA:00:00:00:03/None~of:0000000000000205/6');
237 expect(link3_205.rollup[0].epA).toBe('00:AA:00:00:00:03/None');
238 expect(link3_205.rollup[0].epB).toBe('of:0000000000000205');
239 expect(String(LinkType[link3_205.rollup[0].type])).toBe('2');
240 expect(link3_205.rollup[0].portA).toBe(undefined);
241 expect(link3_205.rollup[0].portB).toBe('6');
242
243 });
244
245 it('should handle regionData change - empty Region', () => {
246 component.ngOnChanges(
247 {'regionData' : new SimpleChange(<Region>{}, emptyRegion, true)});
248
249 expect(component.graph.nodes.length).toBe(0);
250 });
251
252 it('should know hwo to format names', () => {
253 expect(ForceSvgComponent.extractNodeName('00:AA:00:00:00:03/None'))
254 .toEqual('00:AA:00:00:00:03/None');
255
256 expect(ForceSvgComponent.extractNodeName('00:AA:00:00:00:03/161'))
257 .toEqual('00:AA:00:00:00:03/161');
258
259 expect(ForceSvgComponent.extractNodeName('of:0000000000000206/6'))
260 .toEqual('of:0000000000000206');
261 });
262
263 it('should handle regionData change - sample Region', () => {
264 component.regionData = regionData;
265 component.ngOnChanges(
266 {'regionData' : new SimpleChange(<Region>{}, regionData, true)});
267
268 expect(component.graph.nodes.length).toBe(30);
269
270 expect(component.graph.links.length).toBe(44);
271
272 });
Sean Condonf4f54a12018-10-10 23:25:46 +0100273});