public void GetEngineCreatesNewEngineIfNotAtMaximum() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 1, MaxEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); pool.GetEngine(); // First engine created on init factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); Assert.AreEqual(1, pool.EngineCount); Assert.AreEqual(0, pool.AvailableEngineCount); pool.GetEngine(); // Second engine created JIT factory.Verify(x => x.EngineFactory(), Times.Exactly(3)); Assert.AreEqual(2, pool.EngineCount); Assert.AreEqual(0, pool.AvailableEngineCount); }
public void GetEngineReturnsAllAvailableEngines() { var engines = new[] { new Mock <IJsEngine>().Object, new Mock <IJsEngine>().Object, new Mock <IJsEngine>().Object, }; var factory = new Mock <IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) // Initial call to factory is to determine engine type, we don't care // about that here. .Returns(new Mock <IJsEngine>().Object) .Returns(engines[0]) .Returns(engines[1]) .Returns(engines[2]); var config = new JsPoolConfig { StartEngines = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); var resultEngines = new[] { pool.GetEngine(), pool.GetEngine(), pool.GetEngine(), }; CollectionAssert.AreEquivalent(engines, resultEngines); }
/// <summary> /// Creates a new JavaScript engine pool. /// </summary> protected virtual IJsPool CreatePool() { var allFiles = _config.Scripts .Concat(_config.ScriptsWithoutTransform) .Select(_fileSystem.MapPath); var poolConfig = new JsPoolConfig { EngineFactory = _factory, Initializer = InitialiseEngine, WatchPath = _fileSystem.MapPath("~/"), WatchFiles = allFiles }; if (_config.MaxEngines != null) { poolConfig.MaxEngines = _config.MaxEngines.Value; } if (_config.StartEngines != null) { poolConfig.StartEngines = _config.StartEngines.Value; } if (_config.MaxUsagesPerEngine != null) { poolConfig.MaxUsagesPerEngine = _config.MaxUsagesPerEngine.Value; } var pool = new JsPool(poolConfig); // Reset the recycle exception on recycle. If there *are* errors loading the scripts // during recycle, the errors will be caught in the initializer. pool.Recycled += (sender, args) => _scriptLoadException = null; return(pool); }
/// <summary> /// Creates a new JavaScript engine pool. /// </summary> protected virtual IJsPool CreatePool() { var allFiles = _config.Scripts .Concat(_config.ScriptsWithoutTransform) .Select(_fileSystem.MapPath); var poolConfig = new JsPoolConfig { EngineFactory = _factory, Initializer = InitialiseEngine, WatchPath = _fileSystem.MapPath("~/"), WatchFiles = allFiles }; if (_config.MaxEngines != null) { poolConfig.MaxEngines = _config.MaxEngines.Value; } if (_config.StartEngines != null) { poolConfig.StartEngines = _config.StartEngines.Value; } return(new JsPool(poolConfig)); }
public void GetEngineReturnsAllAvailableEngines() { var engines = new[] { new Mock <IJsEngine>().Object, new Mock <IJsEngine>().Object, new Mock <IJsEngine>().Object, }; var factory = new Mock <IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) .Returns(engines[0]) .Returns(engines[1]) .Returns(engines[2]); var config = new JsPoolConfig { StartEngines = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); var resultEngines = new[] { pool.GetEngine().InnerEngine, pool.GetEngine().InnerEngine, pool.GetEngine().InnerEngine, }; Assert.Equal(engines, resultEngines); }
public void DisposeDisposesAllEngines() { var engines = new[] { new Mock<IJsEngine>(), new Mock<IJsEngine>(), new Mock<IJsEngine>(), new Mock<IJsEngine>(), }; var factory = new Mock<IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) .Returns(engines[0].Object) .Returns(engines[1].Object) .Returns(engines[2].Object) .Returns(engines[3].Object); var config = new JsPoolConfig { StartEngines = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); pool.Dispose(); foreach (var engine in engines) { engine.Verify(x => x.Dispose()); } }
protected override IJsPool CreatePool() { var allFiles = _config.Scripts .Concat(_config.ScriptsWithoutTransform) .Select(_fileSystem.MapPath); var poolConfig = new JsPoolConfig { EngineFactory = _factory, Initializer = InitialiseEngine, WatchPath = _fileSystem.MapPath("~/"), WatchFiles = allFiles, GetEngineTimeout = TimeSpan.FromSeconds(10.0), MaxUsagesPerEngine = 0, StartEngines = 10, MaxEngines = 10, GarbageCollectionInterval = 60 }; var pool = new AfishaJsPool(poolConfig); // Reset the recycle exception on recycle. If there *are* errors loading the scripts // during recycle, the errors will be caught in the initializer. pool.Recycled += (sender, args) => _scriptLoadException = null; return(pool); }
public void DisposeDisposesAllEngines() { var engines = new[] { new Mock <IJsEngine>(), new Mock <IJsEngine>(), new Mock <IJsEngine>(), new Mock <IJsEngine>(), }; var factory = new Mock <IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) .Returns(engines[0].Object) .Returns(engines[1].Object) .Returns(engines[2].Object) .Returns(engines[3].Object); var config = new JsPoolConfig { StartEngines = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); pool.Dispose(); foreach (var engine in engines) { engine.Verify(x => x.Dispose()); } }
public void GetEngineReturnsAllAvailableEngines() { var engines = new[] { new Mock<IJsEngine>().Object, new Mock<IJsEngine>().Object, new Mock<IJsEngine>().Object, }; var factory = new Mock<IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) // Initial call to factory is to determine engine type, we don't care // about that here. .Returns(new Mock<IJsEngine>().Object) .Returns(engines[0]) .Returns(engines[1]) .Returns(engines[2]); var config = new JsPoolConfig { StartEngines = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); var resultEngines = new[] { pool.GetEngine(), pool.GetEngine(), pool.GetEngine(), }; CollectionAssert.AreEquivalent(engines, resultEngines); }
public AfishaJsPool(JsPoolConfig <IJsEngine> config) : base(config) { #if DEBUG new Thread( () => { while (!_cancellationTokenSource.IsCancellationRequested) { Debug.WriteLine($"AvailableEngines: {_availableEngines.Count}"); Debug.WriteLine($"EnginesToGC: {_enginesToGc.Count}"); Thread.Sleep(1000); } }).Start(); #endif new Thread( () => { while (!_cancellationTokenSource.IsCancellationRequested) { WaitHandle.WaitAny(new WaitHandle[] { _enginePopulateEvent }, TimeSpan.FromSeconds(5)); while (EngineCount < _config.MaxEngines) { var engine = CreateEngine(); _availableEngines.Add(engine); } } }).Start(); new Thread( () => { while (!_cancellationTokenSource.IsCancellationRequested) { _engineEnqueuedEvent.WaitOne(); while (!_cancellationTokenSource.IsCancellationRequested && _enginesToGc.TryDequeue(out var engine)) { if (!_metadata.TryGetValue(engine, out _)) { // This engine was from another pool. This could happen if a pool is recycled // and replaced with a different one (like what ReactJS.NET does when any // loaded files change). Let's just pretend we never saw it. engine.Dispose(); continue; } engine.CollectGarbage(); _availableEngines.Add(engine); _engineGcTime[engine] = DateTime.UtcNow; } } }).Start(); }
public JsPool GetEnginePool() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 100, EngineFactory = factory.Object.EngineFactory, }; return(new JsPool(config)); }
public void ConstructorCreatesEngines() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 5, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.AreEqual(5, pool.AvailableEngineCount); // 6 times because one is at the very beginning to check the engine type factory.Verify(x => x.EngineFactory(), Times.Exactly(6)); }
public void WatchPathWithoutWatchFilesDoesNotThrow() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory, WatchPath = Directory.GetCurrentDirectory(), }; // Should not throw // ReSharper disable once UnusedVariable var pool = new JsPool(config); }
/// <summary> /// Create a new js Pool /// </summary> /// <returns></returns> private JsPool CreatePool() { var config = new JsPoolConfig { EngineFactory = _factory, Initializer = LoadScripts }; var pool = new JsPool(config); // Reset the recycle exception on recycle. If there *are* errors loading the scripts // during recycle, the errors will be caught in the initializer. pool.Recycled += null; return(pool); }
public void ConstructorCreatesEngines() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 5, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.Equal(5, pool.AvailableEngineCount); factory.Verify(x => x.EngineFactory(), Times.Exactly(5)); }
public void ConstructorCreatesEngines() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 5, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.AreEqual(5, pool.AvailableEngineCount); // 6 times because one is at the very beginning to check the engine type factory.Verify(x => x.EngineFactory(), Times.Exactly(6)); }
public void ReturnEngineDisposesIfAtMaxUsages() { var mockEngine1 = new Mock <IJsEngine>(); var mockEngine2 = new Mock <IJsEngine>(); var factory = new Mock <IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) .Returns(mockEngine1.Object) .Returns(mockEngine2.Object); var config = new JsPoolConfig { StartEngines = 1, MaxUsagesPerEngine = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); // First two usages should not recycle it using (var engine = pool.GetEngine()) { Assert.Equal(mockEngine1.Object, engine.InnerEngine); } mockEngine1.Verify(x => x.Dispose(), Times.Never); using (var engine = pool.GetEngine()) { Assert.Equal(mockEngine1.Object, engine.InnerEngine); } mockEngine1.Verify(x => x.Dispose(), Times.Never); // Third usage should recycle it, since the max usages is 3 using (var engine = pool.GetEngine()) { Assert.Equal(mockEngine1.Object, engine.InnerEngine); } mockEngine1.Verify(x => x.Dispose()); // Next usage should get a new engine using (var engine = pool.GetEngine()) { Assert.Equal(mockEngine2.Object, engine.InnerEngine); } }
public JsEngineManager(IJsEngineManagerConfiguration config) { if (config == null) { throw new ArgumentNullException(nameof(config)); } this._modules = ResolvePaths(config.Modules ?? new List <string>()).ToList(); // replace with custom object & mapping this._poolConfig = new JsPoolConfig { EngineFactory = new ChakraCoreJsEngineFactory().CreateEngine, Initializer = this.Initializer() }; if (this._modules.Count > 0) { // Get common root path for all files and configure watching. this._poolConfig.WatchPath = this.GetCommonRoot(this._modules); this._poolConfig.WatchFiles = this._modules; } if (config.StartEngines.HasValue) { this._poolConfig.StartEngines = config.StartEngines.Value; } if (config.MaxEngines.HasValue) { this._poolConfig.MaxEngines = config.MaxEngines.Value; } if (config.MaxUsagesPerEngine.HasValue) { this._poolConfig.MaxUsagesPerEngine = config.MaxUsagesPerEngine.Value; } this._pool = new JsPool(this._poolConfig); // Clean combined scripts on any script file change this._pool.Recycled += (sender, args) => { this._scripts = null; }; }
/// <summary> /// Creates a new JavaScript engine pool. /// </summary> protected virtual IJsPool CreatePool() { var poolConfig = new JsPoolConfig { EngineFactory = _factory, Initializer = InitialiseEngine, }; if (_config.MaxEngines != null) { poolConfig.MaxEngines = _config.MaxEngines.Value; } if (_config.StartEngines != null) { poolConfig.StartEngines = _config.StartEngines.Value; } return(new JsPool(poolConfig)); }
public void ConcurrentGetAndReleaseEnginesIsSafe() { const int ConcurrentThreadCount = 100; var config = new JsPoolConfig { StartEngines = 0, MaxEngines = ConcurrentThreadCount, EngineFactory = () => new Mock <IJsEngine>().Object }; var pool = new JsPool(config); ThreadStart getReleaseEngine = () => { for (var i = 0; i < 10000; ++i) { IJsEngine engine = pool.GetEngine(); pool.ReturnEngineToPool(engine); } }; IList <Thread> threads = new List <Thread>(); for (var i = 0; i < ConcurrentThreadCount; ++i) { threads.Add(new Thread(getReleaseEngine)); } foreach (var thread in threads) { thread.Start(); } threads[0].Join(); for (var i = 1; i < threads.Count; ++i) { Thread thread = threads[i]; thread.Join(); } Assert.AreEqual(0, pool.EngineCount); }
public void ReturnEngineToPoolAddsToAvailableEngines() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.AreEqual(2, pool.AvailableEngineCount); var engine = pool.GetEngine(); Assert.AreEqual(1, pool.AvailableEngineCount); pool.ReturnEngineToPool(engine); Assert.AreEqual(2, pool.AvailableEngineCount); }
public void ShouldIgnoreReturnToPoolIfUnknownEngine() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 1, EngineFactory = factory.Object.EngineFactory }; var rogueEngine = new Mock <IJsEngine>(); var pool = new JsPool(config); pool.ReturnEngineToPool(rogueEngine.Object); Assert.AreEqual(1, pool.AvailableEngineCount); Assert.AreEqual(1, pool.EngineCount); rogueEngine.Verify(x => x.Dispose()); }
public void ReturnEngineDisposesIfAtMaxUsages() { var mockEngine1 = new Mock <IJsEngine>(); var mockEngine2 = new Mock <IJsEngine>(); var factory = new Mock <IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) // First engine is a dummy engine to check functionality .Returns(new Mock <IJsEngine>().Object) .Returns(mockEngine1.Object) .Returns(mockEngine2.Object); var config = new JsPoolConfig { StartEngines = 1, MaxUsagesPerEngine = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); // First two usages should not recycle it var engine = pool.GetEngine(); Assert.AreEqual(mockEngine1.Object, engine); pool.ReturnEngineToPool(engine); mockEngine1.Verify(x => x.Dispose(), Times.Never); engine = pool.GetEngine(); Assert.AreEqual(mockEngine1.Object, engine); pool.ReturnEngineToPool(engine); mockEngine1.Verify(x => x.Dispose(), Times.Never); // Third usage should recycle it, since the max usages is 3 engine = pool.GetEngine(); pool.ReturnEngineToPool(engine); mockEngine1.Verify(x => x.Dispose()); // Next usage should get a new engine engine = pool.GetEngine(); Assert.AreEqual(mockEngine2.Object, engine); }
public void GetEngineFailsIfAtMaximum() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 1, MaxEngines = 1, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); pool.GetEngine(); // First engine created on init Assert.Throws <JsPoolExhaustedException>(() => pool.GetEngine(TimeSpan.Zero) ); }
public void ConcurrentGetAndReleaseEnginesIsSafe() { const int ConcurrentThreadCount = 100; var config = new JsPoolConfig { StartEngines = 0, MaxEngines = ConcurrentThreadCount, EngineFactory = () => new Mock<IJsEngine>().Object }; var pool = new JsPool(config); ThreadStart getReleaseEngine = () => { for (var i = 0; i < 10000; ++i) { IJsEngine engine = pool.GetEngine(); pool.ReturnEngineToPool(engine); } }; IList<Thread> threads = new List<Thread>(); for (var i = 0; i < ConcurrentThreadCount; ++i) { threads.Add(new Thread(getReleaseEngine)); } foreach (var thread in threads) { thread.Start(); } threads[0].Join(10000); for (var i = 1; i < threads.Count; ++i) { Thread thread = threads[i]; thread.Join(100); } Assert.AreEqual(0, pool.EngineCount); }
public void RecycleCreatesNewEngines() { var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.Equal(2, pool.AvailableEngineCount); factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); // Now recycle the pool pool.Recycle(); Assert.Equal(2, pool.AvailableEngineCount); // Two more engines should have been created factory.Verify(x => x.EngineFactory(), Times.Exactly(4)); }
public void RecycleFiresRecycledEvent() { var callCount = 0; var factory = new Mock <IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock <IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); pool.Recycled += (sender, args) => callCount++; Assert.AreEqual(0, callCount); pool.Recycle(); Assert.AreEqual(1, callCount); pool.Recycle(); Assert.AreEqual(2, callCount); }
public void GetEngineCreatesNewEngineIfNotAtMaximum() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 1, MaxEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); pool.GetEngine(); // First engine created on init factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); Assert.AreEqual(1, pool.EngineCount); Assert.AreEqual(0, pool.AvailableEngineCount); pool.GetEngine(); // Second engine created JIT factory.Verify(x => x.EngineFactory(), Times.Exactly(3)); Assert.AreEqual(2, pool.EngineCount); Assert.AreEqual(0, pool.AvailableEngineCount); }
public void WatchPathWithoutWatchFilesDoesNotThrow() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory, WatchPath = Directory.GetCurrentDirectory(), }; Assert.DoesNotThrow(() => { // ReSharper disable once UnusedVariable var pool = new JsPool(config); }); }
public void ReturnEngineToPoolAddsToAvailableEngines() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.AreEqual(2, pool.AvailableEngineCount); var engine = pool.GetEngine(); Assert.AreEqual(1, pool.AvailableEngineCount); pool.ReturnEngineToPool(engine); Assert.AreEqual(2, pool.AvailableEngineCount); }
public void ReturnEngineDisposesIfAtMaxUsages() { var mockEngine1 = new Mock<IJsEngine>(); var mockEngine2 = new Mock<IJsEngine>(); var factory = new Mock<IEngineFactoryForMock>(); factory.SetupSequence(x => x.EngineFactory()) // First engine is a dummy engine to check functionality .Returns(new Mock<IJsEngine>().Object) .Returns(mockEngine1.Object) .Returns(mockEngine2.Object); var config = new JsPoolConfig { StartEngines = 1, MaxUsagesPerEngine = 3, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); // First two usages should not recycle it var engine = pool.GetEngine(); Assert.AreEqual(mockEngine1.Object, engine); pool.ReturnEngineToPool(engine); mockEngine1.Verify(x => x.Dispose(), Times.Never); engine = pool.GetEngine(); Assert.AreEqual(mockEngine1.Object, engine); pool.ReturnEngineToPool(engine); mockEngine1.Verify(x => x.Dispose(), Times.Never); // Third usage should recycle it, since the max usages is 3 engine = pool.GetEngine(); pool.ReturnEngineToPool(engine); mockEngine1.Verify(x => x.Dispose()); // Next usage should get a new engine engine = pool.GetEngine(); Assert.AreEqual(mockEngine2.Object, engine); }
public void RecycleFiresRecycledEvent() { var callCount = 0; var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); pool.Recycled += (sender, args) => callCount++; Assert.AreEqual(0, callCount); pool.Recycle(); Assert.AreEqual(1, callCount); pool.Recycle(); Assert.AreEqual(2, callCount); }
public void GetEngineFailsIfAtMaximum() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 1, MaxEngines = 1, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); factory.Verify(x => x.EngineFactory(), Times.Exactly(2)); pool.GetEngine(); // First engine created on init Assert.Throws<JsPoolExhaustedException>(() => pool.GetEngine(TimeSpan.Zero) ); }
public void RecycleCreatesNewEngines() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 2, EngineFactory = factory.Object.EngineFactory }; var pool = new JsPool(config); Assert.AreEqual(2, pool.AvailableEngineCount); // 3 times because one is at the very beginning to check the engine type factory.Verify(x => x.EngineFactory(), Times.Exactly(3)); // Now recycle the pool pool.Recycle(); Assert.AreEqual(2, pool.AvailableEngineCount); // Two more engines should have been created factory.Verify(x => x.EngineFactory(), Times.Exactly(5)); }
public void ShouldIgnoreReturnToPoolIfUnknownEngine() { var factory = new Mock<IEngineFactoryForMock>(); factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object); var config = new JsPoolConfig { StartEngines = 1, EngineFactory = factory.Object.EngineFactory }; var rogueEngine = new Mock<IJsEngine>(); var pool = new JsPool(config); pool.ReturnEngineToPool(rogueEngine.Object); Assert.AreEqual(1, pool.AvailableEngineCount); Assert.AreEqual(1, pool.EngineCount); rogueEngine.Verify(x => x.Dispose()); }