| // Copyright 2006 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| goog.provide('goog.structs.PriorityPoolTest'); |
| goog.setTestOnly('goog.structs.PriorityPoolTest'); |
| |
| goog.require('goog.structs.PriorityPool'); |
| goog.require('goog.testing.MockClock'); |
| goog.require('goog.testing.jsunit'); |
| |
| // Implementation of the Pool class with isObjectDead() always returning TRUE, |
| // so that the the Pool will not reuse any objects. |
| function NoObjectReusePriorityPool(opt_min, opt_max) { |
| goog.structs.PriorityPool.call(this, opt_min, opt_max); |
| } |
| goog.inherits(NoObjectReusePriorityPool, goog.structs.PriorityPool); |
| |
| NoObjectReusePriorityPool.prototype.objectCanBeReused = function(obj) { |
| return false; |
| }; |
| |
| |
| function testExceedMax1() { |
| var p = new goog.structs.PriorityPool(0, 3); |
| |
| var getCount1 = 0; |
| var callback1 = function(obj) { |
| assertNotNull(obj); |
| getCount1++; |
| }; |
| |
| var getCount2 = 0; |
| var callback2 = function(obj) { |
| getCount2++; |
| }; |
| |
| p.getObject(callback1); |
| p.getObject(callback1); |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback2); |
| p.getObject(callback2); |
| |
| assertEquals('getCount for allocated, Should be 3', getCount1, 3); |
| assertEquals('getCount for unallocated, Should be 0', getCount2, 0); |
| } |
| |
| |
| function testExceedMax2() { |
| var p = new goog.structs.PriorityPool(0, 1); |
| |
| var getCount1 = 0; |
| var callback1 = function(obj) { |
| assertNotNull(obj); |
| getCount1++; |
| }; |
| |
| var getCount2 = 0; |
| var callback2 = function(obj) { |
| getCount2++; |
| }; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback2); |
| p.getObject(callback2); |
| p.getObject(callback2); |
| p.getObject(callback2); |
| |
| assertEquals('getCount for allocated, Should be 1', getCount1, 1); |
| assertEquals('getCount for unallocated, Should be 0', getCount2, 0); |
| } |
| |
| function testExceedMax3() { |
| var p = new goog.structs.PriorityPool(0, 2); |
| |
| var obj1 = null; |
| var callback1 = function(obj) { |
| obj1 = obj; |
| }; |
| |
| var obj2 = null; |
| var callback2 = function(obj) { |
| obj2 = obj; |
| }; |
| |
| var obj3 = null; |
| var callback3 = function(obj) { |
| obj3 = obj; |
| }; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback3); |
| |
| assertNotNull(obj1); |
| assertNotNull(obj2); |
| assertNull(obj3); |
| } |
| |
| function testExceedMax4() { |
| var p = new goog.structs.PriorityPool(); // default: 10 |
| var objs = []; |
| |
| var getCount1 = 0; |
| var callback1 = function(obj) { |
| assertNotNull(obj); |
| getCount1++; |
| }; |
| |
| var getCount2 = 0; |
| var callback2 = function(obj) { |
| getCount2++; |
| }; |
| |
| for (var i = 0; i < 12; i++) { |
| p.getObject(i < 10 ? callback1 : callback2); |
| } |
| |
| assertEquals('getCount for allocated, Should be 10', getCount1, 10); |
| assertEquals('getCount for unallocated, Should be 0', getCount2, 0); |
| } |
| |
| |
| function testReleaseAndGet1() { |
| var p = new goog.structs.PriorityPool(0, 10); |
| |
| var o = null; |
| var callback = function(obj) { |
| o = obj; |
| }; |
| |
| p.getObject(callback); |
| assertEquals(1, p.getCount()); |
| assertEquals(1, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| assertTrue('Result should be true', p.releaseObject(o)); |
| assertEquals(1, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(1, p.getFreeCount()); |
| } |
| |
| |
| function testReleaseAndGet2() { |
| var p = new NoObjectReusePriorityPool(0, 10); |
| |
| var o = null; |
| var callback = function(obj) { |
| o = obj; |
| }; |
| |
| p.getObject(callback); |
| assertEquals(1, p.getCount()); |
| assertEquals(1, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| assertTrue('Result should be true', p.releaseObject(o)); |
| assertEquals(0, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| } |
| |
| |
| function testReleaseAndGet3() { |
| var p = new goog.structs.PriorityPool(0, 10); |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| |
| var o2 = null; |
| var callback2 = function(obj) { |
| o2 = obj; |
| }; |
| |
| var o3 = null; |
| var callback3 = function(obj) { |
| o3 = obj; |
| }; |
| |
| var o4 = {}; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback3); |
| |
| assertEquals(3, p.getCount()); |
| assertEquals(3, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| assertTrue('Result should be true', p.releaseObject(o1)); |
| assertTrue('Result should be true', p.releaseObject(o2)); |
| assertFalse('Result should be false', p.releaseObject(o4)); |
| assertEquals(3, p.getCount()); |
| assertEquals(1, p.getInUseCount()); |
| assertEquals(2, p.getFreeCount()); |
| } |
| |
| |
| function testReleaseAndGet4() { |
| var p = new NoObjectReusePriorityPool(0, 10); |
| |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| |
| var o2 = null; |
| var callback2 = function(obj) { |
| o2 = obj; |
| }; |
| |
| var o3 = null; |
| var callback3 = function(obj) { |
| o3 = obj; |
| }; |
| |
| var o4 = {}; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback3); |
| assertEquals(3, p.getCount()); |
| assertEquals(3, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| assertTrue('Result should be true', p.releaseObject(o1)); |
| assertTrue('Result should be true', p.releaseObject(o2)); |
| assertFalse('Result should be false', p.releaseObject(o4)); |
| assertEquals(1, p.getCount()); |
| assertEquals(1, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| } |
| |
| |
| function testIsInPool1() { |
| var p = new goog.structs.PriorityPool(); |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| |
| var o2 = null; |
| var callback2 = function(obj) { |
| o2 = obj; |
| }; |
| |
| var o3 = null; |
| var callback3 = function(obj) { |
| o3 = obj; |
| }; |
| |
| var o4 = {}; |
| var o5 = {}; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback3); |
| var o6 = o1; |
| |
| assertTrue(p.contains(o1)); |
| assertTrue(p.contains(o2)); |
| assertTrue(p.contains(o3)); |
| assertFalse(p.contains(o4)); |
| assertFalse(p.contains(o5)); |
| assertTrue(p.contains(o6)); |
| } |
| |
| |
| function testSetMin1() { |
| var p = new goog.structs.PriorityPool(0, 10); |
| |
| assertEquals(0, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| |
| p.setMinimumCount(10); |
| |
| assertEquals(10, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(10, p.getFreeCount()); |
| } |
| |
| |
| function testSetMin2() { |
| var p = new goog.structs.PriorityPool(0, 10); |
| |
| assertEquals(0, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| p.getObject(callback1); |
| |
| assertEquals(1, p.getCount()); |
| assertEquals(1, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| |
| p.setMinimumCount(10); |
| |
| assertEquals(10, p.getCount()); |
| assertEquals(1, p.getInUseCount()); |
| assertEquals(9, p.getFreeCount()); |
| } |
| |
| |
| function testSetMax1() { |
| var p = new goog.structs.PriorityPool(0, 10); |
| |
| assertEquals(0, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| |
| var o2 = null; |
| var callback2 = function(obj) { |
| o2 = obj; |
| }; |
| |
| var o3 = null; |
| var callback3 = function(obj) { |
| o3 = obj; |
| }; |
| |
| var o4 = null; |
| var callback4 = function(obj) { |
| o4 = obj; |
| }; |
| |
| var o5 = null; |
| var callback5 = function(obj) { |
| o5 = obj; |
| }; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback3); |
| p.getObject(callback4); |
| p.getObject(callback5); |
| |
| assertEquals(5, p.getCount()); |
| assertEquals(5, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| |
| assertTrue('Result should be true', p.releaseObject(o5)); |
| |
| assertEquals(5, p.getCount()); |
| assertEquals(4, p.getInUseCount()); |
| assertEquals(1, p.getFreeCount()); |
| |
| p.setMaximumCount(4); |
| |
| assertEquals(4, p.getCount()); |
| assertEquals(4, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| } |
| |
| |
| function testInvalidMinMax1() { |
| var p = new goog.structs.PriorityPool(0, 10); |
| |
| assertEquals(0, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(0, p.getFreeCount()); |
| |
| assertThrows(function() { |
| p.setMinimumCount(11); |
| }); |
| } |
| |
| |
| function testInvalidMinMax2() { |
| var p = new goog.structs.PriorityPool(5, 10); |
| |
| assertEquals(5, p.getCount()); |
| assertEquals(0, p.getInUseCount()); |
| assertEquals(5, p.getFreeCount()); |
| |
| assertThrows(function() { |
| p.setMaximumCount(4); |
| }); |
| } |
| |
| |
| function testInvalidMinMax3() { |
| assertThrows(function() { |
| new goog.structs.PriorityPool(10, 1); |
| }); |
| } |
| |
| function testQueue1() { |
| var p = new goog.structs.PriorityPool(0, 2); |
| |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| |
| var o2 = null; |
| var callback2 = function(obj) { |
| o2 = obj; |
| }; |
| |
| var o3 = null; |
| var callback3 = function(obj) { |
| o3 = obj; |
| }; |
| |
| p.getObject(callback1); |
| p.getObject(callback2); |
| p.getObject(callback3); |
| |
| assertNotNull(o1); |
| assertNotNull(o2); |
| assertNull(o3); |
| |
| p.releaseObject(o1); |
| assertNotNull(o3); |
| } |
| |
| |
| function testPriority1() { |
| var p = new goog.structs.PriorityPool(0, 2); |
| |
| var o1 = null; |
| var callback1 = function(obj) { |
| o1 = obj; |
| }; |
| |
| var o2 = null; |
| var callback2 = function(obj) { |
| o2 = obj; |
| }; |
| |
| var o3 = null; |
| var callback3 = function(obj) { |
| o3 = obj; |
| }; |
| |
| var o4 = null; |
| var callback4 = function(obj) { |
| o4 = obj; |
| }; |
| |
| var o5 = null; |
| var callback5 = function(obj) { |
| o5 = obj; |
| }; |
| |
| var o6 = null; |
| var callback6 = function(obj) { |
| o6 = obj; |
| }; |
| |
| p.getObject(callback1); // Initially seeded requests. |
| p.getObject(callback2); |
| |
| p.getObject(callback3, 101); // Lowest priority. |
| p.getObject(callback4); // Second lowest priority (default is 100). |
| p.getObject(callback5, 99); // Second highest priority. |
| p.getObject(callback6, 0); // Highest priority. |
| |
| assertNotNull(o1); |
| assertNotNull(o2); |
| assertNull(o3); |
| assertNull(o4); |
| assertNull(o5); |
| assertNull(o6); |
| |
| p.releaseObject(o1); // Release the first initially seeded request (o1). |
| assertNotNull(o6); // Make sure the highest priority request (o6) started. |
| assertNull(o3); |
| assertNull(o4); |
| assertNull(o5); |
| |
| p.releaseObject(o2); // Release the second, initially seeded request (o2). |
| assertNotNull(o5); // The second highest priority request starts (o5). |
| assertNull(o3); |
| assertNull(o4); |
| |
| p.releaseObject(o6); |
| assertNotNull(o4); |
| assertNull(o3); |
| } |
| |
| |
| function testRateLimiting() { |
| var clock = new goog.testing.MockClock(); |
| clock.install(); |
| |
| var p = new goog.structs.PriorityPool(0, 4); |
| p.setDelay(100); |
| |
| var getCount = 0; |
| var callback = function(obj) { |
| assertNotNull(obj); |
| getCount++; |
| }; |
| |
| p.getObject(callback); |
| assertEquals(1, getCount); |
| |
| p.getObject(callback); |
| assertEquals(1, getCount); |
| |
| clock.tick(100); |
| assertEquals(2, getCount); |
| |
| p.getObject(callback); |
| p.getObject(callback); |
| assertEquals(2, getCount); |
| |
| clock.tick(100); |
| assertEquals(3, getCount); |
| |
| clock.tick(100); |
| assertEquals(4, getCount); |
| |
| p.getObject(callback); |
| assertEquals(4, getCount); |
| |
| clock.tick(100); |
| assertEquals(4, getCount); |
| |
| goog.dispose(clock); |
| } |
| |
| |
| function testRateLimitingWithChangingDelay() { |
| var clock = new goog.testing.MockClock(); |
| clock.install(); |
| |
| var p = new goog.structs.PriorityPool(0, 3); |
| p.setDelay(100); |
| |
| var getCount = 0; |
| var callback = function(obj) { |
| assertNotNull(obj); |
| getCount++; |
| }; |
| |
| p.getObject(callback); |
| assertEquals(1, getCount); |
| |
| p.getObject(callback); |
| assertEquals(1, getCount); |
| |
| clock.tick(50); |
| assertEquals(1, getCount); |
| |
| p.setDelay(50); |
| assertEquals(2, getCount); |
| |
| p.getObject(callback); |
| assertEquals(2, getCount); |
| |
| clock.tick(20); |
| assertEquals(2, getCount); |
| |
| p.setDelay(40); |
| assertEquals(2, getCount); |
| |
| clock.tick(20); |
| assertEquals(3, getCount); |
| |
| goog.dispose(clock); |
| } |