blob: a0d488b4e945f3d503a21ddbf6fa7a5276087c4f [file] [log] [blame]
Simon Hunt3a6eec02015-02-09 21:16:43 -08001/*
2 * Copyright 2015 Open Networking Laboratory
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 */
16
17/*
18 ONOS GUI -- Topo View -- Topo Model Service - Unit Tests
19 */
20describe('factory: view/topo/topoModel.js', function() {
21 var $log, fs, rnd, tms;
22
23 // stop random numbers from being quite so random
24 var mockRandom = {
25 // mock spread returns s + 1
26 spread: function (s) {
27 return s + 1;
28 },
29 // mock random dimension returns d / 2 - 1
30 randDim: function (d) {
31 return d/2 - 1;
32 },
33 mock: 'yup'
34 };
35
36 // to mock out the [lng,lat] <=> [x,y] transformations, we will
37 // add/subtract 2000, 3000 respectively:
38 // lng:2005 === x:5, lat:3004 === y:4
39
40 var mockProjection = function (lnglat) {
41 return [lnglat[0] - 2000, lnglat[1] - 3000];
42 };
43
44 mockProjection.invert = function (xy) {
45 return [xy[0] + 2000, xy[1] + 3000];
46 };
47
48 // our test device lookup
49 var lu = {
50 dev1: {
51 'class': 'device',
52 id: 'dev1',
53 x: 17,
54 y: 27,
55 online: true
56 },
57 dev2: {
58 'class': 'device',
59 id: 'dev2',
60 x: 18,
61 y: 28,
62 online: true
63 },
64 host1: {
65 'class': 'host',
66 id: 'host1',
67 x: 23,
68 y: 33,
69 cp: {
70 device: 'dev1',
71 port: 7
72 },
73 ingress: 'dev1/7-host1'
74 },
75 host2: {
76 'class': 'host',
77 id: 'host2',
78 x: 24,
79 y: 34,
80 cp: {
81 device: 'dev0',
82 port: 0
83 },
84 ingress: 'dev0/0-host2'
85 }
86 };
87
88 // our test api
89 var api = {
90 projection: function () { return mockProjection; },
91 lookup: lu
92 };
93
94 // our test dimensions and well known locations..
95 var dim = [20, 40],
96 randLoc = [9, 19], // random location using randDim(): d/2-1
97 randHostLoc = [40, 50], // host "near" random location
98 // given that 'nearDist' = 15
99 // and spread(15) = 16
100 // 9 + 15 + 16 = 40; 19 + 15 + 16 = 50
101 nearDev1 = [48,58], // [17+15+16, 27+15+16]
102 dev1Loc = [17,27],
103 dev2Loc = [18,28],
104 host1Loc = [23,33],
105 host2Loc = [24,34];
106
107 // implement some custom matchers...
108 beforeEach(function () {
109 jasmine.addMatchers({
110 toBePositionedAt: function () {
111 return {
112 compare: function (actual, xy) {
113 var result = {},
114 actCoord = [actual.x, actual.y];
115
116 result.pass = (actual.x === xy[0]) && (actual.y === xy[1]);
117
118 if (result.pass) {
119 // for negation with ".not"
120 result.message = 'Expected [' + actCoord +
121 '] NOT to be positioned at [' + xy + ']';
122 } else {
123 result.message = 'Expected [' + actCoord +
124 '] to be positioned at [' + xy + ']';
125 }
126 return result;
127 }
128 }
129 },
130 toHaveEndPoints: function () {
131 return {
132 compare: function (actual, xy1, xy2) {
133 var result = {};
134
135 result.pass = (actual.x1 === xy1[0]) && (actual.y1 === xy1[1]) &&
136 (actual.x2 === xy2[0]) && (actual.y2 === xy2[1]);
137
138 if (result.pass) {
139 // for negation with ".not"
140 result.message = 'Expected ' + actual +
141 ' NOT to have endpoints [' + xy1 + ']-[' + xy2 + ']';
142 } else {
143 result.message = 'Expected ' + actual +
144 ' to have endpoints [' + xy1 + ']-[' + xy2 + ']';
145 }
146 return result;
147 }
148 }
149 },
150 toBeFixed: function () {
151 return {
152 compare: function (actual) {
153 var result = {
154 pass: actual.fixed
155 };
156 if (result.pass) {
157 result.message = 'Expected ' + actual +
158 ' NOT to be fixed!';
159 } else {
160 result.message = 'Expected ' + actual +
161 ' to be fixed!';
162 }
163 return result;
164 }
165 }
166 }
167 });
168 });
169
170 beforeEach(module('ovTopo', 'onosUtil'));
171
172 beforeEach(function () {
173 module(function ($provide) {
174 $provide.value('RandomService', mockRandom);
175 });
176 });
177
178 beforeEach(inject(function (_$log_, FnService, RandomService, TopoModelService) {
179 $log = _$log_;
180 fs = FnService;
181 rnd = RandomService;
182 tms = TopoModelService;
183 tms.initModel(api, dim);
184 }));
185
186
187 it('should install the mock random service', function () {
188 expect(rnd.mock).toBe('yup');
189 expect(rnd.spread(4)).toBe(5);
190 expect(rnd.randDim(8)).toBe(3);
191 });
192
193 it('should install the mock projection', function () {
194 expect(tms.coordFromLngLat({lng: 2005, lat: 3004})).toEqual([5,4]);
195 expect(tms.lngLatFromCoord([5,4])).toEqual([2005,3004]);
196 });
197
198 it('should define TopoModelService', function () {
199 expect(tms).toBeDefined();
200 });
201
202 it('should define api functions', function () {
203 expect(fs.areFunctions(tms, [
204 'initModel', 'newDim',
205 'positionNode', 'createDeviceNode', 'createHostNode',
206 'createHostLink', 'createLink',
207 'coordFromLngLat', 'lngLatFromCoord'
208 ])).toBeTruthy();
209 });
210
211 // === unit tests for positionNode()
212
213 it('should position a node using meta x/y', function () {
214 var node = {
215 metaUi: { x:37, y:48 }
216 };
217 tms.positionNode(node);
218 expect(node).toBePositionedAt([37,48]);
219 expect(node).toBeFixed();
220 });
221
222 it('should position a node by translating lng/lat', function () {
223 var node = {
224 location: {
225 type: 'latlng',
226 lng: 2008,
227 lat: 3009
228 }
229 };
230 tms.positionNode(node);
231 expect(node).toBePositionedAt([8,9]);
232 expect(node).toBeFixed();
233 });
234
235 it('should position a device with no location randomly', function () {
236 var node = { 'class': 'device' };
237 tms.positionNode(node);
238 expect(node).toBePositionedAt(randLoc);
239 expect(node).not.toBeFixed();
240 });
241
242 it('should position a device randomly even if x/y set', function () {
243 var node = { 'class': 'device', x: 1, y: 2 };
244 tms.positionNode(node);
245 expect(node).toBePositionedAt(randLoc);
246 expect(node).not.toBeFixed();
247 });
248
249 it('should NOT reposition a device randomly on update', function () {
250 var node = { 'class': 'device', x: 1, y: 2 };
251 tms.positionNode(node, true);
252 expect(node).toBePositionedAt([1,2]);
253 expect(node).not.toBeFixed();
254 });
255
256 it('should position a host close to its device', function () {
257 var node = { 'class': 'host', cp: { device: 'dev1' } };
258 tms.positionNode(node);
259
260 // note: nearDist is 15; spread(15) adds 16; dev1 at [17,27]
261
262 expect(node).toBePositionedAt(nearDev1);
263 expect(node).not.toBeFixed();
264 });
265
266 it('should randomize host with no assoc device', function () {
267 var node = { 'class': 'host', cp: { device: 'dev0' } };
268 tms.positionNode(node);
269
270 // note: no device gives 'rand loc' [9,19]
271 // nearDist is 15; spread(15) adds 16
272
273 expect(node).toBePositionedAt(randHostLoc);
274 expect(node).not.toBeFixed();
275 });
276
277 // === unit tests for createDeviceNode()
278
279 it('should create a basic device node', function () {
280 var node = tms.createDeviceNode({ id: 'foo' });
281 expect(node).toBePositionedAt(randLoc);
282 expect(node).not.toBeFixed();
283 expect(node.class).toEqual('device');
284 expect(node.svgClass).toEqual('node device');
285 expect(node.id).toEqual('foo');
286 });
287
288 it('should create device node with type', function () {
289 var node = tms.createDeviceNode({ id: 'foo', type: 'cool' });
290 expect(node).toBePositionedAt(randLoc);
291 expect(node).not.toBeFixed();
292 expect(node.class).toEqual('device');
293 expect(node.svgClass).toEqual('node device cool');
294 expect(node.id).toEqual('foo');
295 });
296
297 it('should create online device node with type', function () {
298 var node = tms.createDeviceNode({ id: 'foo', type: 'cool', online: true });
299 expect(node).toBePositionedAt(randLoc);
300 expect(node).not.toBeFixed();
301 expect(node.class).toEqual('device');
302 expect(node.svgClass).toEqual('node device cool online');
303 expect(node.id).toEqual('foo');
304 });
305
306 it('should create online device node with type and lng/lat', function () {
307 var node = tms.createDeviceNode({
308 id: 'foo',
309 type: 'yowser',
310 online: true,
311 location: {
312 type: 'latlng',
313 lng: 2048,
314 lat: 3096
315 }
316 });
317 expect(node).toBePositionedAt([48,96]);
318 expect(node).toBeFixed();
319 expect(node.class).toEqual('device');
320 expect(node.svgClass).toEqual('node device yowser online');
321 expect(node.id).toEqual('foo');
322 });
323
324 // === unit tests for createHostNode()
325
326 it('should create a basic host node', function () {
327 var node = tms.createHostNode({ id: 'bar', cp: { device: 'dev0' } });
328 expect(node).toBePositionedAt(randHostLoc);
329 expect(node).not.toBeFixed();
330 expect(node.class).toEqual('host');
331 expect(node.svgClass).toEqual('node host endstation');
332 expect(node.id).toEqual('bar');
333 });
334
335 it('should create a host with type', function () {
336 var node = tms.createHostNode({
337 id: 'bar',
338 type: 'classic',
339 cp: { device: 'dev1' }
340 });
341 expect(node).toBePositionedAt(nearDev1);
342 expect(node).not.toBeFixed();
343 expect(node.class).toEqual('host');
344 expect(node.svgClass).toEqual('node host classic');
345 expect(node.id).toEqual('bar');
346 });
347
348 // === unit tests for createHostLink()
349
350 it('should create a basic host link', function () {
351 var link = tms.createHostLink(lu.host1);
352 expect(link.source).toEqual(lu.host1);
353 expect(link.target).toEqual(lu.dev1);
354 expect(link).toHaveEndPoints(host1Loc, dev1Loc);
355 expect(link.key).toEqual('dev1/7-host1');
356 expect(link.class).toEqual('link');
357 expect(link.type()).toEqual('hostLink');
358 expect(link.linkWidth()).toEqual(1);
359 expect(link.online()).toEqual(true);
360 });
361
362 it('should return null for failed endpoint lookup', function () {
363 spyOn($log, 'error');
364 var link = tms.createHostLink(lu.host2);
365 expect(link).toBeNull();
366 expect($log.error).toHaveBeenCalledWith(
367 'Node(s) not on map for link:\n[dst] "dev0" missing'
368 );
369 });
370
371 // === unit tests for createLink()
372
373 it('should return null for missing endpoints', function () {
374 spyOn($log, 'error');
375 var link = tms.createLink({src: 'dev0', dst: 'dev00'});
376 expect(link).toBeNull();
377 expect($log.error).toHaveBeenCalledWith(
378 'Node(s) not on map for link:\n[src] "dev0" missing\n[dst] "dev00" missing'
379 );
380 });
381
382 it('should create a basic link', function () {
383 var linkData = {
384 src: 'dev1',
385 dst: 'dev2',
386 id: 'baz',
387 type: 'zoo',
388 online: true,
389 linkWidth: 1.5
390 },
391 link = tms.createLink(linkData);
392 expect(link.source).toEqual(lu.dev1);
393 expect(link.target).toEqual(lu.dev2);
394 expect(link).toHaveEndPoints(dev1Loc, dev2Loc);
395 expect(link.key).toEqual('baz');
396 expect(link.class).toEqual('link');
397 expect(link.fromSource).toBe(linkData);
398 expect(link.type()).toEqual('zoo');
399 expect(link.online()).toEqual(true);
400 expect(link.linkWidth()).toEqual(1.5);
401 });
402
403});