Beispiel #1
0
        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);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
		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);
		}
Beispiel #5
0
        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());
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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();
        }
Beispiel #8
0
        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
            });
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
		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;
        }
Beispiel #14
0
 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);
         }
     });
 }
Beispiel #15
0
        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);
        }
Beispiel #17
0
        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));
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
        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));
        }
Beispiel #20
0
        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; };
        }
Beispiel #22
0
        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);
        }
Beispiel #23
0
        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());
        }
Beispiel #24
0
        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);
        }
Beispiel #25
0
        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();
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
        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)
                                                     );
        }
Beispiel #28
0
        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);
        }
Beispiel #29
0
        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));
        }
Beispiel #30
0
		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);
		}
Beispiel #31
0
        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);
        }
Beispiel #32
0
        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));
        }
Beispiel #33
0
        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);
        }
Beispiel #34
0
 public PooledJsEngine(JsEngine engine, JsPool <JsEngine> pool)
 {
     Engine = engine;
     Pool   = pool;
 }
Beispiel #35
0
        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);
        }
Beispiel #36
0
        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;
 }
Beispiel #38
0
        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());
        }
Beispiel #39
0
 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);
     });
 }
Beispiel #40
0
        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());
            }
        }
Beispiel #41
0
        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)
            );
        }