HttpSimulator.cs :  » Bloggers » SubText » UnitTests » Subtext » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Bloggers » SubText 
SubText » UnitTests » Subtext » HttpSimulator.cs
using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.SessionState;

namespace UnitTests.Subtext{
    public enum HttpVerb
    {
        GET,
        HEAD,
        POST,
        PUT,
        DELETE,
    }

    /// <summary>
    /// Useful class for simulating the HttpContext. This does not actually 
    /// make an HttpRequest, it merely simulates the state that your code 
    /// would be in "as if" handling a request. Thus the HttpContext.Current 
    /// property is populated.
    /// </summary>
    public class HttpSimulator : IDisposable
    {
        private const string DefaultPhysicalAppPath = @"c:\InetPub\wwwRoot\";
        private readonly NameValueCollection _formVars = new NameValueCollection();
        private readonly NameValueCollection _headers = new NameValueCollection();
        private Uri _referer;
        private string _applicationPath = "/";
        private StringBuilder _builder;
        private string _physicalApplicationPath = DefaultPhysicalAppPath;
        private string _physicalPath = DefaultPhysicalAppPath;
        private TextWriter _responseWriter;
        private SimulatedHttpRequest _workerRequest;
        private string _currentExecutionPath;

        public HttpSimulator() : this("/", DefaultPhysicalAppPath)
        {
        }

        public HttpSimulator(string applicationPath) : this(applicationPath, DefaultPhysicalAppPath)
        {
        }

        public HttpSimulator(string applicationPath, string physicalApplicationPath)
        {
            ApplicationPath = applicationPath;
            PhysicalApplicationPath = physicalApplicationPath;
        }

        public string Host { get; private set; }

        public string LocalPath { get; private set; }

        public int Port { get; private set; }

        /// <summary>
        /// Portion of the URL after the application.
        /// </summary>
        public string Page { get; private set; }

        /// <summary>
        /// The same thing as the IIS Virtual directory. It's 
        /// what gets returned by Request.ApplicationPath.
        /// </summary>
        public string ApplicationPath
        {
            get { return _applicationPath; }
            set
            {
                _applicationPath = value ?? "/";
                _applicationPath = NormalizeSlashes(_applicationPath);
            }
        }

        /// <summary>
        /// Physical path to the application (used for simulation purposes).
        /// </summary>
        public string PhysicalApplicationPath
        {
            get { return _physicalApplicationPath; }
            set
            {
                _physicalApplicationPath = value ?? DefaultPhysicalAppPath;
                //strip trailing backslashes.
                _physicalApplicationPath = StripTrailingBackSlashes(_physicalApplicationPath) + @"\";
            }
        }

        /// <summary>
        /// Physical path to the requested file (used for simulation purposes).
        /// </summary>
        public string PhysicalPath
        {
            get { return _physicalPath; }
        }

        public TextWriter ResponseWriter
        {
            get { return _responseWriter; }
            set { _responseWriter = value; }
        }

        /// <summary>
        /// Returns the text from the response to the simulated request.
        /// </summary>
        public string ResponseText
        {
            get { return (_builder ?? new StringBuilder()).ToString(); }
        }

        public SimulatedHttpRequest WorkerRequest
        {
            get { return _workerRequest; }
        }

        /// <summary>
        /// Sets up the HttpContext objects to simulate a GET request.
        /// </summary>
        /// <remarks>
        /// Simulates a request to http://localhost/
        /// </remarks>
        public HttpSimulator SimulateRequest()
        {
            return SimulateRequest(new Uri("http://localhost/"));
        }

        /// <summary>
        /// Sets up the HttpContext objects to simulate a GET request.
        /// </summary>
        /// <param name="url"></param>
        public HttpSimulator SimulateRequest(Uri url)
        {
            return SimulateRequest(url, HttpVerb.GET);
        }

        /// Sets up the HttpContext objects to simulate a request.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="httpVerb"></param>
        public HttpSimulator SimulateRequest(Uri url, HttpVerb httpVerb)
        {
            return SimulateRequest(url, httpVerb, null, null);
        }

        /// <summary>
        /// Sets up the HttpContext objects to simulate a POST request.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="formVariables"></param>
        public HttpSimulator SimulateRequest(Uri url, NameValueCollection formVariables)
        {
            return SimulateRequest(url, HttpVerb.POST, formVariables, null);
        }

        /// <summary>
        /// Sets up the HttpContext objects to simulate a POST request.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="formVariables"></param>
        /// <param name="headers"></param>
        public HttpSimulator SimulateRequest(Uri url, NameValueCollection formVariables, NameValueCollection headers)
        {
            return SimulateRequest(url, HttpVerb.POST, formVariables, headers);
        }

        /// <summary>
        /// Sets up the HttpContext objects to simulate a request.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="httpVerb"></param>
        /// <param name="headers"></param>
        public HttpSimulator SimulateRequest(Uri url, HttpVerb httpVerb, NameValueCollection headers)
        {
            return SimulateRequest(url, httpVerb, null, headers);
        }
        
        /// <summary>
        /// Sets up the HttpContext objects to simulate a request.
        /// </summary>
        /// <param name="url"></param>
        /// <param name="httpVerb"></param>
        /// <param name="formVariables"></param>
        /// <param name="headers"></param>
        protected virtual HttpSimulator SimulateRequest(Uri url, HttpVerb httpVerb, NameValueCollection formVariables,
                                                        NameValueCollection headers)
        {
            HttpContext.Current = null;

            ParseRequestUrl(url);

            if(_responseWriter == null)
            {
                _builder = new StringBuilder();
                _responseWriter = new StringWriter(_builder);
            }

            SetHttpRuntimeInternals();

            string query = ExtractQueryStringPart(url);

            if(formVariables != null)
            {
                _formVars.Add(formVariables);
            }

            if(_formVars.Count > 0)
            {
                httpVerb = HttpVerb.POST; //Need to enforce this.
            }

            if(headers != null)
            {
                _headers.Add(headers);
            }

            _workerRequest = new SimulatedHttpRequest(ApplicationPath, PhysicalApplicationPath, PhysicalPath, Page, query,
                                                     _responseWriter, Host, Port, httpVerb.ToString());
            _workerRequest.CurrentExecutionPath = _currentExecutionPath;
            _workerRequest.Form.Add(_formVars);
            _workerRequest.Headers.Add(_headers);

            if(_referer != null)
            {
                _workerRequest.SetReferer(_referer);
            }

            InitializeSession();
            InitializeApplication();

            #region Console Debug INfo

            //Console.WriteLine("host: " + _host);
            //Console.WriteLine("virtualDir: " + applicationPath);
            //Console.WriteLine("page: " + _localPath);
            //Console.WriteLine("pathPartAfterApplicationPart: " + _page);
            //Console.WriteLine("appPhysicalDir: " + _physicalApplicationPath);
            //Console.WriteLine("Request.Url.LocalPath: " + HttpContext.Current.Request.Url.LocalPath);
            //Console.WriteLine("Request.Url.Host: " + HttpContext.Current.Request.Url.Host);
            //Console.WriteLine("Request.FilePath: " + HttpContext.Current.Request.FilePath);
            //Console.WriteLine("Request.Path: " + HttpContext.Current.Request.Path);
            //Console.WriteLine("Request.RawUrl: " + HttpContext.Current.Request.RawUrl);
            //Console.WriteLine("Request.Url: " + HttpContext.Current.Request.Url);
            //Console.WriteLine("Request.Url.Port: " + HttpContext.Current.Request.Url.Port);
            //Console.WriteLine("Request.ApplicationPath: " + HttpContext.Current.Request.ApplicationPath);
            //Console.WriteLine("Request.PhysicalPath: " + HttpContext.Current.Request.PhysicalPath);
            //Console.WriteLine("HttpRuntime.AppDomainAppPath: " + HttpRuntime.AppDomainAppPath);
            //Console.WriteLine("HttpRuntime.AppDomainAppVirtualPath: " + HttpRuntime.AppDomainAppVirtualPath);
            //Console.WriteLine("HostingEnvironment.ApplicationPhysicalPath: " + HostingEnvironment.ApplicationPhysicalPath);
            //Console.WriteLine("HostingEnvironment.ApplicationVirtualPath: " + HostingEnvironment.ApplicationVirtualPath);

            #endregion

            return this;
        }

        private static void InitializeApplication()
        {
            Type appFactoryType =
                Type.GetType(
                    "System.Web.HttpApplicationFactory, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
            var appFactory = ReflectionHelper.GetStaticFieldValue<object>("_theApplicationFactory", appFactoryType);
            ReflectionHelper.SetPrivateInstanceFieldValue("_state", appFactory, HttpContext.Current.Application);
        }

        private void InitializeSession()
        {
            HttpContext.Current = new HttpContext(_workerRequest);
            HttpContext.Current.Items.Clear();
            var session =
                (HttpSessionState)
                ReflectionHelper.Instantiate(typeof(HttpSessionState), new[] {typeof(IHttpSessionState)},
                                             new FakeHttpSessionState());

            HttpContext.Current.Items.Add("AspSession", session);
        }

        /// <summary>
        /// Sets the referer for the request. Uses a fluent interface.
        /// </summary>
        /// <param name="referer"></param>
        /// <returns></returns>
        public HttpSimulator SetReferer(Uri referer)
        {
            if(_workerRequest != null)
            {
                _workerRequest.SetReferer(referer);
            }
            _referer = referer;
            return this;
        }

        /// <summary>
        /// Sets a form variable.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public HttpSimulator SetFormVariable(string name, string value)
        {
            //TODO: Change this ordering requirement.
            if(_workerRequest != null)
            {
                throw new InvalidOperationException("Cannot set form variables after calling Simulate().");
            }

            _formVars.Add(name, value);

            return this;
        }

        /// <summary>
        /// Sets a header value.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public HttpSimulator SetHeader(string name, string value)
        {
            //TODO: Change this ordering requirement.
            if(_workerRequest != null)
            {
                throw new InvalidOperationException("Cannot set headers after calling Simulate().");
            }

            _headers.Add(name, value);

            return this;
        }

        private void ParseRequestUrl(Uri url)
        {
            if(url == null)
            {
                return;
            }
            Host = url.Host;
            Port = url.Port;
            LocalPath = url.LocalPath;
            Page = StripPrecedingSlashes(RightAfter(url.LocalPath, ApplicationPath));
            _physicalPath = Path.Combine(_physicalApplicationPath, Page.Replace("/", @"\"));
            _currentExecutionPath = "/" + StripPrecedingSlashes(url.LocalPath);
        }

        static string RightAfter(string original, string search)
        {
            if(search.Length > original.Length || search.Length == 0)
            {
                return original;
            }

            int searchIndex = original.IndexOf(search, 0, StringComparison.InvariantCultureIgnoreCase);

            if(searchIndex < 0)
            {
                return original;
            }

            return original.Substring(original.IndexOf(search) + search.Length);
        }

        private static string ExtractQueryStringPart(Uri url)
        {
            string query = url.Query ?? string.Empty;
            if(query.StartsWith("?"))
            {
                return query.Substring(1);
            }
            return query;
        }

        void SetHttpRuntimeInternals()
        {
            //We cheat by using reflection.

            // get singleton property value
            var runtime = ReflectionHelper.GetStaticFieldValue<HttpRuntime>("_theRuntime", typeof(HttpRuntime));

            // set app path property value
            ReflectionHelper.SetPrivateInstanceFieldValue("_appDomainAppPath", runtime, PhysicalApplicationPath);
            // set app virtual path property value
            const string vpathTypeName = "System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
            object virtualPath = ReflectionHelper.Instantiate(vpathTypeName, new[] {typeof(string)},
                                                              new object[] {ApplicationPath + "/"});
            ReflectionHelper.SetPrivateInstanceFieldValue("_appDomainAppVPath", runtime, virtualPath);

            // set codegen dir property value
            ReflectionHelper.SetPrivateInstanceFieldValue("_codegenDir", runtime, PhysicalApplicationPath);

            HostingEnvironment environment = GetHostingEnvironment();
            ReflectionHelper.SetPrivateInstanceFieldValue("_appPhysicalPath", environment, PhysicalApplicationPath);
            ReflectionHelper.SetPrivateInstanceFieldValue("_appVirtualPath", environment, virtualPath);
            ReflectionHelper.SetPrivateInstanceFieldValue("_configMapPath", environment, new ConfigMapPath(this));
        }

        protected static HostingEnvironment GetHostingEnvironment()
        {
            HostingEnvironment environment;
            try
            {
                environment = new HostingEnvironment();
            }
            catch(InvalidOperationException)
            {
                //Shoot, we need to grab it via reflection.
                environment = ReflectionHelper.GetStaticFieldValue<HostingEnvironment>("_theHostingEnvironment",
                                                                                       typeof(HostingEnvironment));
            }
            return environment;
        }

        ///<summary>
        ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        ///</summary>
        ///<filterpriority>2</filterpriority>
        public void Dispose()
        {
            if(HttpContext.Current != null)
            {
                HttpContext.Current = null;
            }
        }

        #region --- Text Manipulation Methods for slashes ---

        protected static string NormalizeSlashes(string s)
        {
            if(String.IsNullOrEmpty(s) || s == "/")
            {
                return "/";
            }

            s = s.Replace(@"\", "/");

            //Reduce multiple slashes in row to single.
            string normalized = Regex.Replace(s, "(/)/+", "$1");
            //Strip left.
            normalized = StripPrecedingSlashes(normalized);
            //Strip right.
            normalized = StripTrailingSlashes(normalized);
            return "/" + normalized;
        }

        protected static string StripPrecedingSlashes(string s)
        {
            return Regex.Replace(s, "^/*(.*)", "$1");
        }

        protected static string StripTrailingSlashes(string s)
        {
            return Regex.Replace(s, "(.*)/*$", "$1", RegexOptions.RightToLeft);
        }

        protected static string StripTrailingBackSlashes(string s)
        {
            if(String.IsNullOrEmpty(s))
            {
                return string.Empty;
            }
            return Regex.Replace(s, @"(.*)\\*$", "$1", RegexOptions.RightToLeft);
        }

        #endregion

        #region Nested type: ConfigMapPath

        public class ConfigMapPath : IConfigMapPath
        {
            private readonly HttpSimulator _requestSimulation;

            public ConfigMapPath(HttpSimulator simulation)
            {
                _requestSimulation = simulation;
            }

            #region IConfigMapPath Members

            public string GetMachineConfigFilename()
            {
                throw new NotImplementedException();
            }

            public string GetRootWebConfigFilename()
            {
                throw new NotImplementedException();
            }

            public void GetPathConfigFilename(string siteID, string path, out string directory, out string baseName)
            {
                throw new NotImplementedException();
            }

            public void GetDefaultSiteNameAndID(out string siteName, out string siteID)
            {
                throw new NotImplementedException();
            }

            public void ResolveSiteArgument(string siteArgument, out string siteName, out string siteID)
            {
                throw new NotImplementedException();
            }

            public string MapPath(string siteID, string path)
            {
                string page = StripPrecedingSlashes(RightAfter(path, _requestSimulation.ApplicationPath));
                return Path.Combine(_requestSimulation.PhysicalApplicationPath, page.Replace("/", @"\"));
            }

            public string GetAppPathForPath(string siteID, string path)
            {
                return _requestSimulation.ApplicationPath;
            }

            #endregion
        }

        #endregion

        #region Nested type: FakeHttpSessionState

        public class FakeHttpSessionState : NameObjectCollectionBase, IHttpSessionState
        {
            private bool isNewSession = true;
            private string sessionID = Guid.NewGuid().ToString();
            private HttpStaticObjectsCollection staticObjects = new HttpStaticObjectsCollection();
            private object syncRoot = new Object();
            private int timeout = 30; //minutes

            #region IHttpSessionState Members

            ///<summary>
            ///Ends the current session.
            ///</summary>
            ///
            public void Abandon()
            {
                BaseClear();
            }

            ///<summary>
            ///Adds a new item to the session-state collection.
            ///</summary>
            ///
            ///<param name="name">The name of the item to add to the session-state collection. </param>
            ///<param name="value">The value of the item to add to the session-state collection. </param>
            public void Add(string name, object value)
            {
                BaseAdd(name, value);
            }

            ///<summary>
            ///Deletes an item from the session-state item collection.
            ///</summary>
            ///
            ///<param name="name">The name of the item to delete from the session-state item collection. </param>
            public void Remove(string name)
            {
                BaseRemove(name);
            }

            ///<summary>
            ///Deletes an item at a specified index from the session-state item collection.
            ///</summary>
            ///
            ///<param name="index">The index of the item to remove from the session-state collection. </param>
            public void RemoveAt(int index)
            {
                BaseRemoveAt(index);
            }

            ///<summary>
            ///Clears all values from the session-state item collection.
            ///</summary>
            ///
            public void Clear()
            {
                BaseClear();
            }

            ///<summary>
            ///Clears all values from the session-state item collection.
            ///</summary>
            ///
            public void RemoveAll()
            {
                BaseClear();
            }

            ///<summary>
            ///Copies the collection of session-state item values to a one-dimensional array, starting at the specified index in the array.
            ///</summary>
            ///
            ///<param name="array">The <see cref="T:System.Array"></see> that receives the session values. </param>
            ///<param name="index">The index in array where copying starts. </param>
            public void CopyTo(Array array, int index)
            {
                throw new NotImplementedException();
            }

            ///<summary>
            ///Gets the unique session identifier for the session.
            ///</summary>
            ///
            ///<returns>
            ///The session ID.
            ///</returns>
            ///
            public string SessionID
            {
                get { return sessionID; }
            }

            ///<summary>
            ///Gets and sets the time-out period (in minutes) allowed between requests before the session-state provider terminates the session.
            ///</summary>
            ///
            ///<returns>
            ///The time-out period, in minutes.
            ///</returns>
            ///
            public int Timeout
            {
                get { return timeout; }
                set { timeout = value; }
            }

            ///<summary>
            ///Gets a value indicating whether the session was created with the current request.
            ///</summary>
            ///
            ///<returns>
            ///true if the session was created with the current request; otherwise, false.
            ///</returns>
            ///
            public bool IsNewSession
            {
                get { return isNewSession; }
            }

            ///<summary>
            ///Gets the current session-state mode.
            ///</summary>
            ///
            ///<returns>
            ///One of the <see cref="T:System.Web.SessionState.SessionStateMode"></see> values.
            ///</returns>
            ///
            public SessionStateMode Mode
            {
                get { return SessionStateMode.InProc; }
            }

            ///<summary>
            ///Gets a value indicating whether the session ID is embedded in the URL or stored in an HTTP cookie.
            ///</summary>
            ///
            ///<returns>
            ///true if the session is embedded in the URL; otherwise, false.
            ///</returns>
            ///
            public bool IsCookieless
            {
                get { return false; }
            }

            ///<summary>
            ///Gets a value that indicates whether the application is configured for cookieless sessions.
            ///</summary>
            ///
            ///<returns>
            ///One of the <see cref="T:System.Web.HttpCookieMode"></see> values that indicate whether the application is configured for cookieless sessions. The default is <see cref="F:System.Web.HttpCookieMode.UseCookies"></see>.
            ///</returns>
            ///
            public HttpCookieMode CookieMode
            {
                get { return HttpCookieMode.UseCookies; }
            }

            ///<summary>
            ///Gets or sets the locale identifier (LCID) of the current session.
            ///</summary>
            ///
            ///<returns>
            ///A <see cref="T:System.Globalization.CultureInfo"></see> instance that specifies the culture of the current session.
            ///</returns>
            ///
            public int LCID { get; set; }

            ///<summary>
            ///Gets or sets the code-page identifier for the current session.
            ///</summary>
            ///
            ///<returns>
            ///The code-page identifier for the current session.
            ///</returns>
            ///
            public int CodePage { get; set; }

            ///<summary>
            ///Gets a collection of objects declared by &lt;object Runat="Server" Scope="Session"/&gt; tags within the ASP.NET application file Global.asax.
            ///</summary>
            ///
            ///<returns>
            ///An <see cref="T:System.Web.HttpStaticObjectsCollection"></see> containing objects declared in the Global.asax file.
            ///</returns>
            ///
            public HttpStaticObjectsCollection StaticObjects
            {
                get { return staticObjects; }
            }

            ///<summary>
            ///Gets or sets a session-state item value by name.
            ///</summary>
            ///
            ///<returns>
            ///The session-state item value specified in the name parameter.
            ///</returns>
            ///
            ///<param name="name">The key name of the session-state item value. </param>
            public object this[string name]
            {
                get { return BaseGet(name); }
                set { BaseSet(name, value); }
            }

            ///<summary>
            ///Gets or sets a session-state item value by numerical index.
            ///</summary>
            ///
            ///<returns>
            ///The session-state item value specified in the index parameter.
            ///</returns>
            ///
            ///<param name="index">The numerical index of the session-state item value. </param>
            public object this[int index]
            {
                get { return BaseGet(index); }
                set { BaseSet(index, value); }
            }

            ///<summary>
            ///Gets an object that can be used to synchronize access to the collection of session-state values.
            ///</summary>
            ///
            ///<returns>
            ///An object that can be used to synchronize access to the collection.
            ///</returns>
            ///
            public object SyncRoot
            {
                get { return syncRoot; }
            }


            ///<summary>
            ///Gets a value indicating whether access to the collection of session-state values is synchronized (thread safe).
            ///</summary>
            ///<returns>
            ///true if access to the collection is synchronized (thread safe); otherwise, false.
            ///</returns>
            ///
            public bool IsSynchronized
            {
                get { return true; }
            }

            ///<summary>
            ///Gets a value indicating whether the session is read-only.
            ///</summary>
            ///
            ///<returns>
            ///true if the session is read-only; otherwise, false.
            ///</returns>
            ///
            bool IHttpSessionState.IsReadOnly
            {
                get { return true; }
            }

            #endregion
        }

        #endregion
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.