Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Hosting;
using MonoTests.stand_alone.WebHarness;
namespace StandAloneRunnerSupport
{
public sealed class Helpers
{
public const string BEGIN_CODE_MARKER = "<!-- @CODE_BEGIN@ -->";
public const string END_CODE_MARKER = "<!-- @CODE_END@ -->";
public static string ExtractCodeFromHtml (string html)
{
AppDomain ad = AppDomain.CurrentDomain;
return HtmlDiff.GetControlFromPageHtml (html, BEGIN_CODE_MARKER, END_CODE_MARKER);
}
public static void ExtractAndCompareCodeFromHtml (string html, string original, string msg)
{
string rendered = ExtractCodeFromHtml (html);
HtmlDiff.AssertAreEqual (original, rendered, msg);
}
public static string StripWebResourceAxdQuery (string origHtml)
{
return StripWebResourceAxdQuery (StripWebResourceAxdQuery (origHtml, "\""), "&quot;");
}
static string StripWebResourceAxdQuery (string origHtml, string delimiter)
{
if (String.IsNullOrEmpty (origHtml))
return origHtml;
// Naive approach, enough for now
return new Regex (delimiter + "/WebResource\\.axd.*?" + delimiter).Replace (origHtml, delimiter + "/WebResource.axd" + delimiter);
}
public static bool HasException (string html, Type exceptionType)
{
if (exceptionType == null)
throw new ArgumentNullException ("exceptionType");
return HasException (html, exceptionType.FullName);
}
public static bool HasException (string html, string exceptionType)
{
if (String.IsNullOrEmpty (exceptionType))
throw new ArgumentNullException ("exceptionType");
if (String.IsNullOrEmpty (html))
return false;
return html.IndexOf ("[" + exceptionType + "]:") != -1;
}
}
}

View File

@@ -0,0 +1,40 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
namespace StandAloneRunnerSupport
{
public interface ITestCase
{
string PhysicalPath { get; }
string VirtualPath { get; }
bool SetUp (List <TestRunItem> runItems);
}
}

View File

@@ -0,0 +1,40 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.IO;
using System.Web;
using System.Web.Hosting;
namespace StandAloneRunnerSupport
{
public interface ITestRunner
{
object TestRunData { get; }
AppDomain Domain { get; }
}
}

View File

@@ -0,0 +1,94 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
namespace StandAloneRunnerSupport
{
[Serializable]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema ()
{
return null;
}
public void ReadXml (XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer (typeof (TKey));
XmlSerializer valueSerializer = new XmlSerializer (typeof (TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read ();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement) {
reader.ReadStartElement ("item");
reader.ReadStartElement ("key");
TKey key = (TKey) keySerializer.Deserialize (reader);
reader.ReadEndElement ();
reader.ReadStartElement ("value");
TValue value = (TValue) valueSerializer.Deserialize (reader);
reader.ReadEndElement ();
this.Add (key, value);
reader.ReadEndElement ();
reader.MoveToContent ();
}
reader.ReadEndElement ();
}
public void WriteXml (XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer (typeof (TKey));
XmlSerializer valueSerializer = new XmlSerializer (typeof (TValue));
foreach (TKey key in this.Keys) {
writer.WriteStartElement ("item");
writer.WriteStartElement ("key");
keySerializer.Serialize (writer, key);
writer.WriteEndElement ();
writer.WriteStartElement ("value");
TValue value = this [key];
valueSerializer.Serialize (writer, value);
writer.WriteEndElement ();
writer.WriteEndElement ();
}
}
}
}

View File

@@ -0,0 +1,322 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Xml;
using MonoTests.SystemWeb.Framework;
using NUnit.Framework;
namespace StandAloneRunnerSupport
{
public sealed class StandaloneTest
{
const string HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
string failureDetails;
public TestCaseFailureException Exception {
get; private set;
}
public string FailureDetails {
get {
if (!String.IsNullOrEmpty (failureDetails))
return failureDetails;
TestCaseFailureException ex = Exception;
if (ex == null)
return String.Empty;
return ex.Details;
}
private set {
failureDetails = value;
}
}
public string FailedUrl {
get; private set;
}
public string FailedUrlDescription {
get; private set;
}
public string FailedUrlCallbackName {
get; private set;
}
public TestCaseAttribute Info {
get; private set;
}
public bool Success {
get; private set;
}
public Type TestType {
get; private set;
}
public StandaloneTest (Type testType, TestCaseAttribute info)
{
if (testType == null)
throw new ArgumentNullException ("testType");
if (info == null)
throw new ArgumentNullException ("info");
TestType = testType;
Info = info;
}
public void Run (ApplicationManager appMan, bool verbose)
{
try {
Success = true;
RunInternal (appMan, verbose);
} catch (TestCaseFailureException ex) {
Exception = ex;
Success = false;
} catch (Exception ex) {
FailureDetails = String.Format ("Test failed with exception of type '{0}':{1}{2}",
ex.GetType (), Environment.NewLine, ex.ToString ());
Success = false;
}
}
void RunInternal (ApplicationManager appMan, bool verbose)
{
ITestCase test = Activator.CreateInstance (TestType) as ITestCase;
var runItems = new List <TestRunItem> ();
if (!test.SetUp (runItems)) {
Success = false;
FailureDetails = "Test aborted in setup phase.";
return;
}
if (runItems.Count == 0) {
Success = false;
FailureDetails = "No test run items returned by the test case.";
return;
}
Response response, previousResponse = null;
TestRunner runner;
string[] formValues;
try {
Console.Write ('[');
if (verbose)
Console.WriteLine ("{0} ({1}: {2})]", TestType, Info.Name, Info.Description);
foreach (var tri in runItems) {
if (tri == null)
continue;
if (verbose)
Console.Write ("\t{0} ({1}) ", tri.Callback != null ? tri.Callback.Method.ToString () : "<null>",
!String.IsNullOrEmpty (tri.UrlDescription) ? tri.UrlDescription : tri.Url);
runner = null;
response = null;
try {
runner = appMan.CreateObject (Info.Name, typeof (TestRunner), test.VirtualPath, test.PhysicalPath, true) as TestRunner;
if (runner == null) {
Success = false;
throw new InvalidOperationException ("runner must not be null.");
}
if (tri.PostValues != null && previousResponse != null)
formValues = ExtractFormAndHiddenControls (previousResponse);
else
formValues = null;
SetRunnerDomainData (tri.AppDomainData, runner.Domain);
response = runner.Run (tri.Url, tri.PathInfo, tri.PostValues, formValues);
if (tri.Callback == null)
continue;
tri.TestRunData = runner.TestRunData;
tri.StatusCode = runner.StatusCode;
tri.Redirected = runner.Redirected;
tri.RedirectLocation = runner.RedirectLocation;
if (tri.Callback != null)
tri.Callback (response.Body, tri);
Console.Write ('.');
} catch (Exception) {
FailedUrl = tri.Url;
FailedUrlDescription = tri.UrlDescription;
if (tri.Callback != null) {
MethodInfo mi = tri.Callback.Method;
FailedUrlCallbackName = FormatMethodName (mi);
}
Console.Write ('F');
throw;
} finally {
if (runner != null) {
runner.Stop (true);
AppDomain.Unload (runner.Domain);
}
runner = null;
previousResponse = response;
}
}
} catch (AssertionException ex) {
throw new TestCaseFailureException ("Assertion failed.", ex.Message, ex);
} finally {
if (verbose)
Console.WriteLine ();
else
Console.Write (']');
}
}
void SetRunnerDomainData (object[] data, AppDomain domain)
{
int len = data != null ? data.Length : 0;
if (len == 0)
return;
if (len % 2 != 0)
throw new ArgumentException ("Must have an even number of elements.", "data");
string name;
for (int i = 0; i < len; i += 2) {
name = data [i] as string;
if (String.IsNullOrEmpty (name))
throw new InvalidOperationException (String.Format ("Name at index {0} must not be null or empty.", i));
domain.SetData (name, data [i + 1]);
}
}
string[] ExtractFormAndHiddenControls (Response response)
{
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument ();
htmlDoc.LoadHtml (response.Body);
var tempxml = new StringBuilder ();
var tsw = new StringWriter (tempxml);
htmlDoc.OptionOutputAsXml = true;
htmlDoc.Save (tsw);
var doc = new XmlDocument ();
doc.LoadXml (tempxml.ToString ());
XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
nsmgr.AddNamespace ("html", HTML_NAMESPACE);
XmlNode formNode = doc.SelectSingleNode ("//html:form", nsmgr);
if (formNode == null)
throw new ArgumentException ("Form was not found in document: " + response.Body);
string actionUrl = formNode.Attributes ["action"].Value;
XmlNode method = formNode.Attributes ["method"];
var data = new List <string> ();
string name, value;
foreach (XmlNode inputNode in doc.SelectNodes ("//html:input[@type='hidden']", nsmgr)) {
name = inputNode.Attributes["name"].Value;
if (String.IsNullOrEmpty (name))
continue;
XmlAttribute attr = inputNode.Attributes["value"];
if (attr != null)
value = attr.Value;
else
value = String.Empty;
data.Add (name);
data.Add (value);
}
return data.ToArray ();
}
static bool ShouldPrintFullName (Type type)
{
return type.IsClass && (!type.IsPointer || (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
}
string FormatMethodName (MethodInfo mi)
{
var sb = new StringBuilder ();
Type retType = mi.ReturnType;
if (ShouldPrintFullName (retType))
sb.Append (retType.ToString ());
else
sb.Append (retType.Name);
sb.Append (" ");
sb.Append (mi.DeclaringType.FullName);
sb.Append ('.');
sb.Append (mi.Name);
if (mi.IsGenericMethod) {
Type[] gen_params = mi.GetGenericArguments ();
sb.Append ("<");
for (int j = 0; j < gen_params.Length; j++) {
if (j > 0)
sb.Append (",");
sb.Append (gen_params [j].Name);
}
sb.Append (">");
}
sb.Append ("(");
ParameterInfo[] p = mi.GetParameters ();
for (int i = 0; i < p.Length; ++i) {
if (i > 0)
sb.Append (", ");
Type pt = p[i].ParameterType;
bool byref = pt.IsByRef;
if (byref)
pt = pt.GetElementType ();
if (ShouldPrintFullName (pt))
sb.Append (pt.ToString ());
else
sb.Append (pt.Name);
if (byref)
sb.Append (" ref");
}
if ((mi.CallingConvention & CallingConventions.VarArgs) != 0) {
if (p.Length > 0)
sb.Append (", ");
sb.Append ("...");
}
sb.Append (")");
return sb.ToString ();
}
}
}

View File

@@ -0,0 +1,33 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace StandAloneRunnerSupport
{
public delegate void TestCallback (string result, TestRunItem runItem);
}

View File

@@ -0,0 +1,63 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.InteropServices;
namespace StandAloneRunnerSupport
{
[AttributeUsage (AttributeTargets.Class)]
[Serializable]
public class TestCaseAttribute : Attribute
{
public string Description {
get; set;
}
public bool Disabled {
get; set;
}
public string Name {
get; set;
}
public TestCaseAttribute (string name)
: this (name, null)
{
}
public TestCaseAttribute (string name, string description)
{
if (String.IsNullOrEmpty (name))
throw new ArgumentNullException ("name");
Description = description;
Name = name;
}
}
}

View File

@@ -0,0 +1,56 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace StandAloneRunnerSupport
{
public class TestCaseFailureException : Exception
{
public string Details {
get; set;
}
public TestCaseFailureException (string message)
: this (message, null, null)
{}
public TestCaseFailureException (string message, string details)
: this (message, details, null)
{}
public TestCaseFailureException (string message, Exception innerException)
: this (message, null, innerException)
{}
public TestCaseFailureException (string message, string details, Exception innerException)
: base (message, innerException)
{
Details = details;
}
}
}

View File

@@ -0,0 +1,100 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Hosting;
namespace StandAloneRunnerSupport
{
public sealed class TestRunItem
{
public TestCallback Callback {
get; set;
}
public object TestRunData {
get; set;
}
public string Url {
get; set;
}
public string PathInfo {
get; set;
}
public string UrlDescription {
get; set;
}
#if BUG_IN_THE_RUNTIME_IS_FIXED
public SerializedDictionary <string, string> PostValues {
get; set;
}
#else
public string[] PostValues {
get; set;
}
#endif
public int StatusCode {
get; set;
}
public string RedirectLocation {
get; set;
}
public bool Redirected {
get; set;
}
#if BUG_IN_THE_RUNTIME_IS_FIXED
public SerializedDictionary <string, object> AppDomainData {
get; set;
}
#else
public object[] AppDomainData {
get; set;
}
#endif
public TestRunItem ()
: this (null, null, null)
{}
public TestRunItem (string url, TestCallback callback)
: this (url, null, callback)
{}
public TestRunItem (string url, string urlDescription, TestCallback callback)
{
Url = url;
Callback = callback;
UrlDescription = urlDescription;
}
}
}

View File

@@ -0,0 +1,127 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Hosting;
using MonoTests.SystemWeb.Framework;
namespace StandAloneRunnerSupport
{
public sealed class TestRunner : MarshalByRefObject, IRegisteredObject, ITestRunner
{
public AppDomain Domain {
get { return AppDomain.CurrentDomain; }
}
public object TestRunData {
get { return Domain.GetData ("TestRunData"); }
}
public int StatusCode { get; private set; }
public string RedirectLocation { get; private set; }
public bool Redirected { get; private set; }
public TestRunner ()
{
}
#if BUG_IN_THE_RUNTIME_IS_FIXED
public Response Run (string url, string pathInfo, SerializableDictionary <string, string> postValues)
#else
public Response Run (string url, string pathInfo, string[] postValues, string[] formValues)
#endif
{
if (String.IsNullOrEmpty (url))
throw new ArgumentNullException ("url");
bool isPost = postValues != null;
ResetState ();
if (String.IsNullOrEmpty (url))
throw new ArgumentNullException ("url");
var output = new StringWriter ();
try {
string fullUrl = "http://localhost";
if (url [0] == '/')
fullUrl += url;
else
fullUrl += "/" + url;
Uri uri = new Uri (fullUrl, UriKind.RelativeOrAbsolute);
string query = uri.Query;
if (!String.IsNullOrEmpty (query) && query [0] == '?')
query = query.Substring (1);
TestWorkerRequest wr;
if (pathInfo != null)
wr = new TestWorkerRequest (uri.AbsolutePath, query, pathInfo, output);
else
wr = new TestWorkerRequest (uri.AbsolutePath, query, output);
wr.IsPost = isPost;
if (isPost) {
wr.AppendPostData (formValues, true);
wr.AppendPostData (postValues, false);
}
HttpRuntime.ProcessRequest (wr);
StatusCode = (int) wr.StatusCode;
Redirected = wr.Redirected;
RedirectLocation = wr.RedirectLocation;
return new Response {
Body = output.ToString (),
StatusCode = wr.StatusCode,
StatusDescription = wr.StatusDescription
};
} finally {
output.Close ();
}
}
public void Stop (bool immediate)
{
HostingEnvironment.UnregisterObject (this);
}
void ResetState ()
{
AppDomain ad = Domain;
ad.SetData ("BEGIN_CODE_MARKER", Helpers.BEGIN_CODE_MARKER);
ad.SetData ("END_CODE_MARKER", Helpers.END_CODE_MARKER);
ad.SetData ("TestRunData", null);
}
}
}

View File

@@ -0,0 +1,200 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2010 Novell, Inc http://novell.com/
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Hosting;
namespace StandAloneRunnerSupport
{
sealed class TestWorkerRequest : SimpleWorkerRequest
{
const string POST_CONTENT_TYPE = "application/x-www-form-urlencoded";
static readonly char[] vpathTrimChars = { '/' };
string page;
string query;
string appVirtualDir;
string pathInfo;
byte[] entityBody;
SortedDictionary <string, string> originalPostData;
public bool IsPost { get; set; }
public HttpStatusCode StatusCode { get; set; }
public string StatusDescription { get; set; }
public string RedirectLocation { get; set; }
public bool Redirected {
get {
int code = (int) StatusCode;
return code == 301 || code == 302;
}
}
public TestWorkerRequest (string page, string query, TextWriter output)
: this (page, query, null, output)
{
}
public TestWorkerRequest (string page, string query, string pathInfo, TextWriter output)
: base (page, query, output)
{
this.page = page;
this.query = query;
this.appVirtualDir = GetAppPath ();
this.pathInfo = pathInfo;
}
public override string GetFilePath ()
{
return page;
}
public override string GetHttpVerbName ()
{
if (IsPost)
return "POST";
return base.GetHttpVerbName ();
}
public override string GetKnownRequestHeader (int index)
{
if (!IsPost || entityBody == null)
return base.GetKnownRequestHeader (index);
switch (index) {
case HttpWorkerRequest.HeaderContentLength:
return entityBody.Length.ToString ();
case HttpWorkerRequest.HeaderContentType:
return POST_CONTENT_TYPE;
default:
return base.GetKnownRequestHeader (index);
}
}
public override byte[] GetPreloadedEntityBody ()
{
if (!IsPost || entityBody == null)
return base.GetPreloadedEntityBody ();
return entityBody;
}
public override string GetPathInfo ()
{
if (pathInfo == null)
return base.GetPathInfo ();
return pathInfo;
}
public override string GetRawUrl ()
{
return TrimLeadingSlash (base.GetRawUrl ());
}
public override string GetUriPath ()
{
return TrimLeadingSlash (base.GetUriPath ());
}
public override void SendKnownResponseHeader (int index, string value)
{
if (index == HttpWorkerRequest.HeaderLocation)
RedirectLocation = value;
base.SendKnownResponseHeader (index, value);
}
public override void SendStatus (int code, string description)
{
StatusCode = (HttpStatusCode) code;
StatusDescription = description;
base.SendStatus (code, description);
}
public void AppendPostData (string[] postData, bool isEncoded)
{
int len = postData != null ? postData.Length : 0;
if (len == 0)
return;
if (len % 2 != 0)
throw new InvalidOperationException ("POST data array must have an even number of elements.");
if (originalPostData == null)
originalPostData = new SortedDictionary <string, string> ();
string key, value;
for (int i = 0; i < len; i += 2) {
key = postData [i];
value = postData [i + 1];
if (originalPostData.ContainsKey (key))
originalPostData [key] = value;
else
originalPostData.Add (key, value);
}
len = originalPostData.Count;
var sb = new StringBuilder ();
bool first = true;
foreach (var de in originalPostData) {
if (first)
first = false;
else
sb.Append ('&');
key = de.Key;
value = de.Value;
sb.Append (isEncoded ? key : HttpUtility.UrlEncode (key));
sb.Append ('=');
if (!String.IsNullOrEmpty (value))
sb.Append (isEncoded ? value : HttpUtility.UrlEncode (value));
}
entityBody = Encoding.ASCII.GetBytes (sb.ToString ());
}
static string TrimLeadingSlash (string input)
{
if (String.IsNullOrEmpty (input))
return input;
return "/" + input.TrimStart (vpathTrimChars);
}
}
}