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); }
/// <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); }
public JsEngineManager(IJsEngineManagerConfiguration config) { this._config = config; if (config == null) { throw new ArgumentNullException(nameof(config)); } this._modules = config.Modules ?? new List <string>(); // replace with custom object & mapping this._poolConfig = new JsPoolConfig { EngineFactory = new ChakraCoreJsEngineFactory().CreateEngine, Initializer = this.Initializer() }; 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); }
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 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); }
static void Main(string[] args) { var pool = new JsPool(new JsPoolConfig { Initializer = initEngine => { // In a real app you'd probably use ExecuteFile and ExecuteResource to load // libraries into the engine. initEngine.Execute(@" function sayHello(name) { return 'Hello ' + name + '!'; } " ); } }); // Get an engine from the pool var engine = pool.GetEngine(); var message = engine.CallFunction <string>("sayHello", "Daniel"); Console.WriteLine(message); // "Hello Daniel!" Console.ReadKey(); // Always release an engine when you're done with it. pool.ReturnEngineToPool(engine); // Disposing the pool will also dispose all its engines. Always dispose it when // it is no longer required. pool.Dispose(); }
public JsEnginePool( Action <IJsEngine> initializer, int startEngines, int maxEngines, int maxUsagesPerEngine, TimeSpan engineTimeout) { // First we need to check if the JsEngineSwitcher has been configured. We'll do this // by checking the DefaultEngineName being set. If that's there we can safely assume // its been configured somehow (maybe via a configuration file). If not we'll wire up // Jint as the default engine. if (string.IsNullOrWhiteSpace(JsEngineSwitcher.Instance.DefaultEngineName)) { JsEngineSwitcher.Instance.EngineFactories.Add(new JintJsEngineFactory()); JsEngineSwitcher.Instance.DefaultEngineName = JintJsEngine.EngineName; } _pool = new JsPool <JsEngine>(new JsPoolConfig <JsEngine> { EngineFactory = () => new JsEngine(JsEngineSwitcher.Instance.CreateDefaultEngine()), Initializer = x => initializer?.Invoke(x), StartEngines = startEngines, MaxEngines = maxEngines, MaxUsagesPerEngine = maxUsagesPerEngine, GetEngineTimeout = engineTimeout }); }
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); }
static void Main(string[] args) { var pool = new JsPool(new JsPoolConfig { Initializer = initEngine => { // In a real app you'd probably use ExecuteFile and ExecuteResource to load // libraries into the engine. initEngine.Execute(@" function sayHello(name) { return 'Hello ' + name + '!'; } "); } }); // Get an engine from the pool var engine = pool.GetEngine(); var message = engine.CallFunction<string>("sayHello", "Daniel"); Console.WriteLine(message); // "Hello Daniel!" Console.ReadKey(); // Always release an engine when you're done with it. pool.ReturnEngineToPool(engine); // Disposing the pool will also dispose all its engines. Always dispose it when // it is no longer required. pool.Dispose(); }
/// <summary> /// Initializes a new instance of the <see cref="ReactViewEngine"/> class. /// </summary> public ReactViewEngine() { this.pool = new JsPool(new JsPoolConfig { // TODO uncomment the following line to enable unstable watch mode, see Daniel15/JSPool#9 //// WatchPath = ReactConfiguration.ClientPath, WatchFiles = new string[] { Script.Path }, Initializer = initEngine => initEngine.ExecuteFile(Script.Path) }); }
/// <summary> /// Initialize the JSPool /// </summary> /// <param name="availableFactories"></param> /// <param name="configuration"></param> public JavascriptFactory(IEnumerable <FactoryRegistration> availableFactories, IJavascriptConfiguration configuration) { if (!configuration.RenderServerSide) { return; } _configuration = configuration; _factory = GetFactory(availableFactories); _pool = CreatePool(); }
/// <summary> /// Clean up all engines /// </summary> public virtual void Dispose() { _disposed = true; if (_pool == null) { return; } _pool.Dispose(); _pool = null; }
public static void InitJsPool() { JsEngineSwitcher.Instance.EngineFactories.AddChakraCore(); JsEngineSwitcher.Instance.DefaultEngineName = ChakraCoreJsEngine.EngineName; _myJsPool = new JsPool(new JsPoolConfig { Initializer = initEngine => { initEngine.ExecuteFile(Path.Combine(ApplicationEnvironment.ApplicationBasePath, "cmd5.js"), Encoding.UTF8); } }); }
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)); }
/// <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 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); }
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; }; }
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 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 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); }
static void Main(string[] args) { // Configure JavaScriptEngineSwitcher. Generally V8 is preferred, however // it's currently not supported on .NET Core. IJsEngineSwitcher engineSwitcher = JsEngineSwitcher.Current; #if NETCOREAPP1_0 || NETCOREAPP2_0 engineSwitcher.EngineFactories.AddChakraCore(); engineSwitcher.DefaultEngineName = ChakraCoreJsEngine.EngineName; #else engineSwitcher.EngineFactories.AddV8(); engineSwitcher.DefaultEngineName = V8JsEngine.EngineName; #endif var pool = new JsPool(new JsPoolConfig { Initializer = initEngine => { // In a real app you'd probably use ExecuteFile and ExecuteResource to load // libraries into the engine. initEngine.Execute(@" function sayHello(name) { return 'Hello ' + name + '!'; } " ); } }); // Get an engine from the pool // Disposing the engine will return it to the pool - The using() block will do that for us! using (var engine = pool.GetEngine()) { var message = engine.CallFunction <string>("sayHello", "Daniel"); Console.WriteLine(message); // "Hello Daniel!" } Console.ReadKey(); // Disposing the pool will also dispose all its engines. Always dispose it when // it is no longer required. pool.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 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 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 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 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 PooledJsEngine(JsEngine engine, JsPool <JsEngine> pool) { Engine = engine; Pool = pool; }
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 PooledJavaScriptEngine(JavaScriptEngine engine, JsPool <JavaScriptEngine> pool) { Engine = engine; Pool = pool; }
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 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 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 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) ); }