public async Task ReturnsAndCachesCompiledResultIfCacheMisses()
            {
                // Arrange
                var compiled = new Mock <Type>();
                TestableDefaultCompilationManager cm = CreateManager();
                TestFile file     = TestData.CreateDummyFile();
                var      compiler = new Mock <ICompiler>();

                cm.Compilers.Add(compiler.Object);
                cm.MockContentIdentifier
                .Setup(i => i.GenerateContentId(file)).Returns("Foo");
                compiler.Setup(c => c.CanCompile(file)).Returns(true);
                compiler.Setup(c => c.Compile(file)).Returns(Task.FromResult(CompilationResult.Successful(It.IsAny <string>(), compiled.Object, new[]
                {
                    new CompilationMessage(MessageLevel.Info, "Foo")
                })));

                // Act
                CompilationResult result = await cm.Compile(file, NullTrace.Instance);

                // Assert
                Assert.True(result.Success);
                Assert.False(result.SatisfiedFromCache);
                Assert.Equal("Foo", result.Messages.Single().Message);
                Assert.Same(compiled.Object, result.GetCompiledType());

                Type cached;

                Assert.True(cm.Cache["Foo"].TryGetTarget(out cached));
                Assert.Same(compiled.Object, cached);
            }
            public async Task ReturnsCacheIfHitAndReferenceValid()
            {
                // Arrange
                var cached = new Mock <Type>();
                TestableDefaultCompilationManager cm = CreateManager();
                TestFile file = TestData.CreateDummyFile();

                cm.Cache["Foo"] = new WeakReference <Type>(cached.Object);
                cm.MockContentIdentifier
                .Setup(i => i.GenerateContentId(file)).Returns("Foo");

                // Act
                CompilationResult result = await cm.Compile(file, NullTrace.Instance);

                // Assert
                Assert.True(result.Success);
                Assert.True(result.SatisfiedFromCache);
                Assert.Equal(0, result.Messages.Count);
                Assert.Same(cached.Object, result.GetCompiledType());
            }
            public void ReturnsAndCachesCompiledResultIfCachedValueHasBeenCollected()
            {
                // Arrange
                var compiled = new Mock <Type>();
                TestableDefaultCompilationManager cm = CreateManager();
                TestFile file     = TestData.CreateDummyFile();
                var      compiler = new Mock <ICompiler>();

                cm.Compilers.Add(compiler.Object);
                cm.MockContentIdentifier
                .Setup(i => i.GenerateContentId(file)).Returns("Foo");
                compiler.Setup(c => c.CanCompile(file)).Returns(true);
                compiler.Setup(c => c.Compile(file)).Returns(Task.FromResult(CompilationResult.Successful(It.IsAny <string>(), compiled.Object, new[]
                {
                    new CompilationMessage(MessageLevel.Info, "Foo")
                })));

                // Add a cache entry, but collect it.
                cm.Cache["Foo"] = new WeakReference <Type>(new FakeType());
                GC.Collect();

                // Act
                // Using ".Result" because making this Async causes a reference to the cached type to be held.
                CompilationResult result = cm.Compile(file, NullTrace.Instance).Result;

                // Assert
                Assert.True(result.Success);
                Assert.False(result.SatisfiedFromCache);
                Assert.Equal("Foo", result.Messages.Single().Message);
                Assert.Same(compiled.Object, result.GetCompiledType());

                Type cached;

                Assert.True(cm.Cache["Foo"].TryGetTarget(out cached));
                Assert.Same(compiled.Object, cached);
            }
Example #4
0
        public async Task Invoke(IDictionary <string, object> environment)
        {
            var    sw    = new Stopwatch();
            var    req   = new RazorRequest(environment);
            ITrace trace = Tracer.ForRequest(req);

            using (trace.StartTrace())
            {
                trace.WriteLine("Received {0} {1}", req.Method, req.Path);

                if (!IsUnder(VirtualRoot, req.Path))
                {
                    // Not for us!
                    await NextApp(environment);

                    return;
                }

                // Step 1. Route the request to a file
                RouteResult routed = await Router.Route(req, trace);

                if (!routed.Success)
                {
                    // Also not for us!
                    await NextApp(environment);

                    return;
                }
                trace.WriteLine("Router: '{0}' ==> '{1}'::'{2}'", req.Path, routed.File.Name, routed.PathInfo);

                // Step 2. Use the compilation manager to get the file's compiled type
                sw.Start();
                CompilationResult compiled = await CompilationManager.Compile(routed.File, trace);

                sw.Stop();
                if (!compiled.Success)
                {
                    trace.WriteLine("Compiler: '{0}' FAILED", routed.File.Name);
                    throw new CompilationFailedException(compiled.Messages, compiled.GeneratedCode);
                }
                if (compiled.SatisfiedFromCache)
                {
                    trace.WriteLine("Retrieved compiled code from cache in {0}ms", sw.ElapsedMilliseconds);
                }
                else
                {
                    trace.WriteLine("Compiled '{0}' in {1}ms", routed.File.Name, sw.ElapsedMilliseconds);
                }
                sw.Reset();

                // Step 3. Construct an instance using the PageActivator
                Type             type      = compiled.GetCompiledType();
                ActivationResult activated = Activator.ActivatePage(type, trace);
                if (!activated.Success)
                {
                    trace.WriteLine("Activator: '{0}' FAILED", type.FullName);
                    throw new ActivationFailedException(type);
                }
                trace.WriteLine("Activator: '{0}' SUCCESS", type.FullName);

                // Step 4. Execute the activated instance!
                await Executor.Execute(activated.Page, environment, trace);
            }
        }