public async void InvokeFromStreamAsync_WithTypeParameter_WithModuleFactory_InvokesFromCacheIfModuleIsCached()
        {
            // Arrange
            const string      dummyArg     = "success";
            HttpNodeJSService testSubject  = CreateHttpNodeJSService();
            MemoryStream      memoryStream = CreateMemoryStream(_dummyExportsMultipleFunctionsModule);
            await testSubject.InvokeFromStreamAsync(memoryStream, DUMMY_CACHE_IDENTIFIER, "setString", new[] { dummyArg }).ConfigureAwait(false);

            // Act
            DummyResult result = await testSubject.
                                 InvokeFromStreamAsync <DummyResult>(() => null, DUMMY_CACHE_IDENTIFIER, "getString").ConfigureAwait(false);

            // Assert
            Assert.Equal(dummyArg, result.Result);
        }
        public async void InvokeFromStreamAsync_WithoutTypeParameter_WithModuleFactory_IsThreadSafe()
        {
            // Arrange
            HttpNodeJSService testSubject = CreateHttpNodeJSService();

            // Act
            const int numThreads = 5;
            var       threads    = new List <Thread>();

            for (int i = 0; i < numThreads; i++)
            {
                var thread = new Thread(() =>
                {
                    MemoryStream memoryStream = CreateMemoryStream(_dummyExportsMultipleFunctionsModule);
                    testSubject.InvokeFromStreamAsync(memoryStream, DUMMY_CACHE_IDENTIFIER, "incrementNumber").GetAwaiter().GetResult();
                });
                threads.Add(thread);
                thread.Start();
            }
            foreach (Thread thread in threads)
            {
                thread.Join();
            }

            // Assert
            (bool success, int result) = await testSubject.TryInvokeFromCacheAsync <int>(DUMMY_CACHE_IDENTIFIER, "getNumber").ConfigureAwait(false);

            Assert.True(success);
            Assert.Equal(numThreads, result);
        }
        public async void InvokeFromStreamAsync_WithoutTypeParameter_WithModuleFactory_InvokesFromCacheIfModuleIsCached()
        {
            // Arrange
            HttpNodeJSService testSubject  = CreateHttpNodeJSService();
            MemoryStream      memoryStream = CreateMemoryStream(_dummyExportsMultipleFunctionsModule);
            await testSubject.InvokeFromStreamAsync(memoryStream, DUMMY_CACHE_IDENTIFIER, "incrementNumber").ConfigureAwait(false);

            // Act
            await testSubject.
            InvokeFromStreamAsync(() => null, DUMMY_CACHE_IDENTIFIER, "incrementNumber").ConfigureAwait(false);

            // Assert
            int result = await testSubject.InvokeFromStreamAsync <int>(memoryStream, DUMMY_CACHE_IDENTIFIER, "getNumber").ConfigureAwait(false);

            Assert.Equal(2, result);
        }
        public async void InvokeFromStreamAsync_WithoutTypeParameter_WithRawStreamModule_InvokesFromStream()
        {
            // Arrange
            const string      dummyArg     = "success";
            HttpNodeJSService testSubject  = CreateHttpNodeJSService(projectPath: _projectPath);
            MemoryStream      memoryStream = CreateMemoryStream(_dummyExportsMultipleFunctionsModule);

            // Act
            await testSubject.InvokeFromStreamAsync(memoryStream, DUMMY_CACHE_IDENTIFIER, "setString", new[] { dummyArg }).ConfigureAwait(false);

            // Assert
            DummyResult result = await testSubject.
                                 InvokeFromStreamAsync <DummyResult>(memoryStream, DUMMY_CACHE_IDENTIFIER, "getString").ConfigureAwait(false);

            Assert.Equal(dummyArg, result.Result);
        }
        public void InvokeFromStreamAsync_WithTypeParameter_WithRawStreamModule_IsThreadSafe()
        {
            // Arrange
            const string      dummyArg    = "success";
            HttpNodeJSService testSubject = CreateHttpNodeJSService();

            // Act
            var       results    = new ConcurrentQueue <DummyResult>();
            const int numThreads = 5;
            var       threads    = new List <Thread>();

            for (int i = 0; i < numThreads; i++)
            {
                var thread = new Thread(() =>
                {
                    MemoryStream memoryStream = CreateMemoryStream(_dummyReturnsArgModule);
                    results.Enqueue(testSubject.InvokeFromStreamAsync <DummyResult>(memoryStream, args: new[] { dummyArg }).GetAwaiter().GetResult());
                });
                threads.Add(thread);
                thread.Start();
            }
            foreach (Thread thread in threads)
            {
                thread.Join();
            }

            // Assert
            Assert.Equal(numThreads, results.Count);
            foreach (DummyResult result in results)
            {
                Assert.Equal(dummyArg, result.Result);
            }
        }
        public async void InvokeFromStreamAsync_WithTypeParameter_WithRawStreamModule_InvokesFromStream()
        {
            // Arrange
            const string      dummyArg     = "success";
            HttpNodeJSService testSubject  = CreateHttpNodeJSService();
            MemoryStream      memoryStream = CreateMemoryStream(_dummyReturnsArgModule);

            // Act
            DummyResult result = await testSubject.InvokeFromStreamAsync <DummyResult>(memoryStream, args : new[] { dummyArg }).ConfigureAwait(false);

            // Assert
            Assert.Equal(dummyArg, result.Result);
        }
        public async void InvokeFromStreamAsync_WithoutTypeParameter_WithModuleFactory_InvokesFromStreamAndCachesModuleIfModuleIsNotCached()
        {
            // Arrange
            HttpNodeJSService testSubject  = CreateHttpNodeJSService();
            MemoryStream      memoryStream = CreateMemoryStream(_dummyExportsMultipleFunctionsModule);

            // Act
            await testSubject.
            InvokeFromStreamAsync(() => memoryStream, DUMMY_CACHE_IDENTIFIER, "incrementNumber").ConfigureAwait(false);

            // Assert
            // Ensure module was cached
            (bool success, int result) = await testSubject.TryInvokeFromCacheAsync <int>(DUMMY_CACHE_IDENTIFIER, "getNumber").ConfigureAwait(false);

            Assert.True(success);
            Assert.Equal(1, result);
        }
        public async void InvokeFromStreamAsync_WithTypeParameter_WithModuleFactory_InvokesFromStreamAndCachesModuleIfModuleIsNotCached()
        {
            // Arrange
            const string      dummyArg     = "success";
            HttpNodeJSService testSubject  = CreateHttpNodeJSService();
            MemoryStream      memoryStream = CreateMemoryStream(_dummyReturnsArgModule);

            // Act
            // Module hasn't been cached, so if this returns the expected value, stream was sent over
            DummyResult result1 = await testSubject.
                                  InvokeFromStreamAsync <DummyResult>(() => memoryStream, DUMMY_CACHE_IDENTIFIER, args : new[] { dummyArg }).ConfigureAwait(false);

            // Assert
            // Ensure module was cached
            (bool success, DummyResult result2) = await testSubject.
                                                  TryInvokeFromCacheAsync <DummyResult>(DUMMY_CACHE_IDENTIFIER, args : new[] { dummyArg }).ConfigureAwait(false);

            Assert.Equal(dummyArg, result1.Result);
            Assert.True(success);
            Assert.Equal(dummyArg, result2.Result);
        }
        public void InvokeFromStreamAsync_IsThreadSafe()
        {
            // Arrange
            const string      dummyModule       = "module.exports = (callback, resultString) => callback(null, {result: resultString});";
            const string      dummyResultString = "success";
            HttpNodeJSService testSubject       = CreateHttpNodeJSService();

            // Act
            var       results    = new ConcurrentQueue <DummyResult>();
            const int numThreads = 5;
            var       threads    = new List <Thread>();

            for (int i = 0; i < numThreads; i++)
            {
                var thread = new Thread(() =>
                {
                    using (var memoryStream = new MemoryStream())
                        using (var streamWriter = new StreamWriter(memoryStream))
                        {
                            streamWriter.Write(dummyModule);
                            streamWriter.Flush();
                            memoryStream.Position = 0;
                            results.Enqueue(testSubject.InvokeFromStreamAsync <DummyResult>(memoryStream, args: new[] { dummyResultString }).GetAwaiter().GetResult());
                        }
                });
                threads.Add(thread);
                thread.Start();
            }
            foreach (Thread thread in threads)
            {
                thread.Join();
            }

            // Assert
            Assert.Equal(numThreads, results.Count);
            foreach (DummyResult result in results)
            {
                Assert.Equal(dummyResultString, result.Result);
            }
        }
        public async void InvokeFromStreamAsync_InvokesJavascript()
        {
            // Arrange
            const string      dummyResultString = "success";
            HttpNodeJSService testSubject       = CreateHttpNodeJSService();

            DummyResult result;

            using (var memoryStream = new MemoryStream())
                using (var streamWriter = new StreamWriter(memoryStream))
                {
                    streamWriter.Write("module.exports = (callback, resultString) => callback(null, {result: resultString});");
                    streamWriter.Flush();
                    memoryStream.Position = 0;

                    // Act
                    result = await testSubject.InvokeFromStreamAsync <DummyResult>(memoryStream, args : new[] { dummyResultString }).ConfigureAwait(false);
                }

            // Assert
            Assert.Equal(dummyResultString, result.Result);
        }
        public void InvokeFromStreamAsync_WithTypeParameter_WithModuleFactory_IsThreadSafe()
        {
            // Arrange
            HttpNodeJSService testSubject = CreateHttpNodeJSService();

            // Act
            var       results    = new ConcurrentQueue <int>();
            const int numThreads = 5;
            var       threads    = new List <Thread>();

            for (int i = 0; i < numThreads; i++)
            {
                var thread = new Thread(() =>
                {
                    MemoryStream memoryStream = CreateMemoryStream(_dummyExportsMultipleFunctionsModule);
                    results.Enqueue(testSubject.InvokeFromStreamAsync <int>(() => memoryStream, DUMMY_CACHE_IDENTIFIER, "incrementAndGetNumber").GetAwaiter().GetResult());
                });
                threads.Add(thread);
                thread.Start();
            }
            foreach (Thread thread in threads)
            {
                thread.Join();
            }

            // Assert
            Assert.Equal(numThreads, results.Count);
            // Module shouldn't get cached more than once, we should get exactly [1,2,3,4,5]
            List <int> resultsList = results.ToList();

            resultsList.Sort();
            for (int i = 0; i < numThreads; i++)
            {
                Assert.Equal(resultsList[i], i + 1);
            }
        }