// 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); }