diff --git a/Configuration.props b/Configuration.props index 93e4dd6f603..2775e40ccd4 100644 --- a/Configuration.props +++ b/Configuration.props @@ -16,5 +16,7 @@ v6.0 $(HOME)\android-archives $(HOME)\android-toolchain + $(AndroidToolchainDirectory)\sdk + $(AndroidToolchainDirectory)\ndk diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index 23b12182d09..19ed2361d0d 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -53,7 +53,7 @@ Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "monodroid", "src\monodroid\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "api-xml-adjuster", "tools\api-xml-adjuster\api-xml-adjuster.csproj", "{8A6CB07C-E493-4A4F-AB94-038645A27118}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{99CBCF85-E4EB-41C8-9089-1A2B740681F0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.NUnitLite", "src\Xamarin.Android.NUnitLite\Xamarin.Android.NUnitLite.csproj", "{4D603AA3-3BFD-43C8-8050-0CD6C2601126}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -196,6 +196,18 @@ Global {E8492EFB-D14A-4F32-AA28-88848322ECEA}.XAIntegrationDebug|Any CPU.Build.0 = Debug|Any CPU {E8492EFB-D14A-4F32-AA28-88848322ECEA}.XAIntegrationRelease|Any CPU.ActiveCfg = Debug|Any CPU {E8492EFB-D14A-4F32-AA28-88848322ECEA}.XAIntegrationRelease|Any CPU.Build.0 = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.Release|AnyCPU.Build.0 = Release|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationDebug|Any CPU.ActiveCfg = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationDebug|Any CPU.Build.0 = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationRelease|Any CPU.ActiveCfg = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationRelease|Any CPU.Build.0 = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationDebug|AnyCPU.ActiveCfg = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationDebug|AnyCPU.Build.0 = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationRelease|AnyCPU.ActiveCfg = Debug|Any CPU + {4D603AA3-3BFD-43C8-8050-0CD6C2601126}.XAIntegrationRelease|AnyCPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} @@ -221,6 +233,7 @@ Global {D48EE8D0-0A0A-4493-AEF5-DAF5F8CF86AD} = {864062D3-A415-4A6F-9324-5820237BA058} {53EE4C57-1C03-405A-8243-8DA539546C88} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {8A6CB07C-E493-4A4F-AB94-038645A27118} = {864062D3-A415-4A6F-9324-5820237BA058} + {4D603AA3-3BFD-43C8-8050-0CD6C2601126} = {04E3E11E-B47D-4599-8AFC-50515A95E715} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 diff --git a/src/Xamarin.Android.NUnitLite/Gui/Activities/OptionsActivity.cs b/src/Xamarin.Android.NUnitLite/Gui/Activities/OptionsActivity.cs new file mode 100644 index 00000000000..7712a408993 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/Activities/OptionsActivity.cs @@ -0,0 +1,72 @@ +// +// Copyright 2011-2012 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; + +using Android.App; +using Android.Content; +using Android.Content.PM; +using Android.OS; +using Android.Views; +using Android.Widget; + +namespace Xamarin.Android.NUnitLite { + + [Activity (Label = "Options", WindowSoftInputMode = SoftInput.AdjustPan, + ConfigurationChanges = ConfigChanges.KeyboardHidden | ConfigChanges.Orientation)] + internal class OptionsActivity : Activity { + CheckBox remote; + TextView host_name; + TextView host_port; + + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + SetContentView (Resource.Layout.options); + + Options options = AndroidRunner.Runner.Options; + remote = FindViewById (Resource.Id.OptionRemoteServer); + remote.Checked = options.EnableNetwork; + host_name = FindViewById (Resource.Id.OptionHostName); + host_name.Text = options.HostName; + host_port = FindViewById (Resource.Id.OptionPort); + host_port.Text = options.HostPort.ToString (); + + base.OnCreate (bundle); + } + + int GetPort () + { + int port; + ushort p; + if (UInt16.TryParse (host_port.Text, out p)) + port = p; + else + port = -1; + return port; + } + + protected override void OnPause () + { + Options options = AndroidRunner.Runner.Options; + options.EnableNetwork = remote.Checked; + options.HostName = host_name.Text; + options.HostPort = GetPort (); + options.Save (this); + base.OnPause (); + } + } +} \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/Gui/Activities/TestResultActivity.cs b/src/Xamarin.Android.NUnitLite/Gui/Activities/TestResultActivity.cs new file mode 100644 index 00000000000..8208fdc0f8d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/Activities/TestResultActivity.cs @@ -0,0 +1,54 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Android.Text.Method; +using NUnit.Framework.Internal; +using NUnitTest = NUnit.Framework.Internal.Test; + +namespace Xamarin.Android.NUnitLite +{ + [Activity (Label = "Test Result")] + internal class TestResultActivity : Activity + { + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + // Create your application here + SetContentView (Resource.Layout.test_result); + + var testName = this.Intent.GetStringExtra ("test"); + var parentSuiteName = testName.Substring (0, testName.LastIndexOf ('.')); + + FindViewById (Resource.Id.ResultRunSingleMethodTest).Click += delegate { + AndroidRunner.Runner.Run ((NUnitTest) AndroidRunner.Suites [parentSuiteName].Tests.First (t => t.FullName == testName), this); + UpdateData (AndroidRunner.Results [testName]); + }; + if (AndroidRunner.Results.ContainsKey (testName)) + UpdateData (AndroidRunner.Results [testName]); + else + FindViewById (Resource.Id.ResultFullName).Text = testName; + } + + void UpdateData (TestResult test) + { + if (test == null) + return; // no result to fill + FindViewById (Resource.Id.ResultFullName).Text = test.FullName; + FindViewById (Resource.Id.ResultResultState).Text = test.ResultState.ToString (); + FindViewById (Resource.Id.ResultMessage).Text= test.Message; + FindViewById (Resource.Id.ResultStackTrace).Text = test.StackTrace; + FindViewById (Resource.Id.ResultStackTrace).MovementMethod = new ScrollingMovementMethod (); + } + } +} + diff --git a/src/Xamarin.Android.NUnitLite/Gui/Activities/TestSuiteActivity.cs b/src/Xamarin.Android.NUnitLite/Gui/Activities/TestSuiteActivity.cs new file mode 100644 index 00000000000..5f213b99efe --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/Activities/TestSuiteActivity.cs @@ -0,0 +1,238 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; + +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Util; +using Android.Views; +using Android.Widget; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +using NUnitTest = NUnit.Framework.Internal.Test; +using Android.Text; +using Java.Lang; +using Android.Graphics; + +namespace Xamarin.Android.NUnitLite +{ + [Activity (Label = "NUnitLite runner")] + public class TestSuiteActivity : Activity + { + static readonly string [] from_cols = {"id", "passed", "failed", "ignored", "inconclusive", "result", "message"}; + static readonly int [] to_ids = { Resource.Id.ResultsId, Resource.Id.ResultsPassed, Resource.Id.ResultsFailed, Resource.Id.ResultsIgnored, Resource.Id.ResultsInconclusive, Resource.Id.ResultsResult, Resource.Id.ResultsMessage }; + + protected bool GCAfterEachFixture { + get { return AndroidRunner.Runner.GCAfterEachFixture; } + set { AndroidRunner.Runner.GCAfterEachFixture = value; } + } + + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + SetContentView (Resource.Layout.test_suite); + + var lv = FindViewById (Resource.Id.TestSuiteListView); + var data = new JavaList> (); + + UpdateData (data, lv); + + var automated = this.Intent.GetBooleanExtra ("automated", false); + if (automated) { + AndroidRunner.Runner.Options.LoadFromBundle (Intent.Extras); + } + AndroidRunner.Runner.AddTestFilters (GetIncludedCategories (), GetExcludedCategories ()); + + FindViewById (Resource.Id.RunTestsButton).Click += (o, e) => { + AndroidRunner.Runner.Run (current_test, this); + UpdateData (data, lv); + }; + FindViewById (Resource.Id.OptionsButton).Click += (o, e) => { + var intent = new Intent (this, typeof (OptionsActivity)); + intent.AddFlags (ActivityFlags.NewTask); + this.StartActivityForResult (intent, (int) Result.Ok); + }; + + lv.ItemClick += (sender, e) => { + var item = (TestData) ((SimpleAdapter) lv.Adapter).GetItem (e.Position); + if (AndroidRunner.Suites.ContainsKey (item.Id)) { + var intent = new Intent (this, typeof (TestSuiteActivity)); + intent.AddFlags (ActivityFlags.NewTask); + intent.PutExtra ("suite", item.Id); + this.StartActivityForResult (intent, (int) Result.Ok); + } else { + var intent = new Intent (this, typeof (TestResultActivity)); + intent.AddFlags (ActivityFlags.NewTask); + intent.PutExtra ("test", item.Id); + this.StartActivityForResult (intent, (int) Result.Ok); + } + }; + + AndroidRunner.Runner.Initialized = true; + if (automated) { + System.Threading.ThreadPool.QueueUserWorkItem (delegate { + Log.Info ("NUnitLite", "NUnit automated tests started"); + AndroidRunner.Runner.Run (current_test, this); + Log.Info ("NUnitLite", "NUnit automated tests completed"); + Finish (); + }); + } + Log.Info ("NUnitLite", "NUnit automated tests loaded."); + } + + protected override void OnResume () + { + base.OnResume (); + var lv = FindViewById (Resource.Id.TestSuiteListView); + var data = new JavaList> (); + UpdateData (data, lv); + } + + protected virtual IEnumerable GetIncludedCategories () + { + return null; + } + + protected virtual IEnumerable GetExcludedCategories () + { + return null; + } + + public void AddTest (Assembly assembly) + { + AndroidRunner.Runner.AddTest (assembly); + } + + IEnumerable GetChildTests (NUnitTest test) + { + if (test is TestSuite) + foreach (NUnitTest child in ((TestSuite) test).Tests) + yield return child; + else + yield return test; + } + + void UpdateData (JavaList> data, ListView lv) + { + data.Clear (); + var testTarget = SetupTestTarget (); + foreach (var test in GetChildTests (testTarget)) { + TestResult res; + AndroidRunner.Results.TryGetValue (test.FullName, out res); + if (test is TestSuite) { + var suite = test as TestSuite; + data.Add (new TestData (suite.FullName, + res != null && res.PassCount > 0 ? res.PassCount + " passed" : null, + res != null && res.FailCount > 0 ? res.FailCount + " failed" : null, + res != null && res.SkipCount > 0 ? res.SkipCount + " ignored" : null, + res != null && res.InconclusiveCount > 0 ? res.InconclusiveCount + " inconclusive" : null, + res == null ? null : res.ResultState.Status.ToString (), res == null ? null : res.Message)); + } else if (test is NUnitTest) + data.Add (new TestData (test.FullName, null, null, null, null, res == null ? null : res.ResultState.Status.ToString (), res == null ? null : res.Message)); + } + lv.Adapter = new TestDataAdapter (this, data, Resource.Layout.results, from_cols, to_ids); + } + + class TestDataAdapter : SimpleAdapter + { + JavaList> data; + + public TestDataAdapter (Context ctx, JavaList> data, int resId, string [] fromCols, int [] toIds) + : base (ctx, data, resId, fromCols, toIds) + { + this.data = data; + } + + public override View GetView (int position, View convertView, ViewGroup parent) + { + var view = base.GetView (position, convertView, parent); + var tv = view.FindViewById (Resource.Id.ResultsResult); + TestStatus status; + System.Enum.TryParse ((string) data [position] ["result"], out status); + tv.SetTextColor (GetStatusColor (status)); + return view; + } + + static Color GetStatusColor (TestStatus status) + { + switch (status) { + case TestStatus.Passed: + return Color.Green; + case TestStatus.Failed: + return Color.Red; + case TestStatus.Skipped: + return Color.Yellow; + case TestStatus.Inconclusive: + return Color.Blue; + default: + return Color.White; + } + } + } + + class TestData : JavaDictionary + { + public TestData (string id, string passed, string failed, string ignored, string inconclusive, string result, string message) + { + Id = id; + Passed = passed; + Failed = failed; + Ignored = ignored; + Inconclusive = inconclusive; + Result = result; + Message = message; + } + + public string Id { + get { return (string) this ["id"]; } + set { this ["id"] = value; } + } + + public string Passed { + get { return (string) this ["passed"]; } + set { this ["passed"] = value; } + } + + public string Failed { + get { return (string) this ["failed"]; } + set { this ["failed"] = value; } + } + + public string Ignored { + get { return (string) this ["ignored"]; } + set { this ["ignored"] = value; } + } + + public string Inconclusive { + get { return (string) this ["inconclusive"]; } + set { this ["inconclusive"] = value; } + } + + public string Result { + get { return (string) this ["result"]; } + set { this ["result"] = value; } + } + + public string Message { + get { return (string) this ["message"]; } + set { this ["message"] = value; } + } + } + + NUnitTest current_test; + + NUnitTest SetupTestTarget () + { + if (current_test == null) + current_test = AndroidRunner.GetSetupTestTarget (Intent); + return current_test; + } + } +} + diff --git a/src/Xamarin.Android.NUnitLite/Gui/AndroidRunner.cs b/src/Xamarin.Android.NUnitLite/Gui/AndroidRunner.cs new file mode 100644 index 00000000000..ace2af361e2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/AndroidRunner.cs @@ -0,0 +1,399 @@ +// +// Copyright 2011-2012 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Sockets; + +using Android.Content; +using Android.OS; +using Android.Util; +using Android.Widget; + +using NUnitLite; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.WorkItems; +using NUnit.Framework.Internal.Filters; +using System.Reflection; +using System.Collections; + +using NUnitTest = NUnit.Framework.Internal.Test; + +namespace Xamarin.Android.NUnitLite +{ + internal class AndroidRunner : ITestListener, ITestFilter + { + const string TAG = "NUnitLite"; + + Options options; + NUnitLiteTestAssemblyBuilder builder = new NUnitLiteTestAssemblyBuilder (); + Dictionary empty = new Dictionary (); + int passed, failed, skipped, inconclusive; + + public List Assemblies = new List (); + + public AndroidRunner () + { + } + + public bool AutoStart { get; set; } + + public bool TerminateAfterExecution { get; set; } + + public Options Options { + get { + if (options == null) + options = new Options (); + return options; + } + set { options = value; } + } + + public bool GCAfterEachFixture { get; set; } + + public TestSuite LoadAssembly (string assemblyName, IDictionary settings) + { + return builder.Build (assemblyName, settings ?? empty); + } + + public TestSuite LoadAssembly (Assembly assembly, IDictionary settings) + { + return builder.Build (assembly, settings ?? empty); + } + + #region writer + + public TextWriter Writer { get; set; } + + public bool OpenWriter (string message, Context activity) + { + passed = 0; + failed = 0; + skipped = 0; + inconclusive = 0; + + DateTime now = DateTime.Now; + // let the application provide it's own TextWriter to ease automation with AutoStart property + if (Writer == null) { + if (Options.ShowUseNetworkLogger) { + Console.WriteLine ("[{0}] Sending '{1}' results to {2}:{3}", now, message, Options.HostName, Options.HostPort); + try { + Writer = new TcpTextWriter (Options.HostName, Options.HostPort); + } catch (SocketException) { + string msg = String.Format ("Cannot connect to {0}:{1}. Start network service or disable network option", options.HostName, options.HostPort); + Toast.MakeText (activity, msg, ToastLength.Long).Show (); + return false; + } + } else { + Writer = Console.Out; + } + } + + Writer.WriteLine ("[Runner executing:\t{0}]", message); + + // FIXME: provide valid MFA version + Writer.WriteLine ("[M4A Version:\t{0}]", "???"); + + Writer.WriteLine ("[Board:\t\t{0}]", Build.Board); +#if __ANDROID_8__ + if (((int) Build.VERSION.SdkInt) >= 8) { + Writer.WriteLine ("[Bootloader:\t{0}]", Build.Bootloader); + } +#endif + Writer.WriteLine ("[Brand:\t\t{0}]", Build.Brand); + string cpuAbi = Build.CpuAbi; +#if __ANDROID_8__ + if (((int) Build.VERSION.SdkInt) >= 8) { + cpuAbi += " " + Build.CpuAbi2; + } +#endif + Writer.WriteLine ("[CpuAbi:\t{0}]", cpuAbi); + Writer.WriteLine ("[Device:\t{0}]", Build.Device); + Writer.WriteLine ("[Display:\t{0}]", Build.Display); + Writer.WriteLine ("[Fingerprint:\t{0}]", Build.Fingerprint); +#if __ANDROID_8__ + if (((int) Build.VERSION.SdkInt) >= 8) { + Writer.WriteLine ("[Hardware:\t{0}]", Build.Hardware); + } +#endif + Writer.WriteLine ("[Host:\t\t{0}]", Build.Host); + Writer.WriteLine ("[Id:\t\t{0}]", Build.Id); + Writer.WriteLine ("[Manufacturer:\t{0}]", Build.Manufacturer); + Writer.WriteLine ("[Model:\t\t{0}]", Build.Model); + Writer.WriteLine ("[Product:\t{0}]", Build.Product); +#if __ANDROID_8__ + if (((int) Build.VERSION.SdkInt) >= 8) { + Writer.WriteLine ("[Radio:\t\t{0}]", Build.Radio); + } +#endif + Writer.WriteLine ("[Tags:\t\t{0}]", Build.Tags); + Writer.WriteLine ("[Time:\t\t{0}]", Build.Time); + Writer.WriteLine ("[Type:\t\t{0}]", Build.Type); + Writer.WriteLine ("[User:\t\t{0}]", Build.User); + Writer.WriteLine ("[VERSION.Codename:\t{0}]", Build.VERSION.Codename); + Writer.WriteLine ("[VERSION.Incremental:\t{0}]", Build.VERSION.Incremental); + Writer.WriteLine ("[VERSION.Release:\t{0}]", Build.VERSION.Release); + Writer.WriteLine ("[VERSION.Sdk:\t\t{0}]", Build.VERSION.Sdk); + Writer.WriteLine ("[VERSION.SdkInt:\t{0}]", Build.VERSION.SdkInt); + Writer.WriteLine ("[Device Date/Time:\t{0}]", now); // to match earlier C.WL output + + // FIXME: add data about how the app was compiled (e.g. ARMvX, LLVM, Linker options) + return true; + } + + public void CloseWriter () + { + Writer.Close (); + Writer = null; + } + + #endregion + + public void TestStarted (ITest test) + { + if (test is TestSuite) { + Writer.WriteLine (); + time.Push (DateTime.UtcNow); + Writer.WriteLine (test.Name); + } else + Writer.Write ("\t{0} ", test.Name); + Writer.Flush (); // Sometimes the test fails before it completes crashing the runtime, it's good to have the name of the test on the screen + } + + Stack time = new Stack (); + + public void TestFinished (ITestResult result) + { + AndroidRunner.Results [result.Test.FullName ?? result.Test.Name] = result as TestResult; + + if (result.Test is TestSuite) { + //if (!result.IsError && !result.IsFailure && !result.IsSuccess && !result.Executed) + //Writer.WriteLine ("\t[INFO] {0}", result.Message); + if (result.ResultState.Status != TestStatus.Failed + && result.ResultState.Status != TestStatus.Skipped + && result.ResultState.Status != TestStatus.Passed + && result.ResultState.Status != TestStatus.Inconclusive) + Writer.WriteLine ("\t[INFO] {0}", result.Message); + + var diff = DateTime.UtcNow - time.Pop (); + Writer.WriteLine ("{0} : {1} ms", result.Test.Name, diff.TotalMilliseconds); + if (GCAfterEachFixture) + GC.Collect (); + } else { + if (result.ResultState.Status == TestStatus.Passed) { + //Writer.Write ("\t{0} ", result.Executed ? "[PASS]" : "[IGNORED]"); + Writer.Write ("{0}", result.ResultState.ToString ()); + passed++; + } else if (result.ResultState.Status == TestStatus.Failed) { + Writer.Write ("[FAIL]"); + failed++; + } else { + Writer.Write ("[INFO]"); + if (result.ResultState.Status == TestStatus.Skipped) + skipped++; + else if (result.ResultState.Status == TestStatus.Inconclusive) + inconclusive++; + } + + string message = result.Message; + if (!String.IsNullOrEmpty (message)) { + Writer.Write (" : {0}", message.Replace ("\r\n", "\\r\\n")); + } + Writer.WriteLine (); + + string stacktrace = result.StackTrace; + if (!String.IsNullOrEmpty (result.StackTrace)) { + string[] lines = stacktrace.Split (new char [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string line in lines) + Writer.WriteLine ("\t\t{0}", line); + } + } + } + + static AndroidRunner runner = new AndroidRunner (); + + static public AndroidRunner Runner { + get { return runner; } + } + + static List top = new List (); + static Dictionary suites = new Dictionary (); + static Dictionary results = new Dictionary (); + + bool ITestFilter.IsEmpty { + get { return top.Count > 0 && suites.Count == 0 && results.Count == 0; } + } + + public ITestFilter Filter { get; set; } + + static public IList AssemblyLevel { + get { return top; } + } + + static public IDictionary Suites { + get { return suites; } + } + + static public IDictionary Results { + get { return results; } + } + + public TestResult Run (NUnit.Framework.Internal.Test test) + { + TestExecutionContext current = TestExecutionContext.CurrentContext; + current.WorkDirectory = System.Environment.CurrentDirectory; + current.Listener = this; + current.TestObject = test is TestSuite ? null : Reflect.Construct ((test as TestMethod).Method.ReflectedType, null); + WorkItem wi = test.CreateWorkItem (Filter ?? TestFilter.Empty); + if (test is TestMethod) + (test.Parent as TestSuite).GetOneTimeSetUpCommand ().Execute (current); + wi.Execute (current); + if (test is TestMethod) + (test.Parent as TestSuite).GetOneTimeTearDownCommand ().Execute (current); + return wi.Result; + } + + public void TestOutput (TestOutput testOutput) + { + if (!String.IsNullOrEmpty (testOutput.Text)) { + string kind = testOutput.Type.ToString (); + foreach (string l in testOutput.Text.Split ('\n')) { + Writer.Write (" {0}: ", kind); + Writer.WriteLine (l); + } + } + } + + public bool Pass (ITest pass) + { + return true; + } + + #region moved from RunnerActivity + + internal bool Initialized { get; set; } + + internal void AddTest (Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException ("assembly"); + + // this can be called many times but we only want to load them + // once since we need to share them across most activities + if (!Initialized) { + // TestLoader.Load always return a TestSuite so we can avoid casting many times + TestSuite ts = Runner.LoadAssembly (assembly, null); + if (ts != null) { + AssemblyLevel.Add (ts); + AddTest (ts); + } + } + } + + void AddTest (TestSuite suite) + { + Suites.Add (suite.FullName ?? suite.Name, suite); + foreach (ITest test in suite.Tests) { + TestSuite ts = (test as TestSuite); + if (ts != null) { + AddTest (ts); + } + } + } + + internal void Run (NUnitTest test, Context context) + { + if (!OpenWriter ("Run Everything", context)) + return; + + try { + Run (test); + } finally { + int testCount = passed + failed + skipped + inconclusive; + Runner.Writer.WriteLine ("Tests run: {0}, Passed: {1}, Failed: {2}, Skipped: {3}, Inconclusive: {4}", + testCount, passed, failed, skipped, inconclusive); + CloseWriter (); + } + } + #endregion + + internal static NUnitTest GetSetupTestTarget (Intent intent) + { + return GetSetupTestTarget (intent == null ? null : intent.Extras); + } + + internal static NUnitTest GetSetupTestTarget (Bundle bundle) + { + var suiteName = bundle == null ? null : bundle.GetString ("suite"); + TestSuite suite = null; + if (suiteName != null && !Suites.TryGetValue (suiteName, out suite)) { + Console.WriteLine ("Invalid suite name: {0}", suiteName); + Console.WriteLine ("Supported suite names:"); + foreach (KeyValuePair e in Suites) + Console.WriteLine ("\t{0}", e.Key); + return new TestSuite ("__error__"); + } + if (suite != null) + return suite; + else { + var ts = new TestSuite (""); + Console.Error.WriteLine (ts.FullName); + foreach (var i in AssemblyLevel.Cast ()) + ts.Add (i); + return ts; + } + } + + internal void AddTestFilters (IEnumerable included, IEnumerable excluded) + { + TestFilter filter = TestFilter.Empty; + + Log.Info (TAG, "Configuring test categories to include:"); + ChainCategoryFilter (included, false, ref filter); + + Log.Info (TAG, "Configuring test categories to exclude:"); + ChainCategoryFilter (excluded, true, ref filter); + + if (filter.IsEmpty) + return; + + if (Filter == null) + Filter = filter; + else + Filter = new AndFilter (Filter, filter); + } + + static void ChainCategoryFilter (IEnumerable categories, bool negate, ref TestFilter chain) + { + bool gotCategories = false; + if (categories != null) { + var filter = new CategoryFilter (); + foreach (string c in categories) { + Log.Info (TAG, " {0}", c); + filter.AddCategory (c); + gotCategories = true; + } + + chain = new AndFilter (chain, negate ? (TestFilter)new NotFilter (filter) : (TestFilter)filter); + } + + if (!gotCategories) + Log.Info (TAG, " none"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs b/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs new file mode 100644 index 00000000000..59f6c0d5990 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/Instrumentations/TestSuiteInstrumentation.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +using Android.App; +using Android.OS; +using Android.Runtime; +using Android.Util; + +using NUnit.Framework.Internal; + +namespace Xamarin.Android.NUnitLite { + + public abstract class TestSuiteInstrumentation : Instrumentation { + const string TAG = "NUnitLite"; + + protected bool GCAfterEachFixture { + get { return AndroidRunner.Runner.GCAfterEachFixture; } + set { AndroidRunner.Runner.GCAfterEachFixture = value; } + } + + protected TestSuiteInstrumentation (IntPtr handle, JniHandleOwnership transfer) + : base (handle, transfer) + { + } + + Bundle arguments; + + public override void OnCreate (Bundle arguments) + { + base.OnCreate (arguments); + this.arguments = arguments; + Start (); + } + + public override void OnStart () + { + base.OnStart (); + + AddTests (); + + AndroidRunner.Runner.Options.LoadFromBundle (arguments); + AndroidRunner.Runner.AddTestFilters (GetIncludedCategories (), GetExcludedCategories ()); + + AndroidRunner.Runner.Initialized = true; + var results = new Bundle (); + int failed = 0; + try { + Log.Info (TAG, "NUnit automated tests started"); + AndroidRunner.Runner.Run (AndroidRunner.GetSetupTestTarget (arguments), TargetContext); + Log.Info (TAG, "NUnit automated tests completed"); + int passed = 0, skipped = 0, inconclusive = 0; + foreach (TestResult result in AndroidRunner.Results.Values) { + if (result.HasChildren) + continue; + inconclusive += result.InconclusiveCount; + failed += result.FailCount; + passed += result.PassCount; + skipped += result.SkipCount; + if (result.FailCount > 0) { + Log.Error (TAG, "Test '{0}' failed: {1}", result.FullName, result.Message); + // Avoid Java.Lang.NullPointerException: println needs a message + if (!String.IsNullOrEmpty (result.StackTrace)) + Log.Error (TAG, result.StackTrace); + results.PutString ("failure: " + result.FullName, + result.Message + "\n" + result.StackTrace); + Log.Error (TAG, " "); // makes it easier to read the failures in logcat output + } + } + results.PutInt ("passed", passed); + results.PutInt ("failed", failed); + results.PutInt ("skipped", skipped); + results.PutInt ("inconclusive", inconclusive); + string message = string.Format ("Passed: {0}, Failed: {1}, Skipped: {2}, Inconclusive: {3}", + passed, failed, skipped, inconclusive); + Log.Info (TAG, message); + } catch (Exception e) { + Log.Error (TAG, "Error: {0}", e); + results.PutString ("error", e.ToString ()); + } + Finish (failed == 0 ? Result.Ok : Result.Canceled, results); + } + + protected abstract void AddTests (); + + protected void AddTest (Assembly assembly) + { + AndroidRunner.Runner.AddTest (assembly); + } + + protected virtual IEnumerable GetIncludedCategories () + { + return null; + } + + protected virtual IEnumerable GetExcludedCategories () + { + return null; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/Gui/Options.cs b/src/Xamarin.Android.NUnitLite/Gui/Options.cs new file mode 100644 index 00000000000..89781a02e2f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/Options.cs @@ -0,0 +1,68 @@ +// +// Copyright 2011-2012 Xamarin Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; + +using Android.App; +using Android.Content; +using Android.OS; + +namespace Xamarin.Android.NUnitLite { + + internal class Options { + + public Options () + { + } + + // Options are not as useful as under iOS since re-installing the + // application deletes the file containing them. + internal Options (Activity activity) + { + ISharedPreferences prefs = activity.GetSharedPreferences ("options", FileCreationMode.Private); + EnableNetwork = prefs.GetBoolean ("remote", false); + HostName = prefs.GetString ("hostName", "0.0.0.0"); + HostPort = prefs.GetInt ("hostPort", -1); + } + + public bool EnableNetwork { get; set; } + + public string HostName { get; set; } + + public int HostPort { get; set; } + + public bool ShowUseNetworkLogger { + get { return (EnableNetwork && !String.IsNullOrWhiteSpace (HostName) && (HostPort > 0)); } + } + + public void LoadFromBundle (Bundle bundle) + { + EnableNetwork = bundle.GetBoolean ("remote", false); + HostName = bundle.GetString ("hostName") ?? "0.0.0.0"; + HostPort = bundle.GetInt ("hostPort", -1); + } + + public void Save (Activity activity) + { + ISharedPreferences prefs = activity.GetSharedPreferences ("options", FileCreationMode.Private); + var edit = prefs.Edit (); + edit.PutBoolean ("remote", EnableNetwork); + edit.PutString ("hostName", HostName); + edit.PutInt ("hostPort", HostPort); + edit.Commit (); + } + } +} \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/Gui/TcpTextWriter.cs b/src/Xamarin.Android.NUnitLite/Gui/TcpTextWriter.cs new file mode 100644 index 00000000000..2d5909b57b8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Gui/TcpTextWriter.cs @@ -0,0 +1,85 @@ +// this is an adaptation of NUnitLite's TcpWriter.cs with an additional +// overrides + +using System; +using System.IO; +using System.Net.Sockets; +using System.Text; + +namespace Xamarin.Android.NUnitLite { + + internal class TcpTextWriter : TextWriter { + + private TcpClient client; + private StreamWriter writer; + + public TcpTextWriter (string hostName, int port) + { + if (hostName == null) + throw new ArgumentNullException ("hostName"); + if ((port < 0) || (port > UInt16.MaxValue)) + throw new ArgumentException ("port"); + + HostName = hostName; + Port = port; + + client = new TcpClient (hostName, port); + writer = new StreamWriter (client.GetStream ()); + } + + public string HostName { get; private set; } + + public int Port { get; private set; } + + // we override everything that StreamWriter overrides from TextWriter + + public override System.Text.Encoding Encoding { + // hardcoded to UTF8 so make it easier on the server side + get { return System.Text.Encoding.UTF8; } + } + + public override void Close () + { + writer.Close (); + } + + protected override void Dispose (bool disposing) + { + writer.Dispose (); + } + + public override void Flush () + { + writer.Flush (); + } + + // minimum to override - see http://msdn.microsoft.com/en-us/library/system.io.textwriter.aspx + public override void Write (char value) + { + writer.Write (value); + } + + public override void Write (char[] buffer) + { + writer.Write (buffer); + } + + public override void Write (char[] buffer, int index, int count) + { + writer.Write (buffer, index, count); + } + + public override void Write (string value) + { + writer.Write (value); + } + + // special extra override to ensure we flush data regularly + + public override void WriteLine () + { + writer.WriteLine (); + writer.Flush (); + } + } +} \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ExpectedExceptionData.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ExpectedExceptionData.cs new file mode 100644 index 00000000000..940d14ab7c6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ExpectedExceptionData.cs @@ -0,0 +1,143 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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.Reflection; + +namespace NUnit.Framework.Api +{ + /// + /// ExpectedExceptionData is a struct used within the framework + /// to encapsulate information about an expected exception. + /// + public struct ExpectedExceptionData + { + #region Fields + + private Type expectedExceptionType; + private string expectedExceptionName; + private string expectedMessage; + private MessageMatch matchType; + private string userMessage; + private string handlerName; + private MethodInfo exceptionHandler; + + #endregion + + #region Properties + + /// + /// The Type of any exception that is expected. + /// + public Type ExpectedExceptionType + { + get { return expectedExceptionType; } + set + { + expectedExceptionType = value; + expectedExceptionName = value.FullName; + } + } + + /// + /// The FullName of any exception that is expected + /// + public string ExpectedExceptionName + { + get { return expectedExceptionName; } + set + { + expectedExceptionName = value; + expectedExceptionType = null; + } + } + + /// + /// The Message of any exception that is expected + /// + public string ExpectedMessage + { + get { return expectedMessage; } + set { expectedMessage = value; } + } + + /// + /// The type of match to be performed on the expected message + /// + public MessageMatch MatchType + { + get { return matchType; } + set { matchType = value; } + } + + /// + /// A user message to be issued in case of error + /// + public string UserMessage + { + get { return userMessage; } + set { userMessage = value; } + } + + /// + /// The name of an alternate exception handler to be + /// used to validate the exception. + /// + public string HandlerName + { + get { return handlerName; } + set + { + handlerName = value; + exceptionHandler = null; + } + } + + #endregion + + #region Methods + + /// + /// Returns a MethodInfo for the handler to be used to + /// validate any exception thrown. + /// + /// The Type of the fixture. + /// A MethodInfo. + public MethodInfo GetExceptionHandler(Type fixtureType) + { + if (exceptionHandler == null && handlerName != null) + { + exceptionHandler = fixtureType.GetMethod( + handlerName, + BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + null, + new Type[] { typeof(System.Exception) }, + null); + } + + return exceptionHandler; + } + + #endregion + }; +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IParameterDataSource.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IParameterDataSource.cs new file mode 100644 index 00000000000..04a122a2078 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IParameterDataSource.cs @@ -0,0 +1,44 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; + +namespace NUnit.Framework.Api +{ + /// + /// The IParameterDataSource interface is implemented by types + /// that can provide data for a test method parameter. + /// + public interface IParameterDataSource + { + /// + /// Gets an enumeration of data items for use as arguments + /// for a test method parameter. + /// + /// The parameter for which data is needed + /// An enumeration containing individual data items + IEnumerable GetData(ParameterInfo parameter); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IPropertyBag.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IPropertyBag.cs new file mode 100644 index 00000000000..46edb3b55fe --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IPropertyBag.cs @@ -0,0 +1,162 @@ +using System; + +namespace NUnit.Framework.Api +{ + /// + /// A PropertyBag represents a collection of name/value pairs + /// that allows duplicate entries with the same key. Methods + /// are provided for adding a new pair as well as for setting + /// a key to a single value. All keys are strings but values + /// may be of any type. Null values are not permitted, since + /// a null entry represents the absence of the key. + /// + /// The entries in a PropertyBag are of two kinds: those that + /// take a single value and those that take multiple values. + /// However, the PropertyBag has no knowledge of which entries + /// fall into each category and the distinction is entirely + /// up to the code using the PropertyBag. + /// + /// When working with multi-valued properties, client code + /// should use the Add method to add name/value pairs and + /// indexing to retrieve a list of all values for a given + /// key. For example: + /// + /// bag.Add("Tag", "one"); + /// bag.Add("Tag", "two"); + /// Assert.That(bag["Tag"], + /// Is.EqualTo(new string[] { "one", "two" })); + /// + /// When working with single-valued propeties, client code + /// should use the Set method to set the value and Get to + /// retrieve the value. The GetSetting methods may also be + /// used to retrieve the value in a type-safe manner while + /// also providing default. For example: + /// + /// bag.Set("Priority", "low"); + /// bag.Set("Priority", "high"); // replaces value + /// Assert.That(bag.Get("Priority"), + /// Is.EqualTo("high")); + /// Assert.That(bag.GetSetting("Priority", "low"), + /// Is.EqualTo("high")); + /// + public interface IPropertyBag : IXmlNodeBuilder, System.Collections.IEnumerable + { + /// + /// Get the number of key/value pairs in the property bag + /// + int Count { get; } + + /// + /// Adds a key/value pair to the property bag + /// + /// The key + /// The value + void Add(string key, object value); + + + /// + /// Sets the value for a key, removing any other + /// values that are already in the property set. + /// + /// + /// + void Set(string key, object value); + + /// + /// Gets a single value for a key, using the first + /// one if multiple values are present and returning + /// null if the value is not found. + /// + object Get(string key); + + /// + /// Gets a single string value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + string GetSetting(string key, string defaultValue); + + /// + /// Gets a single int value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + int GetSetting(string key, int defaultValue); + + /// + /// Gets a single boolean value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + bool GetSetting(string key, bool defaultValue); + + /// + /// Gets a single enum value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + System.Enum GetSetting(string key, System.Enum defaultValue); + + /// + /// Removes all entries for a key from the property set. + /// If the key is not found, no error occurs. + /// + /// The key for which the entries are to be removed + void Remove(string key); + + /// + /// Removes a single entry if present. If not found, + /// no error occurs. + /// + /// + /// + void Remove(string key, object value); + + /// + /// Removes a specific PropertyEntry. If the entry is not + /// found, no errr occurs. + /// + /// The property entry to remove + void Remove(PropertyEntry entry); + + /// + /// Gets a flag indicating whether the specified key has + /// any entries in the property set. + /// + /// The key to be checked + /// True if their are values present, otherwise false + bool ContainsKey(string key); + + /// + /// Gets a flag indicating whether the specified key and + /// value are present in the property set. + /// + /// The key to be checked + /// The value to be checked + /// True if the key and value are present, otherwise false + bool Contains(string key, object value); + + /// + /// Gets a flag indicating whether the specified key and + /// value are present in the property set. + /// + /// The property entry to be checked + /// True if the entry is present, otherwise false + bool Contains(PropertyEntry entry); + + /// + /// Gets or sets the list of values for a particular key + /// + /// The key for which the values are to be retrieved or set + System.Collections.IList this[string key] { get; set; } + + /// + /// Gets a collection containing all the keys in the property set + /// +#if CLR_2_0 || CLR_4_0 + System.Collections.Generic.ICollection Keys { get; } +#else + System.Collections.ICollection Keys { get; } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITest.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITest.cs new file mode 100644 index 00000000000..5765124057d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITest.cs @@ -0,0 +1,107 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api +{ + /// + /// Common interface supported by all representations + /// of a test. Only includes informational fields. + /// The Run method is specifically excluded to allow + /// for data-only representations of a test. + /// + public interface ITest : IXmlNodeBuilder + { + /// + /// Gets or sets the id of the test + /// + int Id { get; set; } + + /// + /// Gets the name of the test + /// + string Name { get; } + + /// + /// Gets the fully qualified name of the test + /// + string FullName { get; } + + /// + /// Gets the Type of the test fixture, if applicable, or + /// null if no fixture type is associated with this test. + /// + Type FixtureType { get; } + + /// + /// Indicates whether the test can be run using + /// the RunState enum. + /// + RunState RunState { get; set; } + + /// + /// Count of the test cases ( 1 if this is a test case ) + /// + int TestCaseCount { get; } + + /// + /// Gets the properties of the test + /// + IPropertyBag Properties { get; } + + /// + /// Gets the parent test, if any. + /// + /// The parent test or null if none exists. + ITest Parent { get; } + + /// + /// Returns true if this is a test suite + /// + bool IsSuite { get; } + + /// + /// Gets a bool indicating whether the current test + /// has any descendant tests. + /// + bool HasChildren { get; } + + /// + /// Gets the Int value representing the seed for the RandomGenerator + /// + /// + int Seed { get; } + + /// + /// Gets this test's child tests + /// + /// A list of child tests +#if CLR_2_0 || CLR_4_0 + System.Collections.Generic.IList Tests { get; } +#else + System.Collections.IList Tests { get; } +#endif + } +} + diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestAssemblyBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestAssemblyBuilder.cs new file mode 100644 index 00000000000..bce1805acbd --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestAssemblyBuilder.cs @@ -0,0 +1,56 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using System.Reflection; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Api +{ + /// + /// The ITestAssemblyBuilder interface is implemented by a class + /// that is able to build a suite of tests given an assembly or + /// an assembly filename. + /// + public interface ITestAssemblyBuilder + { + // TODO: Remove use of TestSuite after tests are not self-running + + /// + /// Build a suite of tests from a provided assembly + /// + /// The assembly from which tests are to be built + /// A dictionary of options to use in building the suite + /// A TestSuite containing the tests found in the assembly + TestSuite Build(Assembly assembly, IDictionary options); + + /// + /// Build a suite of tests given the filename of an assembly + /// + /// The filename of the assembly from which tests are to be built + /// A dictionary of options to use in building the suite + /// A TestSuite containing the tests found in the assembly + TestSuite Build(string assemblyName, IDictionary options); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestAssemblyRunner.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestAssemblyRunner.cs new file mode 100644 index 00000000000..320a0819c00 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestAssemblyRunner.cs @@ -0,0 +1,83 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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.Reflection; + +namespace NUnit.Framework.Api +{ + /// + /// The ITestAssemblyRunner interface is implemented by classes + /// that are able to execute a suite of tests loaded + /// from an assembly. + /// + public interface ITestAssemblyRunner + { + #region Properties + + /// + /// Gets the tree of loaded tests, or null if + /// no tests have been loaded. + /// + ITest LoadedTest { get; } + + #endregion + + #region Methods + + /// + /// Loads the tests found in an Assembly, returning an + /// indication of whether or not the load succeeded. + /// + /// File name of the assembly to load + /// Dictionary of settings to use in loading the test + /// True if the load was successful + bool Load(string assemblyName, System.Collections.IDictionary settings); + + /// + /// Loads the tests found in an Assembly, returning an + /// indication of whether or not the load succeeded. + /// + /// The assembly to load + /// Dictionary of settings to use in loading the test + /// True if the load was successful + bool Load(Assembly assembly, System.Collections.IDictionary settings); + + ///// + ///// Count Test Cases using a filter + ///// + ///// The filter to apply + ///// The number of test cases found + //int CountTestCases(TestFilter filter); + + /// + /// Run selected tests and return a test result. The test is run synchronously, + /// and the listener interface is notified as it progresses. + /// + /// Interface to receive ITestListener notifications. + /// A test filter used to select tests to be run + ITestResult Run(ITestListener listener, ITestFilter filter); + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseData.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseData.cs new file mode 100644 index 00000000000..a3bad3b9ab8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseData.cs @@ -0,0 +1,71 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 OFn +// 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; + +namespace NUnit.Framework.Api +{ + /// + /// The ITestCaseData interface is implemented by a class + /// that is able to return complete testcases for use by + /// a parameterized test method. + /// + public interface ITestCaseData + { + /// + /// Gets the name to be used for the test + /// + string TestName { get; } + + /// + /// Gets the RunState for this test case. + /// + RunState RunState { get; } + + /// + /// Gets the argument list to be provided to the test + /// + object[] Arguments { get; } + + /// + /// Gets the expected result of the test case + /// + object ExpectedResult { get; } + + /// + /// Returns true if an expected result has been set + /// + bool HasExpectedResult { get; } + + /// + /// Gets data about any expected exception. + /// + ExpectedExceptionData ExceptionData { get; } + + /// + /// Gets the property dictionary for the test case + /// + IPropertyBag Properties { get; } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseSource.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseSource.cs new file mode 100644 index 00000000000..cf04c2f4d5a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseSource.cs @@ -0,0 +1,50 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 OFn +// 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.Reflection; + +namespace NUnit.Framework.Api +{ + /// + /// ITestCaseSource interface is implemented by Types that know how to + /// return a set of ITestCaseData items for use by a test method. + /// + /// + /// This method is defined differently depending on the version of .NET. + /// + public interface ITestCaseSource + { + /// + /// Returns a set of ITestCaseDataItems for use as arguments + /// to a parameterized test method. + /// + /// The method for which data is needed. + /// +#if CLR_2_0 || CLR_4_0 + System.Collections.Generic.IEnumerable GetTestCasesFor(MethodInfo method); +#else + System.Collections.IEnumerable GetTestCasesFor(MethodInfo method); +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseSourceProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseSourceProvider.cs new file mode 100644 index 00000000000..0b0652e65fc --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestCaseSourceProvider.cs @@ -0,0 +1,50 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 OFn +// 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 NUnit.Framework.Api +{ + /// + /// The ITestCaseSourceProvider interface is implemented by Types that + /// are able to provide a test case source for use by a test method. + /// + public interface IDynamicTestCaseSource + { + /// + /// Returns a test case source. May be called on a provider + /// implementing the source internally or able to create + /// a source instance on it's own. + /// + /// + ITestCaseSource GetTestCaseSource(); + + /// + /// Returns a test case source based on an instance of a + /// source object. + /// + /// + /// + ITestCaseSource GetTestCaseSource(object instance); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestFilter.cs new file mode 100644 index 00000000000..a5180cb6176 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestFilter.cs @@ -0,0 +1,49 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api +{ + /// + /// Interface to be implemented by filters applied to tests. + /// The filter applies when running the test, after it has been + /// loaded, since this is the only time an ITest exists. + /// + public interface ITestFilter + { + /// + /// Indicates whether this is the EmptyFilter + /// + bool IsEmpty { get; } + + /// + /// Determine if a particular test passes the filter criteria. Pass + /// may examine the parents and/or descendants of a test, depending + /// on the semantics of the particular filter + /// + /// The test to which the filter is applied + /// True if the test passes the fFilter, otherwise false + bool Pass( ITest test ); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestListener.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestListener.cs new file mode 100644 index 00000000000..9349ea18b65 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestListener.cs @@ -0,0 +1,52 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Api +{ + /// + /// The ITestListener interface is used internally to receive + /// notifications of significant events while a test is being + /// run. The events are propogated to clients by means of an + /// AsyncCallback. NUnit extensions may also monitor these events. + /// + public interface ITestListener + { + /// + /// Called when a test has just started + /// + /// The test that is starting + void TestStarted(ITest test); + + /// + /// Called when a test has finished + /// + /// The result of the test + void TestFinished(ITestResult result); + + /// + /// Called when the test creates text output. + /// + /// A console message + void TestOutput(TestOutput testOutput); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestResult.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestResult.cs new file mode 100644 index 00000000000..4ac6cd9c070 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ITestResult.cs @@ -0,0 +1,161 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Api +{ + /// + /// The ITestResult interface represents the result of a test. + /// + public interface ITestResult : IXmlNodeBuilder + { + /// + /// Gets the ResultState of the test result, which + /// indicates the success or failure of the test. + /// + ResultState ResultState + { + get; + } + + /// + /// Gets the name of the test result + /// + string Name + { + get; + } + + /// + /// Gets the full name of the test result + /// + string FullName + { + get; + } + + /// + /// Gets the elapsed time for running the test + /// + TimeSpan Duration + { + get; + } + + /// + /// Gets the message associated with a test + /// failure or with not running the test + /// + string Message + { + get; + } + + /// + /// Gets any stacktrace associated with an + /// error or failure. Not available in + /// the Compact Framework 1.0. + /// + string StackTrace + { + get; + } + + /// + /// Gets the number of asserts executed + /// when running the test and all its children. + /// + int AssertCount + { + get; + } + + + /// + /// Gets the number of test cases that failed + /// when running the test and all its children. + /// + int FailCount + { + get; + } + + /// + /// Gets the number of test cases that passed + /// when running the test and all its children. + /// + int PassCount + { + get; + } + + /// + /// Gets the number of test cases that were skipped + /// when running the test and all its children. + /// + int SkipCount + { + get; + } + + /// + /// Gets the number of test cases that were inconclusive + /// when running the test and all its children. + /// + int InconclusiveCount + { + get; + } + + /// + /// Indicates whether this result has any child results. + /// Accessing HasChildren should not force creation of the + /// Children collection in classes implementing this interface. + /// + bool HasChildren + { + get; + } + + /// + /// Gets the the collection of child results. + /// +#if CLR_2_0 || CLR_4_0 + System.Collections.Generic.IList Children +#else + System.Collections.IList Children +#endif + { + get; + } + + /// + /// Gets the Test to which this result applies. + /// + ITest Test + { + get; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IXmlNodeBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IXmlNodeBuilder.cs new file mode 100644 index 00000000000..c0d029f03fe --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/IXmlNodeBuilder.cs @@ -0,0 +1,29 @@ +using System; + +namespace NUnit.Framework.Api +{ + /// + /// An object implementing IXmlNodeBuilder is able to build + /// an XmlResult representation of itself and any children. + /// Note that the interface refers to the implementation + /// of XmlNode in the NUnit.Framework.Api namespace. + /// + public interface IXmlNodeBuilder + { + /// + /// Returns an XmlNode representating the current object. + /// + /// If true, children are included where applicable + /// An XmlNode representing the result + XmlNode ToXml(bool recursive); + + /// + /// Returns an XmlNode representing the current object after + /// adding it as a child of the supplied parent node. + /// + /// The parent node. + /// If true, children are included, where applicable + /// + XmlNode AddToXml(XmlNode parentNode, bool recursive); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/PropertyEntry.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/PropertyEntry.cs new file mode 100644 index 00000000000..b9d6162f800 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/PropertyEntry.cs @@ -0,0 +1,70 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Api +{ + /// + /// Immutable class that stores a property entry as a Name/Value pair. + /// + public class PropertyEntry + { + private readonly string name; + private readonly object value; + + /// + /// Initializes a new immutable instance of the class. + /// + /// + /// + public PropertyEntry(string name, object value) + { + this.name = name; + this.value = value; + } + + /// Name of the PropertyEntry. + public string Name + { + get { return name; } + } + + /// Value of the PropertyEntry. + public object Value + { + get { return value; } + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format("{0}={1}", name, value); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ResultState.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ResultState.cs new file mode 100644 index 00000000000..f7e5e0f8c1a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/ResultState.cs @@ -0,0 +1,139 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Api +{ + /// + /// The ResultState class represents the outcome of running a test. + /// It contains two pieces of information. The Status of the test + /// is an enum indicating whether the test passed, failed, was + /// skipped or was inconclusive. The Label provides a more + /// detailed breakdown for use by client runners. + /// + public class ResultState + { + private readonly TestStatus status; + private readonly string label; + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The TestStatus. + public ResultState(TestStatus status) : this (status, string.Empty) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The TestStatus. + /// The label. + public ResultState(TestStatus status, string label) + { + this.status = status; + this.label = label == null ? string.Empty : label; + } + + #endregion + + #region Predefined ResultStates + + /// + /// The result is inconclusive + /// + public readonly static ResultState Inconclusive = new ResultState(TestStatus.Inconclusive); + + /// + /// The test was not runnable. + /// + public readonly static ResultState NotRunnable = new ResultState(TestStatus.Skipped, "Invalid"); + + /// + /// The test has been skipped. + /// + public readonly static ResultState Skipped = new ResultState(TestStatus.Skipped); + + /// + /// The test has been ignored. + /// + public readonly static ResultState Ignored = new ResultState(TestStatus.Skipped, "Ignored"); + + /// + /// The test succeeded + /// + public readonly static ResultState Success = new ResultState(TestStatus.Passed); + + /// + /// The test failed + /// + public readonly static ResultState Failure = new ResultState(TestStatus.Failed); + + /// + /// The test encountered an unexpected exception + /// + public readonly static ResultState Error = new ResultState(TestStatus.Failed, "Error"); + + /// + /// The test was cancelled by the user + /// + public readonly static ResultState Cancelled = new ResultState(TestStatus.Failed, "Cancelled"); + + #endregion + + #region Properties + + /// + /// Gets the TestStatus for the test. + /// + /// The status. + public TestStatus Status + { + get { return status; } + } + + /// + /// Gets the label under which this test resullt is + /// categorized, if any. + /// + public string Label + { + get { return label; } + } + + #endregion + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + string s = status.ToString(); + return label == null || label.Length == 0 ? s : string.Format("{0}:{1}", s, label); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/RunState.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/RunState.cs new file mode 100644 index 00000000000..c30b0700e45 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/RunState.cs @@ -0,0 +1,60 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Api +{ + /// + /// The RunState enum indicates whether a test + /// can be executed. + /// + public enum RunState + { + /// + /// The test is not runnable. + /// + NotRunnable, + + /// + /// The test is runnable. + /// + Runnable, + + /// + /// The test can only be run explicitly. + /// + Explicit, + + /// + /// The test has been skipped. This value may + /// appear on a Test when certain attributes + /// are used to skip the test. + /// + Skipped, + + /// + /// The test has been ignored. May appear on + /// a Test, when the IgnoreAttribute is used. + /// + Ignored + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/TestOutput.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/TestOutput.cs new file mode 100644 index 00000000000..b8eed4a9fa5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/TestOutput.cs @@ -0,0 +1,109 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Api +{ + using System; + + /// + /// The TestOutput class holds a unit of output from + /// a test to either stdOut or stdErr + /// + public class TestOutput + { + string text; + TestOutputType type; + + /// + /// Construct with text and an ouput destination type + /// + /// Text to be output + /// Destination of output + public TestOutput(string text, TestOutputType type) + { + this.text = text; + this.type = type; + } + + /// + /// Return string representation of the object for debugging + /// + /// + public override string ToString() + { + return type + ": " + text; + } + + /// + /// Get the text + /// + public string Text + { + get + { + return this.text; + } + } + + /// + /// Get the output type + /// + public TestOutputType Type + { + get + { + return this.type; + } + } + } + + /// + /// Enum representing the output destination + /// It uses combinable flags so that a given + /// output control can accept multiple types + /// of output. Normally, each individual + /// output uses a single flag value. + /// + public enum TestOutputType + { + /// + /// Send output to stdOut + /// + Out, + + /// + /// Send output to stdErr + /// + Error, + + /// + /// Send output to Trace + /// + Trace, + + /// + /// Send output to Log + /// + Log + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/TestStatus.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/TestStatus.cs new file mode 100644 index 00000000000..2a206f3cdf5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/TestStatus.cs @@ -0,0 +1,51 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Api +{ + /// + /// The TestStatus enum indicates the result of running a test + /// + public enum TestStatus + { + /// + /// The test was inconclusive + /// + Inconclusive, + + /// + /// The test has skipped + /// + Skipped, + + /// + /// The test succeeded + /// + Passed, + + /// + /// The test failed + /// + Failed + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Api/XmlNode.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/XmlNode.cs new file mode 100644 index 00000000000..640e0905544 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Api/XmlNode.cs @@ -0,0 +1,352 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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 NUnit.Framework.Api +{ + /// + /// XmlNode represents a single node in the XML representation + /// of a Test or TestResult. It replaces System.Xml.XmlNode and + /// provides a minimal set of methods for operating on the XML + /// in a platform-independent manner. + /// + public class XmlNode + { + #region Private Fields + + private string name; + + private AttributeDictionary attributes; + + private NodeList childNodes; + + private string textContent; + + #endregion + + #region Constructors + + /// + /// Constructs a new instance of XmlNode + /// + /// The name of the node + public XmlNode(string name) + { + this.name = name; + this.attributes = new AttributeDictionary(); + this.childNodes = new NodeList(); + } + + #endregion + + #region Static Methods + + /// + /// Creates a new top level element node. + /// + /// The element name. + /// + public static XmlNode CreateTopLevelElement(string name) + { + return new XmlNode(name); + } + + #endregion + + #region Properties + + /// + /// Gets the name of the node + /// + public string Name + { + get { return name; } + } + + /// + /// Gets the text content of the node + /// + public string TextContent + { + get { return textContent; } + set { textContent = value; } + } + + /// + /// Gets the text content of the node escaped as needed. + /// This is for use in writing out the XML representation. + /// + public string EscapedTextContent + { + get { return Escape(textContent); } + } + + /// + /// Gets the dictionary of attributes + /// + public AttributeDictionary Attributes + { + get { return attributes; } + } + + /// + /// Gets a list of child nodes + /// + public NodeList ChildNodes + { + get { return childNodes; } + } + + /// + /// Gets the first child of this node, or null + /// + public XmlNode FirstChild + { + get + { + return ChildNodes.Count > 0 + ? ChildNodes[0] as XmlNode + : null; + } + } + + #endregion + + #region Instance Methods + + /// + /// Adds a new element as a child of the current node and returns it. + /// + /// The element name. + /// The newly created child element + public XmlNode AddElement(string name) + { + XmlNode childResult = new XmlNode(name); + ChildNodes.Add(childResult); + return childResult; + } + + /// + /// Adds an attribute with a specified name and value to the XmlNode. + /// + /// The name of the attribute. + /// The value of the attribute. + public void AddAttribute(string name, string value) + { + this.Attributes.Add(name, value); + } + + /// + /// Finds a single descendant of this node matching an xpath + /// specification. The format of the specification is + /// limited to what is needed by NUnit and its tests. + /// + /// + /// + public XmlNode FindDescendant(string xpath) + { + NodeList nodes = FindDescendants(xpath); + + return nodes.Count > 0 + ? nodes[0] as XmlNode + : null; + } + + /// + /// Finds all descendants of this node matching an xpath + /// specification. The format of the specification is + /// limited to what is needed by NUnit and its tests. + /// + /// + /// + public NodeList FindDescendants(string xpath) + { + NodeList nodeList = new NodeList(); + nodeList.Add(this); + + return ApplySelection(nodeList, xpath); + } + + /// + /// Writes the XML representation of the node to an XmlWriter + /// + /// + public void WriteTo(System.Xml.XmlWriter writer) + { + writer.WriteStartElement(this.Name); + + foreach (string name in this.Attributes.Keys) + writer.WriteAttributeString(name, Attributes[name]); + + if (this.TextContent != null) + writer.WriteChars(this.TextContent.ToCharArray(), 0, this.TextContent.Length); + + foreach (XmlNode node in this.ChildNodes) + node.WriteTo(writer); + + writer.WriteEndElement(); + } + + #endregion + + #region Helper Methods + + private static NodeList ApplySelection(NodeList nodeList, string xpath) + { + Guard.ArgumentNotNullOrEmpty(xpath, "xpath"); + if (xpath[0] == '/') + throw new ArgumentException("XPath expressions starting with '/' are not supported", "xpath"); + if (xpath.IndexOf("//") >= 0) + throw new ArgumentException("XPath expressions with '//' are not supported", "xpath"); + + string head = xpath; + string tail = null; + + int slash = xpath.IndexOf('/'); + if (slash >= 0) + { + head = xpath.Substring(0, slash); + tail = xpath.Substring(slash + 1); + } + + NodeList resultNodes = new NodeList(); + NodeFilter filter = new NodeFilter(head); + + foreach(XmlNode node in nodeList) + foreach (XmlNode childNode in node.ChildNodes) + if (filter.Pass(childNode)) + resultNodes.Add(childNode); + + return tail != null + ? ApplySelection(resultNodes, tail) + : resultNodes; + } + + private static string Escape(string original) + { + return original + .Replace("&", "&") + .Replace("\"", """) + .Replace("'", "'") + .Replace("<", "<") + .Replace(">", ">"); + } + + #endregion + + #region Nested NodeFilter class + + class NodeFilter + { + private string nodeName; + private string propName; + private string propValue; + + public NodeFilter(string xpath) + { + this.nodeName = xpath; + + int lbrack = xpath.IndexOf('['); + if (lbrack >= 0) + { + if (!xpath.EndsWith("]")) + throw new ArgumentException("Invalid property expression", "xpath"); + + nodeName = xpath.Substring(0, lbrack); + string filter = xpath.Substring(lbrack+1, xpath.Length - lbrack - 2); + + int equals = filter.IndexOf('='); + if (equals < 0 || filter[0] != '@') + throw new ArgumentException("Invalid property expression", "xpath"); + + this.propName = filter.Substring(1, equals - 1).Trim(); + this.propValue = filter.Substring(equals + 1).Trim(new char[] { ' ', '"', '\'' }); + } + } + + public bool Pass(XmlNode node) + { + if (node.Name != nodeName) + return false; + + if (propName == null) + return true; + + return (string)node.Attributes[propName] == propValue; + } + } + + #endregion + } + + /// + /// Class used to represent a list of XmlResults + /// +#if CLR_2_0 || CLR_4_0 + public class NodeList : System.Collections.Generic.List + { + } +#else + public class NodeList : System.Collections.ArrayList + { + } +#endif + + /// + /// Class used to represent the attributes of a node + /// +#if CLR_2_0 || CLR_4_0 + public class AttributeDictionary : System.Collections.Generic.Dictionary + { + } +#else + public class AttributeDictionary : System.Collections.Specialized.StringDictionary + { + private System.Collections.ArrayList orderedKeys = new System.Collections.ArrayList(); + + /// + /// Adds a key and value to the dictionary. Overridden to + /// save the order in which keys are added. + /// + /// The attribute key + /// The attribute value + public override void Add(string key, string value) + { + base.Add(key, value); + orderedKeys.Add(key); + } + + /// + /// Gets the keys in the same order they were added. + /// + public override System.Collections.ICollection Keys + { + get + { + return orderedKeys; + } + } + } +#endif +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/AssemblyInfo.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/AssemblyInfo.cs new file mode 100644 index 00000000000..9c0268f5d6a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/AssemblyInfo.cs @@ -0,0 +1,110 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NUnitLite")] +[assembly: AssemblyDescription("NUnitLite unit-testing framework")] +[assembly: AssemblyCompany("NUnit Software")] +[assembly: AssemblyProduct("NUnitLite")] +[assembly: AssemblyCopyright("Copyright 2013, Charlie Poole")] +[assembly: AssemblyTrademark("NUnitLite")] +[assembly: AssemblyCulture("")] + +// Set AssemblyConfiguration attribute depending on +// how we are building the assembly. +#if DEBUG +#if NET_4_5 +[assembly: AssemblyConfiguration(".NET 4.5 Debug")] +#elif NET_4_0 +[assembly: AssemblyConfiguration(".NET 4.0 Debug")] +#elif NET_3_5 +[assembly: AssemblyConfiguration(".NET 3.5 Debug")] +#elif NET_2_0 +[assembly: AssemblyConfiguration(".NET 2.0 Debug")] +#elif NET_1_1 +[assembly: AssemblyConfiguration(".NET 1.1 Debug")] +#elif NETCF_3_5 +[assembly: AssemblyConfiguration(".NET CF 3.5 Debug")] +#elif NETCF_2_0 +[assembly: AssemblyConfiguration(".NET CF 2.0 Debug")] +#elif SL_5_0 +[assembly: AssemblyConfiguration("Silverlight 5.0 Debug")] +#elif SL_4_0 +[assembly: AssemblyConfiguration("Silverlight 4.0 Debug")] +#elif SL_3_0 +[assembly: AssemblyConfiguration("Silverlight 3.0 Debug")] +#endif +#else +#if NET_4_5 +[assembly: AssemblyConfiguration(".NET 4.5")] +#elif NET_4_0 +[assembly: AssemblyConfiguration(".NET 4.0")] +#elif NET_3_5 +[assembly: AssemblyConfiguration(".NET 3.5")] +#elif NET_2_0 +[assembly: AssemblyConfiguration(".NET 2.0")] +#elif NET_1_1 +[assembly: AssemblyConfiguration(".NET 1.1")] +#elif NETCF_3_5 +[assembly: AssemblyConfiguration(".NET CF 3.5")] +#elif NETCF_2_0 +[assembly: AssemblyConfiguration(".NET CF 2.0")] +#elif SL_5_0 +[assembly: AssemblyConfiguration("Silverlight 5.0")] +#elif SL_4_0 +[assembly: AssemblyConfiguration("Silverlight 4.0")] +#elif SL_3_0 +[assembly: AssemblyConfiguration("Silverlight 3.0")] +#endif +#endif + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +[assembly: CLSCompliant(true)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0be367fd-d825-4039-a70b-54a3557170ec")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +#if !PocketPC && !WindowsCE && !NETCF +[assembly: AssemblyFileVersion("1.0.0.0")] +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Assert.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Assert.cs new file mode 100644 index 00000000000..755a8ff1be6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Assert.cs @@ -0,0 +1,2321 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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.ComponentModel; +using NUnit.Framework.Constraints; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Delegate used by tests that execute code and + /// capture any thrown exception. + /// + public delegate void TestDelegate(); + + /// + /// The Assert class contains a collection of static methods that + /// implement the most common assertions used in NUnit. + /// + public class Assert + { + #region Constructor + + /// + /// We don't actually want any instances of this object, but some people + /// like to inherit from it to add other static methods. Hence, the + /// protected constructor disallows any instances of this object. + /// + protected Assert() { } + + #endregion + + #region GreaterOrEqual + + #region IsInstanceOfType + /// + /// Asserts that an object is an instance of a given type. + /// + /// The expected Type + /// The object being examined + public static void IsInstanceOfType( System.Type expected, object actual ) + { + IsInstanceOfType( expected, actual, string.Empty, null ); + } + + /// + /// Asserts that an object is an instance of a given type. + /// + /// The expected Type + /// The object being examined + /// A message to display in case of failure + public static void IsInstanceOfType( System.Type expected, object actual, string message ) + { + IsInstanceOfType( expected, actual, message, null ); + } + + /// + /// Asserts that an object is an instance of a given type. + /// + /// The expected Type + /// The object being examined + /// A message to display in case of failure + /// An array of objects to be used in formatting the message + public static void IsInstanceOfType( System.Type expected, object actual, string message, params object[] args ) + { + Assert.That(actual, Is.InstanceOfType(expected), message, args); + } + #endregion + + #region Ints + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void GreaterOrEqual(int arg1, + int arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + static public void GreaterOrEqual(int arg1, int arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + static public void GreaterOrEqual(int arg1, int arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region UInts + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + [CLSCompliant(false)] + static public void GreaterOrEqual(uint arg1, + uint arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + [CLSCompliant(false)] + static public void GreaterOrEqual(uint arg1, uint arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater or equal to than the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + [CLSCompliant(false)] + static public void GreaterOrEqual(uint arg1, uint arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region Longs + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void GreaterOrEqual(long arg1, + long arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + static public void GreaterOrEqual(long arg1, long arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater or equal to than the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + static public void GreaterOrEqual(long arg1, long arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region ULongs + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + [CLSCompliant(false)] + static public void GreaterOrEqual(ulong arg1, + ulong arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + [CLSCompliant(false)] + static public void GreaterOrEqual(ulong arg1, ulong arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater or equal to than the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + [CLSCompliant(false)] + static public void GreaterOrEqual(ulong arg1, ulong arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region Decimals + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void GreaterOrEqual(decimal arg1, + decimal arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + static public void GreaterOrEqual(decimal arg1, decimal arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + static public void GreaterOrEqual(decimal arg1, decimal arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region Doubles + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void GreaterOrEqual(double arg1, + double arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + static public void GreaterOrEqual(double arg1, + double arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + static public void GreaterOrEqual(double arg1, double arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region Floats + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void GreaterOrEqual(float arg1, + float arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + static public void GreaterOrEqual(float arg1, float arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater than or equal to the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + static public void GreaterOrEqual(float arg1, float arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #region IComparables + + /// + /// Verifies that the first value is greater than the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void GreaterOrEqual(IComparable arg1, + IComparable arg2, string message, params object[] args) + { + Assert.That(arg1, Is.GreaterThanOrEqualTo(arg2), message, args); + } + + /// + /// Verifies that the first value is greater than the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + /// The message that will be displayed on failure + static public void GreaterOrEqual(IComparable arg1, IComparable arg2, string message) + { + Assert.GreaterOrEqual(arg1, arg2, message, null); + } + + /// + /// Verifies that the first value is greater than the second + /// value. If they are not, then an + /// is thrown. + /// + /// The first value, expected to be greater + /// The second value, expected to be less + static public void GreaterOrEqual(IComparable arg1, IComparable arg2) + { + Assert.GreaterOrEqual(arg1, arg2, string.Empty, null); + } + + #endregion + + #endregion + + #region Equals and ReferenceEquals + +#if !NETCF + /// + /// The Equals method throws an AssertionException. This is done + /// to make sure there is no mistake by calling this function. + /// + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static new bool Equals(object a, object b) + { + throw new InvalidOperationException("Assert.Equals should not be used for Assertions"); + } + + /// + /// override the default ReferenceEquals to throw an AssertionException. This + /// implementation makes sure there is no mistake in calling this function + /// as part of Assert. + /// + /// + /// + public static new void ReferenceEquals(object a, object b) + { + throw new InvalidOperationException("Assert.ReferenceEquals should not be used for Assertions"); + } +#endif + + #endregion + + #region Utility Asserts + + #region Pass + + /// + /// Throws a with the message and arguments + /// that are passed in. This allows a test to be cut short, with a result + /// of success returned to NUnit. + /// + /// The message to initialize the with. + /// Arguments to be used in formatting the message + static public void Pass(string message, params object[] args) + { + if (message == null) message = string.Empty; + else if (args != null && args.Length > 0) + message = string.Format(message, args); + + throw new SuccessException(message); + } + + /// + /// Throws a with the message and arguments + /// that are passed in. This allows a test to be cut short, with a result + /// of success returned to NUnit. + /// + /// The message to initialize the with. + static public void Pass(string message) + { + Assert.Pass(message, null); + } + + /// + /// Throws a with the message and arguments + /// that are passed in. This allows a test to be cut short, with a result + /// of success returned to NUnit. + /// + static public void Pass() + { + Assert.Pass(string.Empty, null); + } + + #endregion + + #region Fail + + /// + /// Throws an with the message and arguments + /// that are passed in. This is used by the other Assert functions. + /// + /// The message to initialize the with. + /// Arguments to be used in formatting the message + static public void Fail(string message, params object[] args) + { + if (message == null) message = string.Empty; + else if (args != null && args.Length > 0) + message = string.Format(message, args); + + throw new AssertionException(message); + } + + /// + /// Throws an with the message that is + /// passed in. This is used by the other Assert functions. + /// + /// The message to initialize the with. + static public void Fail(string message) + { + Assert.Fail(message, null); + } + + /// + /// Throws an . + /// This is used by the other Assert functions. + /// + static public void Fail() + { + Assert.Fail(string.Empty, null); + } + + #endregion + + #region Ignore + + /// + /// Throws an with the message and arguments + /// that are passed in. This causes the test to be reported as ignored. + /// + /// The message to initialize the with. + /// Arguments to be used in formatting the message + static public void Ignore(string message, params object[] args) + { + if (message == null) message = string.Empty; + else if (args != null && args.Length > 0) + message = string.Format(message, args); + + throw new IgnoreException(message); + } + + /// + /// Throws an with the message that is + /// passed in. This causes the test to be reported as ignored. + /// + /// The message to initialize the with. + static public void Ignore(string message) + { + Assert.Ignore(message, null); + } + + /// + /// Throws an . + /// This causes the test to be reported as ignored. + /// + static public void Ignore() + { + Assert.Ignore(string.Empty, null); + } + + #endregion + + #region InConclusive + + /// + /// Throws an with the message and arguments + /// that are passed in. This causes the test to be reported as inconclusive. + /// + /// The message to initialize the with. + /// Arguments to be used in formatting the message + static public void Inconclusive(string message, params object[] args) + { + if (message == null) message = string.Empty; + else if (args != null && args.Length > 0) + message = string.Format(message, args); + + throw new InconclusiveException(message); + } + + /// + /// Throws an with the message that is + /// passed in. This causes the test to be reported as inconclusive. + /// + /// The message to initialize the with. + static public void Inconclusive(string message) + { + Assert.Inconclusive(message, null); + } + + /// + /// Throws an . + /// This causes the test to be reported as Inconclusive. + /// + static public void Inconclusive() + { + Assert.Inconclusive(string.Empty, null); + } + + #endregion + + #endregion + + #region Assert.That + + #region Object + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + static public void That(object actual, IResolveConstraint expression) + { + Assert.That(actual, expression, null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + static public void That(object actual, IResolveConstraint expression, string message) + { + Assert.That(actual, expression, message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(object actual, IResolveConstraint expression, string message, params object[] args) + { + Constraint constraint = expression.Resolve(); + + IncrementAssertCount(); + if (!constraint.Matches(actual)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new AssertionException(writer.ToString()); + } + } + + #endregion + + #region Boolean + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display if the condition is false + /// Arguments to be used in formatting the message + static public void That(bool condition, string message, params object[] args) + { + Assert.That(condition, Is.True, message, args); + } + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display if the condition is false + static public void That(bool condition, string message) + { + Assert.That(condition, Is.True, message, null); + } + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + static public void That(bool condition) + { + Assert.That(condition, Is.True, null, null); + } + + #endregion + + #region ref Boolean + +#if !CLR_2_0 && !CLR_4_0 + /// + /// Apply a constraint to a referenced boolean, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + static public void That(ref bool actual, IResolveConstraint constraint) + { + Assert.That(ref actual, constraint.Resolve(), null, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + static public void That(ref bool actual, IResolveConstraint constraint, string message) + { + Assert.That(ref actual, constraint.Resolve(), message, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ref bool actual, IResolveConstraint expression, string message, params object[] args) + { + Constraint constraint = expression.Resolve(); + + IncrementAssertCount(); + if (!constraint.Matches(ref actual)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new AssertionException(writer.ToString()); + } + } +#endif + + #endregion + + #region ActualValueDelegate + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + static public void That(ActualValueDelegate del, IResolveConstraint expr) + { + Assert.That(del, expr.Resolve(), null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message) + { + Assert.That(del, expr.Resolve(), message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message, params object[] args) + { + Constraint constraint = expr.Resolve(); + + IncrementAssertCount(); + if (!constraint.Matches(del)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new AssertionException(writer.ToString()); + } + } +#else + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + static public void That(ActualValueDelegate del, IResolveConstraint expr) + { + Assert.That(del, expr.Resolve(), null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message) + { + Assert.That(del, expr.Resolve(), message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message, params object[] args) + { + Constraint constraint = expr.Resolve(); + + IncrementAssertCount(); + if (!constraint.Matches(del)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new AssertionException(writer.ToString()); + } + } +#endif + + #endregion + + #region ref Object + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + static public void That(ref T actual, IResolveConstraint expression) + { + Assert.That(ref actual, expression, null, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + static public void That(ref T actual, IResolveConstraint expression, string message) + { + Assert.That(ref actual, expression, message, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ref T actual, IResolveConstraint expression, string message, params object[] args) + { + Constraint constraint = expression.Resolve(); + + IncrementAssertCount(); + if (!constraint.Matches(ref actual)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new AssertionException(writer.ToString()); + } + } +#endif + + #endregion + + #region TestDelegate + + /// + /// Asserts that the code represented by a delegate throws an exception + /// that satisfies the constraint provided. + /// + /// A TestDelegate to be executed + /// A ThrowsConstraint used in the test + static public void That(TestDelegate code, IResolveConstraint constraint) + { + Assert.That((object)code, constraint); + } + + #endregion + + #endregion + + #region Assert.ByVal + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// Used as a synonym for That in rare cases where a private setter + /// causes a Visual Basic compilation error. + /// + /// The actual value to test + /// A Constraint to be applied + static public void ByVal(object actual, IResolveConstraint expression) + { + Assert.That(actual, expression, null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// Used as a synonym for That in rare cases where a private setter + /// causes a Visual Basic compilation error. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + static public void ByVal(object actual, IResolveConstraint expression, string message) + { + Assert.That(actual, expression, message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// Used as a synonym for That in rare cases where a private setter + /// causes a Visual Basic compilation error. + /// + /// + /// This method is provided for use by VB developers needing to test + /// the value of properties with private setters. + /// + /// The actual value to test + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void ByVal(object actual, IResolveConstraint expression, string message, params object[] args) + { + Assert.That(actual, expression, message, args); + } + + #endregion + + #region Throws, Catch and DoesNotThrow + + #region Throws + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// A constraint to be satisfied by the exception + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static Exception Throws(IResolveConstraint expression, TestDelegate code, string message, params object[] args) + { + Exception caughtException = null; + +#if NET_4_5 + if (AsyncInvocationRegion.IsAsyncOperation(code)) + { + using (AsyncInvocationRegion region = AsyncInvocationRegion.Create(code)) + { + code(); + + try + { + region.WaitForPendingOperationsToComplete(null); + } + catch (Exception e) + { + caughtException = e; + } + } + } + else +#endif + try + { + code(); + } + catch (Exception ex) + { + caughtException = ex; + } + + Assert.That(caughtException, expression, message, args); + + return caughtException; + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// A constraint to be satisfied by the exception + /// A TestDelegate + /// The message that will be displayed on failure + public static Exception Throws(IResolveConstraint expression, TestDelegate code, string message) + { + return Throws(expression, code, message, null); + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// A constraint to be satisfied by the exception + /// A TestDelegate + public static Exception Throws(IResolveConstraint expression, TestDelegate code) + { + return Throws(expression, code, string.Empty, null); + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// The exception Type expected + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static Exception Throws(Type expectedExceptionType, TestDelegate code, string message, params object[] args) + { + return Throws(new ExceptionTypeConstraint(expectedExceptionType), code, message, args); + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// The exception Type expected + /// A TestDelegate + /// The message that will be displayed on failure + public static Exception Throws(Type expectedExceptionType, TestDelegate code, string message) + { + return Throws(new ExceptionTypeConstraint(expectedExceptionType), code, message, null); + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// The exception Type expected + /// A TestDelegate + public static Exception Throws(Type expectedExceptionType, TestDelegate code) + { + return Throws(new ExceptionTypeConstraint(expectedExceptionType), code, string.Empty, null); + } + + #endregion + + #region Throws + +#if CLR_2_0 || CLR_4_0 + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// Type of the expected exception + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static T Throws(TestDelegate code, string message, params object[] args) where T : Exception + { + return (T)Throws(typeof(T), code, message, args); + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// Type of the expected exception + /// A TestDelegate + /// The message that will be displayed on failure + public static T Throws(TestDelegate code, string message) where T : Exception + { + return Throws(code, message, null); + } + + /// + /// Verifies that a delegate throws a particular exception when called. + /// + /// Type of the expected exception + /// A TestDelegate + public static T Throws(TestDelegate code) where T : Exception + { + return Throws(code, string.Empty, null); + } +#endif + + #endregion + + #region Catch + /// + /// Verifies that a delegate throws an exception when called + /// and returns it. + /// + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static Exception Catch(TestDelegate code, string message, params object[] args) + { + return Throws(new InstanceOfTypeConstraint(typeof(Exception)), code, message, args); + } + + /// + /// Verifies that a delegate throws an exception when called + /// and returns it. + /// + /// A TestDelegate + /// The message that will be displayed on failure + public static Exception Catch(TestDelegate code, string message) + { + return Throws(new InstanceOfTypeConstraint(typeof(Exception)), code, message); + } + + /// + /// Verifies that a delegate throws an exception when called + /// and returns it. + /// + /// A TestDelegate + public static Exception Catch(TestDelegate code) + { + return Throws(new InstanceOfTypeConstraint(typeof(Exception)), code); + } + + /// + /// Verifies that a delegate throws an exception of a certain Type + /// or one derived from it when called and returns it. + /// + /// The expected Exception Type + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static Exception Catch(Type expectedExceptionType, TestDelegate code, string message, params object[] args) + { + return Throws(new InstanceOfTypeConstraint(expectedExceptionType), code, message, args); + } + + /// + /// Verifies that a delegate throws an exception of a certain Type + /// or one derived from it when called and returns it. + /// + /// The expected Exception Type + /// A TestDelegate + /// The message that will be displayed on failure + public static Exception Catch(Type expectedExceptionType, TestDelegate code, string message) + { + return Throws(new InstanceOfTypeConstraint(expectedExceptionType), code, message); + } + + /// + /// Verifies that a delegate throws an exception of a certain Type + /// or one derived from it when called and returns it. + /// + /// The expected Exception Type + /// A TestDelegate + public static Exception Catch(Type expectedExceptionType, TestDelegate code) + { + return Throws(new InstanceOfTypeConstraint(expectedExceptionType), code); + } + #endregion + + #region Catch + +#if CLR_2_0 || CLR_4_0 + /// + /// Verifies that a delegate throws an exception of a certain Type + /// or one derived from it when called and returns it. + /// + /// The expected Exception Type + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static T Catch(TestDelegate code, string message, params object[] args) where T : System.Exception + { + return (T)Throws(new InstanceOfTypeConstraint(typeof(T)), code, message, args); + } + + /// + /// Verifies that a delegate throws an exception of a certain Type + /// or one derived from it when called and returns it. + /// + /// The expected Exception Type + /// A TestDelegate + /// The message that will be displayed on failure + public static T Catch(TestDelegate code, string message) where T : System.Exception + { + return (T)Throws(new InstanceOfTypeConstraint(typeof(T)), code, message); + } + + /// + /// Verifies that a delegate throws an exception of a certain Type + /// or one derived from it when called and returns it. + /// + /// The expected Exception Type + /// A TestDelegate + public static T Catch(TestDelegate code) where T : System.Exception + { + return (T)Throws(new InstanceOfTypeConstraint(typeof(T)), code); + } +#endif + + #endregion + + #region DoesNotThrow + + /// + /// Verifies that a delegate does not throw an exception + /// + /// A TestDelegate + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public static void DoesNotThrow(TestDelegate code, string message, params object[] args) + { + Assert.That(code, new ThrowsNothingConstraint(), message, args); + } + + /// + /// Verifies that a delegate does not throw an exception. + /// + /// A TestDelegate + /// The message that will be displayed on failure + public static void DoesNotThrow(TestDelegate code, string message) + { + DoesNotThrow(code, message, null); + } + + /// + /// Verifies that a delegate does not throw an exception. + /// + /// A TestDelegate + public static void DoesNotThrow(TestDelegate code) + { + DoesNotThrow(code, string.Empty, null); + } + + #endregion + + #endregion + + #region True + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void True(bool condition, string message, params object[] args) + { + Assert.That(condition, Is.True ,message, args); + } + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + public static void True(bool condition, string message) + { + Assert.That(condition, Is.True ,message, null); + } + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + public static void True(bool condition) + { + Assert.That(condition, Is.True ,null, null); + } + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void IsTrue(bool condition, string message, params object[] args) + { + Assert.That(condition, Is.True ,message, args); + } + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + public static void IsTrue(bool condition, string message) + { + Assert.That(condition, Is.True ,message, null); + } + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + public static void IsTrue(bool condition) + { + Assert.That(condition, Is.True ,null, null); + } + + #endregion + + #region False + + /// + /// Asserts that a condition is false. If the condition is true the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void False(bool condition, string message, params object[] args) + { + Assert.That(condition, Is.False ,message, args); + } + /// + /// Asserts that a condition is false. If the condition is true the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + public static void False(bool condition, string message) + { + Assert.That(condition, Is.False ,message, null); + } + /// + /// Asserts that a condition is false. If the condition is true the method throws + /// an . + /// + /// The evaluated condition + public static void False(bool condition) + { + Assert.That(condition, Is.False ,null, null); + } + + /// + /// Asserts that a condition is false. If the condition is true the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void IsFalse(bool condition, string message, params object[] args) + { + Assert.That(condition, Is.False ,message, args); + } + /// + /// Asserts that a condition is false. If the condition is true the method throws + /// an . + /// + /// The evaluated condition + /// The message to display in case of failure + public static void IsFalse(bool condition, string message) + { + Assert.That(condition, Is.False ,message, null); + } + /// + /// Asserts that a condition is false. If the condition is true the method throws + /// an . + /// + /// The evaluated condition + public static void IsFalse(bool condition) + { + Assert.That(condition, Is.False ,null, null); + } + + #endregion + + #region NotNull + + /// + /// Verifies that the object that is passed in is not equal to null + /// If the object is null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void NotNull(object anObject, string message, params object[] args) + { + Assert.That(anObject, Is.Not.Null ,message, args); + } + /// + /// Verifies that the object that is passed in is not equal to null + /// If the object is null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + public static void NotNull(object anObject, string message) + { + Assert.That(anObject, Is.Not.Null ,message, null); + } + /// + /// Verifies that the object that is passed in is not equal to null + /// If the object is null then an + /// is thrown. + /// + /// The object that is to be tested + public static void NotNull(object anObject) + { + Assert.That(anObject, Is.Not.Null ,null, null); + } + + /// + /// Verifies that the object that is passed in is not equal to null + /// If the object is null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void IsNotNull(object anObject, string message, params object[] args) + { + Assert.That(anObject, Is.Not.Null ,message, args); + } + /// + /// Verifies that the object that is passed in is not equal to null + /// If the object is null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + public static void IsNotNull(object anObject, string message) + { + Assert.That(anObject, Is.Not.Null ,message, null); + } + /// + /// Verifies that the object that is passed in is not equal to null + /// If the object is null then an + /// is thrown. + /// + /// The object that is to be tested + public static void IsNotNull(object anObject) + { + Assert.That(anObject, Is.Not.Null ,null, null); + } + + #endregion + + #region Null + + /// + /// Verifies that the object that is passed in is equal to null + /// If the object is not null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void Null(object anObject, string message, params object[] args) + { + Assert.That(anObject, Is.Null ,message, args); + } + /// + /// Verifies that the object that is passed in is equal to null + /// If the object is not null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + public static void Null(object anObject, string message) + { + Assert.That(anObject, Is.Null ,message, null); + } + /// + /// Verifies that the object that is passed in is equal to null + /// If the object is not null then an + /// is thrown. + /// + /// The object that is to be tested + public static void Null(object anObject) + { + Assert.That(anObject, Is.Null ,null, null); + } + + /// + /// Verifies that the object that is passed in is equal to null + /// If the object is not null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void IsNull(object anObject, string message, params object[] args) + { + Assert.That(anObject, Is.Null ,message, args); + } + /// + /// Verifies that the object that is passed in is equal to null + /// If the object is not null then an + /// is thrown. + /// + /// The object that is to be tested + /// The message to display in case of failure + public static void IsNull(object anObject, string message) + { + Assert.That(anObject, Is.Null ,message, null); + } + /// + /// Verifies that the object that is passed in is equal to null + /// If the object is not null then an + /// is thrown. + /// + /// The object that is to be tested + public static void IsNull(object anObject) + { + Assert.That(anObject, Is.Null ,null, null); + } + + #endregion + + #region AreEqual + + #region Ints + + /// + /// Verifies that two ints are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreEqual(int expected, int actual, string message, params object[] args) + { + Assert.That(actual, Is.EqualTo(expected), message, args); + } + /// + /// Verifies that two ints are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreEqual(int expected, int actual, string message) + { + Assert.That(actual, Is.EqualTo(expected), message, null); + } + /// + /// Verifies that two ints are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreEqual(int expected, int actual) + { + Assert.That(actual, Is.EqualTo(expected), null, null); + } + + #endregion + + #region Longs + + /// + /// Verifies that two longs are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreEqual(long expected, long actual, string message, params object[] args) + { + Assert.That(actual, Is.EqualTo(expected), message, args); + } + /// + /// Verifies that two longs are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreEqual(long expected, long actual, string message) + { + Assert.That(actual, Is.EqualTo(expected), message, null); + } + /// + /// Verifies that two longs are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreEqual(long expected, long actual) + { + Assert.That(actual, Is.EqualTo(expected), null, null); + } + + #endregion + + #region Unsigned Ints + + /// + /// Verifies that two unsigned ints are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + [CLSCompliant(false)] + public static void AreEqual(uint expected, uint actual, string message, params object[] args) + { + Assert.That(actual, Is.EqualTo(expected), message, args); + } + /// + /// Verifies that two unsigned ints are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + [CLSCompliant(false)] + public static void AreEqual(uint expected, uint actual, string message) + { + Assert.That(actual, Is.EqualTo(expected), message, null); + } + /// + /// Verifies that two unsigned ints are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + [CLSCompliant(false)] + public static void AreEqual(uint expected, uint actual) + { + Assert.That(actual, Is.EqualTo(expected), null, null); + } + + #endregion + + #region Unsigned Longs + + /// + /// Verifies that two unsigned longs are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + [CLSCompliant(false)] + public static void AreEqual(ulong expected, ulong actual, string message, params object[] args) + { + Assert.That(actual, Is.EqualTo(expected), message, args); + } + /// + /// Verifies that two unsigned longs are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + [CLSCompliant(false)] + public static void AreEqual(ulong expected, ulong actual, string message) + { + Assert.That(actual, Is.EqualTo(expected), message, null); + } + /// + /// Verifies that two unsigned longs are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + [CLSCompliant(false)] + public static void AreEqual(ulong expected, ulong actual) + { + Assert.That(actual, Is.EqualTo(expected), null, null); + } + + #endregion + + #region Decimals + + /// + /// Verifies that two decimals are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreEqual(decimal expected, decimal actual, string message, params object[] args) + { + Assert.That(actual, Is.EqualTo(expected), message, args); + } + /// + /// Verifies that two decimals are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreEqual(decimal expected, decimal actual, string message) + { + Assert.That(actual, Is.EqualTo(expected), message, null); + } + /// + /// Verifies that two decimals are equal. If they are not, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreEqual(decimal expected, decimal actual) + { + Assert.That(actual, Is.EqualTo(expected), null, null); + } + + #endregion + + #region Doubles + + /// + /// Verifies that two doubles are equal considering a delta. If the + /// expected value is infinity then the delta value is ignored. If + /// they are not equal then an is + /// thrown. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreEqual(double expected, double actual, double delta, string message, params object[] args) + { + AssertDoublesAreEqual(expected, actual, delta, message, args); + } + /// + /// Verifies that two doubles are equal considering a delta. If the + /// expected value is infinity then the delta value is ignored. If + /// they are not equal then an is + /// thrown. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + /// The message to display in case of failure + public static void AreEqual(double expected, double actual, double delta, string message) + { + AssertDoublesAreEqual(expected, actual, delta, message, null); + } + /// + /// Verifies that two doubles are equal considering a delta. If the + /// expected value is infinity then the delta value is ignored. If + /// they are not equal then an is + /// thrown. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + public static void AreEqual(double expected, double actual, double delta) + { + AssertDoublesAreEqual(expected, actual, delta, null, null); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Verifies that two doubles are equal considering a delta. If the + /// expected value is infinity then the delta value is ignored. If + /// they are not equal then an is + /// thrown. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreEqual(double expected, double? actual, double delta, string message, params object[] args) + { + AssertDoublesAreEqual(expected, (double)actual, delta, message, args); + } + /// + /// Verifies that two doubles are equal considering a delta. If the + /// expected value is infinity then the delta value is ignored. If + /// they are not equal then an is + /// thrown. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + /// The message to display in case of failure + public static void AreEqual(double expected, double? actual, double delta, string message) + { + AssertDoublesAreEqual(expected, (double)actual, delta, message, null); + } + /// + /// Verifies that two doubles are equal considering a delta. If the + /// expected value is infinity then the delta value is ignored. If + /// they are not equal then an is + /// thrown. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + public static void AreEqual(double expected, double? actual, double delta) + { + AssertDoublesAreEqual(expected, (double)actual, delta, null, null); + } +#endif + + #endregion + + #region Objects + + /// + /// Verifies that two objects are equal. Two objects are considered + /// equal if both are null, or if both have the same value. NUnit + /// has special semantics for some object types. + /// If they are not equal an is thrown. + /// + /// The value that is expected + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreEqual(object expected, object actual, string message, params object[] args) + { + Assert.That(actual, Is.EqualTo(expected), message, args); + } + /// + /// Verifies that two objects are equal. Two objects are considered + /// equal if both are null, or if both have the same value. NUnit + /// has special semantics for some object types. + /// If they are not equal an is thrown. + /// + /// The value that is expected + /// The actual value + /// The message to display in case of failure + public static void AreEqual(object expected, object actual, string message) + { + Assert.That(actual, Is.EqualTo(expected), message, null); + } + /// + /// Verifies that two objects are equal. Two objects are considered + /// equal if both are null, or if both have the same value. NUnit + /// has special semantics for some object types. + /// If they are not equal an is thrown. + /// + /// The value that is expected + /// The actual value + public static void AreEqual(object expected, object actual) + { + Assert.That(actual, Is.EqualTo(expected), null, null); + } + + #endregion + + #endregion + + #region AreNotEqual + + #region Ints + + /// + /// Verifies that two ints are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotEqual(int expected, int actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two ints are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreNotEqual(int expected, int actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two ints are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreNotEqual(int expected, int actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Longs + + /// + /// Verifies that two longs are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotEqual(long expected, long actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two longs are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreNotEqual(long expected, long actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two longs are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreNotEqual(long expected, long actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Unsigned Ints + + /// + /// Verifies that two unsigned ints are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + [CLSCompliant(false)] + public static void AreNotEqual(uint expected, uint actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two unsigned ints are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + [CLSCompliant(false)] + public static void AreNotEqual(uint expected, uint actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two unsigned ints are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + [CLSCompliant(false)] + public static void AreNotEqual(uint expected, uint actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Unsigned Longs + + /// + /// Verifies that two unsigned longs are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + [CLSCompliant(false)] + public static void AreNotEqual(ulong expected, ulong actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two unsigned longs are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + [CLSCompliant(false)] + public static void AreNotEqual(ulong expected, ulong actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two unsigned longs are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + [CLSCompliant(false)] + public static void AreNotEqual(ulong expected, ulong actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Decimals + + /// + /// Verifies that two decimals are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotEqual(decimal expected, decimal actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two decimals are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreNotEqual(decimal expected, decimal actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two decimals are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreNotEqual(decimal expected, decimal actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Floats + + /// + /// Verifies that two floats are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotEqual(float expected, float actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two floats are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreNotEqual(float expected, float actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two floats are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreNotEqual(float expected, float actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Doubles + + /// + /// Verifies that two doubles are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotEqual(double expected, double actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two doubles are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + /// The message to display in case of failure + public static void AreNotEqual(double expected, double actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two doubles are not equal. If they are equal, then an + /// is thrown. + /// + /// The expected value + /// The actual value + public static void AreNotEqual(double expected, double actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #region Objects + + /// + /// Verifies that two objects are not equal. Two objects are considered + /// equal if both are null, or if both have the same value. NUnit + /// has special semantics for some object types. + /// If they are equal an is thrown. + /// + /// The value that is expected + /// The actual value + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotEqual(object expected, object actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, args); + } + /// + /// Verifies that two objects are not equal. Two objects are considered + /// equal if both are null, or if both have the same value. NUnit + /// has special semantics for some object types. + /// If they are equal an is thrown. + /// + /// The value that is expected + /// The actual value + /// The message to display in case of failure + public static void AreNotEqual(object expected, object actual, string message) + { + Assert.That(actual, Is.Not.EqualTo(expected), message, null); + } + /// + /// Verifies that two objects are not equal. Two objects are considered + /// equal if both are null, or if both have the same value. NUnit + /// has special semantics for some object types. + /// If they are equal an is thrown. + /// + /// The value that is expected + /// The actual value + public static void AreNotEqual(object expected, object actual) + { + Assert.That(actual, Is.Not.EqualTo(expected), null, null); + } + + #endregion + + #endregion + + #region AreSame + + /// + /// Asserts that two objects refer to the same object. If they + /// are not the same an is thrown. + /// + /// The expected object + /// The actual object + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreSame(object expected, object actual, string message, params object[] args) + { + Assert.That(actual, Is.SameAs(expected), message, args); + } + /// + /// Asserts that two objects refer to the same object. If they + /// are not the same an is thrown. + /// + /// The expected object + /// The actual object + /// The message to display in case of failure + public static void AreSame(object expected, object actual, string message) + { + Assert.That(actual, Is.SameAs(expected), message, null); + } + /// + /// Asserts that two objects refer to the same object. If they + /// are not the same an is thrown. + /// + /// The expected object + /// The actual object + public static void AreSame(object expected, object actual) + { + Assert.That(actual, Is.SameAs(expected), null, null); + } + + #endregion + + #region AreNotSame + + /// + /// Asserts that two objects do not refer to the same object. If they + /// are the same an is thrown. + /// + /// The expected object + /// The actual object + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + public static void AreNotSame(object expected, object actual, string message, params object[] args) + { + Assert.That(actual, Is.Not.SameAs(expected), message, args); + } + /// + /// Asserts that two objects do not refer to the same object. If they + /// are the same an is thrown. + /// + /// The expected object + /// The actual object + /// The message to display in case of failure + public static void AreNotSame(object expected, object actual, string message) + { + Assert.That(actual, Is.Not.SameAs(expected), message, null); + } + /// + /// Asserts that two objects do not refer to the same object. If they + /// are the same an is thrown. + /// + /// The expected object + /// The actual object + public static void AreNotSame(object expected, object actual) + { + Assert.That(actual, Is.Not.SameAs(expected), null, null); + } + + #endregion + + #region Helper Methods + + /// + /// Helper for Assert.AreEqual(double expected, double actual, ...) + /// allowing code generation to work consistently. + /// + /// The expected value + /// The actual value + /// The maximum acceptable difference between the + /// the expected and the actual + /// The message to display in case of failure + /// Array of objects to be used in formatting the message + protected static void AssertDoublesAreEqual(double expected, double actual, double delta, string message, object[] args) + { + if (double.IsNaN(expected) || double.IsInfinity(expected)) + Assert.That(actual, Is.EqualTo(expected), message, args); + else + Assert.That(actual, Is.EqualTo(expected).Within(delta), message, args); + } + + private static void IncrementAssertCount() + { + TestExecutionContext.CurrentContext.IncrementAssertCount(); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/AssertionHelper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/AssertionHelper.cs new file mode 100644 index 00000000000..0846087347c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/AssertionHelper.cs @@ -0,0 +1,366 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework +{ + /// + /// AssertionHelper is an optional base class for user tests, + /// allowing the use of shorter names for constraints and + /// asserts and avoiding conflict with the definition of + /// , from which it inherits much of its + /// behavior, in certain mock object frameworks. + /// + public class AssertionHelper : ConstraintFactory + { + #region Assert + //private Assertions assert = new Assertions(); + //public virtual Assertions Assert + //{ + // get { return assert; } + //} + #endregion + + #region Expect + + #region Object + +#if !CLR_2_0 && !CLR_4_0 + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. Works + /// identically to Assert.That. + /// + /// The actual value to test + /// A Constraint to be applied + public void Expect(object actual, IResolveConstraint expression) + { + Assert.That(actual, expression, null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. Works + /// identically to Assert.That. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message to be displayed in case of failure + public void Expect(object actual, IResolveConstraint expression, string message) + { + Assert.That(actual, expression, message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. Works + /// identically to Assert.That. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message to be displayed in case of failure + /// Arguments to use in formatting the message + public void Expect(object actual, IResolveConstraint expression, string message, params object[] args) + { + Assert.That(actual, expression, message, args); + } +#endif + + #endregion + + #region Boolean + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . Works Identically to + /// . + /// + /// The evaluated condition + /// The message to display if the condition is false + /// Arguments to be used in formatting the message + public void Expect(bool condition, string message, params object[] args) + { + Assert.That(condition, Is.True, message, args); + } + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . Works Identically to + /// . + /// + /// The evaluated condition + /// The message to display if the condition is false + public void Expect(bool condition, string message) + { + Assert.That(condition, Is.True, message, null); + } + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . Works Identically to . + /// + /// The evaluated condition + public void Expect(bool condition) + { + Assert.That(condition, Is.True, null, null); + } + + #endregion + + #region ref Boolean + +#if !CLR_2_0 && !CLR_4_0 + /// + /// Apply a constraint to a referenced boolean, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint to be applied + /// The actual value to test + public void Expect(ref bool actual, IResolveConstraint constraint) + { + Assert.That(ref actual, constraint.Resolve(), null, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint to be applied + /// The actual value to test + /// The message that will be displayed on failure + public void Expect(ref bool actual, IResolveConstraint constraint, string message) + { + Assert.That(ref actual, constraint.Resolve(), message, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public void Expect(ref bool actual, IResolveConstraint expression, string message, params object[] args) + { + Assert.That(ref actual, expression, message, args); + } +#endif + + #endregion + + #region ActualValueDelegate + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + public void Expect(ActualValueDelegate del, IResolveConstraint expr) + { + Assert.That(del, expr.Resolve(), null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + /// The message that will be displayed on failure + public void Expect(ActualValueDelegate del, IResolveConstraint expr, string message) + { + Assert.That(del, expr.Resolve(), message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public void Expect(ActualValueDelegate del, IResolveConstraint expr, string message, params object[] args) + { + Assert.That(del, expr, message, args); + } +#else + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + public void Expect(ActualValueDelegate del, IResolveConstraint expr) + { + Assert.That(del, expr.Resolve(), null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + /// The message that will be displayed on failure + public void Expect(ActualValueDelegate del, IResolveConstraint expr, string message) + { + Assert.That(del, expr.Resolve(), message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public void Expect(ActualValueDelegate del, IResolveConstraint expr, string message, params object[] args) + { + Assert.That(del, expr, message, args); + } +#endif + + #endregion + + #region ref Object + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + public void Expect(ref T actual, IResolveConstraint expression) + { + Assert.That(ref actual, expression, null, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + public void Expect(ref T actual, IResolveConstraint expression, string message) + { + Assert.That(ref actual, expression, message, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// The actual value to test + /// A Constraint to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + public void Expect(ref T actual, IResolveConstraint expression, string message, params object[] args) + { + Assert.That(ref actual, expression, message, args); + } +#endif + + #endregion + + #region TestDelegate + + /// + /// Asserts that the code represented by a delegate throws an exception + /// that satisfies the constraint provided. + /// + /// A TestDelegate to be executed + /// A ThrowsConstraint used in the test + public void Expect(TestDelegate code, IResolveConstraint constraint) + { + Assert.That((object)code, constraint); + } + + #endregion + + #endregion + + #region Expect + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint to be applied + /// The actual value to test + static public void Expect(T actual, IResolveConstraint expression) + { + Assert.That(actual, expression, null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint to be applied + /// The actual value to test + /// The message that will be displayed on failure + static public void Expect(T actual, IResolveConstraint expression, string message) + { + Assert.That(actual, expression, message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an assertion exception on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void Expect(T actual, IResolveConstraint expression, string message, params object[] args) + { + Assert.That(actual, expression, message, args); + } + +#endif + + #endregion + + #region Map + /// + /// Returns a ListMapper based on a collection. + /// + /// The original collection + /// + public ListMapper Map( ICollection original ) + { + return new ListMapper( original ); + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Assume.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Assume.cs new file mode 100644 index 00000000000..da693c448aa --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Assume.cs @@ -0,0 +1,360 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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.ComponentModel; +using NUnit.Framework.Constraints; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Provides static methods to express the assumptions + /// that must be met for a test to give a meaningful + /// result. If an assumption is not met, the test + /// should produce an inconclusive result. + /// + public class Assume + { + #region Equals and ReferenceEquals + + /// + /// The Equals method throws an AssertionException. This is done + /// to make sure there is no mistake by calling this function. + /// + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static new bool Equals(object a, object b) + { + // TODO: This should probably be InvalidOperationException + throw new AssertionException("Assert.Equals should not be used for Assertions"); + } + + /// + /// override the default ReferenceEquals to throw an AssertionException. This + /// implementation makes sure there is no mistake in calling this function + /// as part of Assert. + /// + /// + /// + public static new void ReferenceEquals(object a, object b) + { + throw new AssertionException("Assert.ReferenceEquals should not be used for Assertions"); + } + + #endregion + + #region Assume.That + + #region Object + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + static public void That(object actual, IResolveConstraint expression) + { + Assume.That(actual, expression, null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + /// The message that will be displayed on failure + static public void That(object actual, IResolveConstraint expression, string message) + { + Assume.That(actual, expression, message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(object actual, IResolveConstraint expression, string message, params object[] args) + { + Constraint constraint = expression.Resolve(); + + if (!constraint.Matches(actual)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new InconclusiveException(writer.ToString()); + } + } + #endregion + + #region Boolean + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display if the condition is false + /// Arguments to be used in formatting the message + static public void That(bool condition, string message, params object[] args) + { + Assume.That(condition, Is.True, message, args); + } + + /// + /// Asserts that a condition is true. If the condition is false the method throws + /// an . + /// + /// The evaluated condition + /// The message to display if the condition is false + static public void That(bool condition, string message) + { + Assume.That(condition, Is.True, message, null); + } + + /// + /// Asserts that a condition is true. If the condition is false the + /// method throws an . + /// + /// The evaluated condition + static public void That(bool condition) + { + Assume.That(condition, Is.True, null, null); + } + + #endregion + + #region ref Boolean + +#if !CLR_2_0 && !CLR_4_0 + /// + /// Apply a constraint to a referenced boolean, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + static public void That(ref bool actual, IResolveConstraint expression) + { + Assume.That(ref actual, expression.Resolve(), null, null); + } + + /// + /// Apply a constraint to a referenced boolean, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + /// The message that will be displayed on failure + static public void That(ref bool actual, IResolveConstraint expression, string message) + { + Assume.That(ref actual, expression.Resolve(), message, null); + } + + /// + /// Apply a constraint to a referenced boolean, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// The actual value to test + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ref bool actual, IResolveConstraint expression, string message, params object[] args) + { + Constraint constraint = expression.Resolve(); + + if (!constraint.Matches(ref actual)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new InconclusiveException(writer.ToString()); + } + } +#endif + + #endregion + + #region ActualValueDelegate + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + static public void That(ActualValueDelegate del, IResolveConstraint expr) + { + Assume.That(del, expr.Resolve(), null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + /// The message that will be displayed on failure + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message) + { + Assume.That(del, expr.Resolve(), message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message, params object[] args) + { + Constraint constraint = expr.Resolve(); + + if (!constraint.Matches(del)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new InconclusiveException(writer.ToString()); + } + } +#else + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + static public void That(ActualValueDelegate del, IResolveConstraint expr) + { + Assume.That(del, expr.Resolve(), null, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// An ActualValueDelegate returning the value to be tested + /// The message that will be displayed on failure + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message) + { + Assume.That(del, expr.Resolve(), message, null); + } + + /// + /// Apply a constraint to an actual value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// An ActualValueDelegate returning the value to be tested + /// A Constraint expression to be applied + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ActualValueDelegate del, IResolveConstraint expr, string message, params object[] args) + { + Constraint constraint = expr.Resolve(); + + if (!constraint.Matches(del)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new InconclusiveException(writer.ToString()); + } + } +#endif + + #endregion + + #region ref Object + +#if CLR_2_0 || CLR_4_0 + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + static public void That(ref T actual, IResolveConstraint expression) + { + Assume.That(ref actual, expression.Resolve(), null, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + /// The message that will be displayed on failure + static public void That(ref T actual, IResolveConstraint expression, string message) + { + Assume.That(ref actual, expression.Resolve(), message, null); + } + + /// + /// Apply a constraint to a referenced value, succeeding if the constraint + /// is satisfied and throwing an InconclusiveException on failure. + /// + /// A Constraint expression to be applied + /// The actual value to test + /// The message that will be displayed on failure + /// Arguments to be used in formatting the message + static public void That(ref T actual, IResolveConstraint expression, string message, params object[] args) + { + Constraint constraint = expression.Resolve(); + + if (!constraint.Matches(ref actual)) + { + MessageWriter writer = new TextMessageWriter(message, args); + constraint.WriteMessageTo(writer); + throw new InconclusiveException(writer.ToString()); + } + } +#endif + + #endregion + + #region TestDelegate + + /// + /// Asserts that the code represented by a delegate throws an exception + /// that satisfies the constraint provided. + /// + /// A TestDelegate to be executed + /// A ThrowsConstraint used in the test + static public void That(TestDelegate code, IResolveConstraint constraint) + { + Assume.That((object)code, constraint); + } + + #endregion + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CategoryAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CategoryAttribute.cs new file mode 100644 index 00000000000..d18c13486ec --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CategoryAttribute.cs @@ -0,0 +1,95 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Attribute used to apply a category to a test + /// + [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Assembly, AllowMultiple=true, Inherited=true)] + public class CategoryAttribute : NUnitAttribute, IApplyToTest + { + /// + /// The name of the category + /// + protected string categoryName; + + /// + /// Construct attribute for a given category based on + /// a name. The name may not contain the characters ',', + /// '+', '-' or '!'. However, this is not checked in the + /// constructor since it would cause an error to arise at + /// as the test was loaded without giving a clear indication + /// of where the problem is located. The error is handled + /// in NUnitFramework.cs by marking the test as not + /// runnable. + /// + /// The name of the category + public CategoryAttribute(string name) + { + this.categoryName = name.Trim(); + } + + /// + /// Protected constructor uses the Type name as the name + /// of the category. + /// + protected CategoryAttribute() + { + this.categoryName = this.GetType().Name; + if ( categoryName.EndsWith( "Attribute" ) ) + categoryName = categoryName.Substring( 0, categoryName.Length - 9 ); + } + + /// + /// The name of the category + /// + public string Name + { + get { return categoryName; } + } + + #region IApplyToTest Members + + /// + /// Modifies a test by adding a category to it. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + test.Properties.Add(PropertyNames.Category, this.Name); + + if (this.Name.IndexOfAny(new char[] { ',', '!', '+', '-' }) >= 0) + { + test.RunState = RunState.NotRunnable; + test.Properties.Set(PropertyNames.SkipReason, "Category name must not contain ',', '!', '+' or '-'"); + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CombinatorialAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CombinatorialAttribute.cs new file mode 100644 index 00000000000..cf9784eac86 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CombinatorialAttribute.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Marks a test to use a combinatorial join of any argument + /// data provided. Since this is the default, the attribute is + /// not needed. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=false)] + public class CombinatorialAttribute : PropertyAttribute + { + /// + /// Default constructor + /// + public CombinatorialAttribute() : base(PropertyNames.JoinType, "Combinatorial") { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CultureAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CultureAttribute.cs new file mode 100644 index 00000000000..b30c37ac7d5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/CultureAttribute.cs @@ -0,0 +1,131 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Globalization; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// CultureAttribute is used to mark a test fixture or an + /// individual method as applying to a particular Culture only. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Assembly, AllowMultiple = false, Inherited=false)] + public class CultureAttribute : IncludeExcludeAttribute, IApplyToTest + { + private CultureDetector cultureDetector = new CultureDetector(); + private CultureInfo currentCulture = CultureInfo.CurrentCulture; + + /// + /// Constructor with no cultures specified, for use + /// with named property syntax. + /// + public CultureAttribute() { } + + /// + /// Constructor taking one or more cultures + /// + /// Comma-deliminted list of cultures + public CultureAttribute(string cultures) : base(cultures) { } + + #region IApplyToTest members + + /// + /// Causes a test to be skipped if this CultureAttribute is not satisfied. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + if (test.RunState != RunState.NotRunnable && !IsCultureSupported()) + { + test.RunState = RunState.Skipped; + test.Properties.Set(PropertyNames.SkipReason, Reason); + } + } + + #endregion + + /// + /// Tests to determine if the current culture is supported + /// based on the properties of this attribute. + /// + /// True, if the current culture is supported + private bool IsCultureSupported() + { + if (Include != null && !cultureDetector.IsCultureSupported(Include)) + { + Reason = string.Format("Only supported under culture {0}", Include); + return false; + } + + if (Exclude != null && cultureDetector.IsCultureSupported(Exclude)) + { + Reason = string.Format("Not supported under culture {0}", Exclude); + return false; + } + + return true; + } + + /// + /// Test to determine if the a particular culture or comma- + /// delimited set of cultures is in use. + /// + /// Name of the culture or comma-separated list of culture names + /// True if the culture is in use on the system + public bool IsCultureSupported(string culture) + { + culture = culture.Trim(); + + if (culture.IndexOf(',') >= 0) + { + if (IsCultureSupported(culture.Split(new char[] { ',' }))) + return true; + } + else + { + if (currentCulture.Name == culture || currentCulture.TwoLetterISOLanguageName == culture) + return true; + } + + return false; + } + + /// + /// Test to determine if one of a collection of culturess + /// is being used currently. + /// + /// + /// + public bool IsCultureSupported(string[] cultures) + { + foreach (string culture in cultures) + if (IsCultureSupported(culture)) + return true; + + return false; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DataAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DataAttribute.cs new file mode 100644 index 00000000000..c009088e30e --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DataAttribute.cs @@ -0,0 +1,40 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// The abstract base class for all data-providing attributes + /// defined by NUnit. Used to select all data sources for a + /// method, class or parameter. + /// + public abstract class DataAttribute : NUnitAttribute + { + /// + /// Default constructor + /// + public DataAttribute() { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointAttribute.cs new file mode 100644 index 00000000000..418a2ee3d79 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointAttribute.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// Used to mark a field for use as a datapoint when executing a theory + /// within the same fixture that requires an argument of the field's Type. + /// + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class DatapointAttribute : NUnitAttribute + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointSourceAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointSourceAttribute.cs new file mode 100644 index 00000000000..6bfa051e005 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointSourceAttribute.cs @@ -0,0 +1,39 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// Used to mark a field, property or method providing a set of datapoints to + /// be used in executing any theories within the same fixture that require an + /// argument of the Type provided. The data source may provide an array of + /// the required Type or an IEnumerable<T>. + /// Synonymous with DatapointsAttribute. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class DatapointSourceAttribute : NUnitAttribute + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointsAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointsAttribute.cs new file mode 100644 index 00000000000..9b6253479f5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DatapointsAttribute.cs @@ -0,0 +1,39 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// Used to mark a field, property or method providing a set of datapoints to + /// be used in executing any theories within the same fixture that require an + /// argument of the Type provided. The data source may provide an array of + /// the required Type or an IEnumerable<T>. + /// Synonymous with DatapointSourceAttribute. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class DatapointsAttribute : DatapointSourceAttribute + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DescriptionAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DescriptionAttribute.cs new file mode 100644 index 00000000000..57338100104 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/DescriptionAttribute.cs @@ -0,0 +1,43 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Attribute used to provide descriptive text about a + /// test case or fixture. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false, Inherited=false)] + public sealed class DescriptionAttribute : PropertyAttribute + { + /// + /// Construct a description Attribute + /// + /// The text of the description + public DescriptionAttribute(string description) : base(PropertyNames.Description, description) { } + } + +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ExpectedExceptionAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ExpectedExceptionAttribute.cs new file mode 100644 index 00000000000..6967ac4a733 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ExpectedExceptionAttribute.cs @@ -0,0 +1,175 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework.Internal; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Api; + +namespace NUnit.Framework +{ + /// + /// ExpectedExceptionAttribute + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=false)] + public class ExpectedExceptionAttribute : NUnitAttribute + { + private ExpectedExceptionData exceptionData = new ExpectedExceptionData(); + + /// + /// Constructor for a non-specific exception + /// + public ExpectedExceptionAttribute() + { + } + + /// + /// Constructor for a given type of exception + /// + /// The type of the expected exception + public ExpectedExceptionAttribute(Type exceptionType) + { + exceptionData.ExpectedExceptionType = exceptionType; + } + + /// + /// Constructor for a given exception name + /// + /// The full name of the expected exception + public ExpectedExceptionAttribute(string exceptionName) + { + exceptionData.ExpectedExceptionName = exceptionName; + } + + /// + /// Gets or sets the expected exception type + /// + public Type ExpectedException + { + get { return exceptionData.ExpectedExceptionType; } + set { exceptionData.ExpectedExceptionType = value; } + } + + /// + /// Gets or sets the full Type name of the expected exception + /// + public string ExpectedExceptionName + { + get { return exceptionData.ExpectedExceptionName; } + set { exceptionData.ExpectedExceptionName = value; } + } + + /// + /// Gets or sets the expected message text + /// + public string ExpectedMessage + { + get { return exceptionData.ExpectedMessage; } + set { exceptionData.ExpectedMessage = value; } + } + + /// + /// Gets or sets the user message displayed in case of failure + /// + public string UserMessage + { + get { return exceptionData.UserMessage; } + set { exceptionData.UserMessage = value; } + } + + /// + /// Gets or sets the type of match to be performed on the expected message + /// + public MessageMatch MatchType + { + get { return exceptionData.MatchType; } + set { exceptionData.MatchType = value; } + } + + /// + /// Gets the name of a method to be used as an exception handler + /// + public string Handler + { + get { return exceptionData.HandlerName; } + set { exceptionData.HandlerName = value; } + } + + /// + /// Gets all data about the expected exception. + /// + public ExpectedExceptionData ExceptionData + { + get { return exceptionData; } + } + + //#region IApplyToTest Members + + //void IApplyToTest.ApplyToTest(ITest test) + //{ + // TestMethod testMethod = test as TestMethod; + // if (testMethod != null) + // testMethod.CustomDecorators.Add(new ExpectedExceptionDecorator()); + //} + + //#endregion + } + + /// + /// ExpectedExceptionDecorator applies to a TestCommand and returns + /// a success result only if the expected exception is thrown. + /// Otherwise, an appropriate failure result is returned. + /// + public class ExpectedExceptionDecorator : ICommandDecorator + { + private ExpectedExceptionData exceptionData; + + /// + /// Construct an ExpectedExceptionDecorator using specified data. + /// + /// Data describing the expected exception + public ExpectedExceptionDecorator(ExpectedExceptionData exceptionData) + { + this.exceptionData = exceptionData; + } + + #region ICommandDecorator Members + + CommandStage ICommandDecorator.Stage + { + get { return CommandStage.BelowSetUpTearDown; } + } + + int ICommandDecorator.Priority + { + get { return 0; } + } + + TestCommand ICommandDecorator.Decorate(TestCommand command) + { + return new ExpectedExceptionCommand(command, exceptionData); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ExplicitAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ExplicitAttribute.cs new file mode 100644 index 00000000000..9c1bb77d2b0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ExplicitAttribute.cs @@ -0,0 +1,75 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// ExplicitAttribute marks a test or test fixture so that it will + /// only be run if explicitly executed from the gui or command line + /// or if it is included by use of a filter. The test will not be + /// run simply because an enclosing suite is run. + /// + [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)] + public class ExplicitAttribute : NUnitAttribute, IApplyToTest + { + private string reason; + + /// + /// Default constructor + /// + public ExplicitAttribute() + { + this.reason = ""; + } + + /// + /// Constructor with a reason + /// + /// The reason test is marked explicit + public ExplicitAttribute(string reason) + { + this.reason = reason; + } + + #region IApplyToTest members + + /// + /// Modifies a test by marking it as explicit. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + if (test.RunState != RunState.NotRunnable) + { + test.RunState = RunState.Explicit; + test.Properties.Set(PropertyNames.SkipReason, reason); + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/IgnoreAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/IgnoreAttribute.cs new file mode 100644 index 00000000000..235cf6aef6f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/IgnoreAttribute.cs @@ -0,0 +1,75 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Attribute used to mark a test that is to be ignored. + /// Ignored tests result in a warning message when the + /// tests are run. + /// + [AttributeUsage(AttributeTargets.Method|AttributeTargets.Class|AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)] + public class IgnoreAttribute : NUnitAttribute, IApplyToTest + { + private string reason; + + /// + /// Constructs the attribute without giving a reason + /// for ignoring the test. + /// + public IgnoreAttribute() + { + this.reason = ""; + } + + /// + /// Constructs the attribute giving a reason for ignoring the test + /// + /// The reason for ignoring the test + public IgnoreAttribute(string reason) + { + this.reason = reason; + } + +#region IApplyToTest members + + /// + /// Modifies a test by marking it as Ignored. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + if (test.RunState != RunState.NotRunnable) + { + test.RunState = RunState.Ignored; + test.Properties.Set(PropertyNames.SkipReason, reason); + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/IncludeExcludeAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/IncludeExcludeAttribute.cs new file mode 100644 index 00000000000..2ab6c622be5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/IncludeExcludeAttribute.cs @@ -0,0 +1,83 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// Abstract base for Attributes that are used to include tests + /// in the test run based on environmental settings. + /// + public abstract class IncludeExcludeAttribute : NUnitAttribute + { + private string include; + private string exclude; + private string reason; + + /// + /// Constructor with no included items specified, for use + /// with named property syntax. + /// + public IncludeExcludeAttribute() { } + + /// + /// Constructor taking one or more included items + /// + /// Comma-delimited list of included items + public IncludeExcludeAttribute( string include ) + { + this.include = include; + } + + /// + /// Name of the item that is needed in order for + /// a test to run. Multiple itemss may be given, + /// separated by a comma. + /// + public string Include + { + get { return this.include; } + set { include = value; } + } + + /// + /// Name of the item to be excluded. Multiple items + /// may be given, separated by a comma. + /// + public string Exclude + { + get { return this.exclude; } + set { this.exclude = value; } + } + + /// + /// The reason for including or excluding the test + /// + public string Reason + { + get { return reason; } + set { reason = value; } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/MaxTimeAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/MaxTimeAttribute.cs new file mode 100644 index 00000000000..3f5122a7af2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/MaxTimeAttribute.cs @@ -0,0 +1,63 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Internal.Commands; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Summary description for MaxTimeAttribute. + /// + [AttributeUsage( AttributeTargets.Method, AllowMultiple=false, Inherited=false )] + public sealed class MaxTimeAttribute : PropertyAttribute, ICommandDecorator + { + /// + /// Construct a MaxTimeAttribute, given a time in milliseconds. + /// + /// The maximum elapsed time in milliseconds + public MaxTimeAttribute( int milliseconds ) + : base( milliseconds ) { } + + #region ICommandDecorator Members + + CommandStage ICommandDecorator.Stage + { + get { return CommandStage.AboveSetUpTearDown; } + } + + int ICommandDecorator.Priority + { + get { return 0; } + } + + TestCommand ICommandDecorator.Decorate(TestCommand command) + { + return new MaxTimeCommand(command); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/NUnitAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/NUnitAttribute.cs new file mode 100644 index 00000000000..993054a0ac9 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/NUnitAttribute.cs @@ -0,0 +1,38 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// The abstract base class for all custom attributes defined by NUnit. + /// + public abstract class NUnitAttribute : Attribute + { + /// + /// Default constructor + /// + public NUnitAttribute() { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PairwiseAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PairwiseAttribute.cs new file mode 100644 index 00000000000..94705eb2f0b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PairwiseAttribute.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Marks a test to use a pairwise join of any argument + /// data provided. Arguments will be combined in such a + /// way that all possible pairs of arguments are used. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=false)] + public class PairwiseAttribute : PropertyAttribute + { + /// + /// Default constructor + /// + public PairwiseAttribute() : base(PropertyNames.JoinType, "Pairwise") { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PlatformAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PlatformAttribute.cs new file mode 100644 index 00000000000..d5973d88893 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PlatformAttribute.cs @@ -0,0 +1,68 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// PlatformAttribute is used to mark a test fixture or an + /// individual method as applying to a particular platform only. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Assembly, AllowMultiple = true, Inherited=false)] + public class PlatformAttribute : IncludeExcludeAttribute, IApplyToTest + { + private PlatformHelper platformHelper = new PlatformHelper(); + + /// + /// Constructor with no platforms specified, for use + /// with named property syntax. + /// + public PlatformAttribute() { } + + /// + /// Constructor taking one or more platforms + /// + /// Comma-deliminted list of platforms + public PlatformAttribute(string platforms) : base(platforms) { } + + #region IApplyToTest members + + /// + /// Causes a test to be skipped if this PlatformAttribute is not satisfied. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + if (test.RunState != RunState.NotRunnable && !platformHelper.IsPlatformSupported(this)) + { + test.RunState = RunState.Skipped; + test.Properties.Add(PropertyNames.SkipReason, platformHelper.Reason); + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PropertyAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PropertyAttribute.cs new file mode 100644 index 00000000000..4babb4ffdf0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/PropertyAttribute.cs @@ -0,0 +1,113 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// PropertyAttribute is used to attach information to a test as a name/value pair.. + /// + [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Assembly, AllowMultiple=true, Inherited=true)] + public class PropertyAttribute : NUnitAttribute, IApplyToTest + { + private PropertyBag properties = new PropertyBag(); + + /// + /// Construct a PropertyAttribute with a name and string value + /// + /// The name of the property + /// The property value + public PropertyAttribute(string propertyName, string propertyValue) + { + this.properties.Add(propertyName, propertyValue); + } + + /// + /// Construct a PropertyAttribute with a name and int value + /// + /// The name of the property + /// The property value + public PropertyAttribute(string propertyName, int propertyValue) + { + this.properties.Add(propertyName, propertyValue); + } + + /// + /// Construct a PropertyAttribute with a name and double value + /// + /// The name of the property + /// The property value + public PropertyAttribute(string propertyName, double propertyValue) + { + this.properties.Add(propertyName, propertyValue); + } + + /// + /// Constructor for derived classes that set the + /// property dictionary directly. + /// + protected PropertyAttribute() { } + + /// + /// Constructor for use by derived classes that use the + /// name of the type as the property name. Derived classes + /// must ensure that the Type of the property value is + /// a standard type supported by the BCL. Any custom + /// types will cause a serialization Exception when + /// in the client. + /// + protected PropertyAttribute( object propertyValue ) + { + string propertyName = this.GetType().Name; + if ( propertyName.EndsWith( "Attribute" ) ) + propertyName = propertyName.Substring( 0, propertyName.Length - 9 ); + this.properties.Add(propertyName, propertyValue); + } + + /// + /// Gets the property dictionary for this attribute + /// + public IPropertyBag Properties + { + get { return properties; } + } + + #region IApplyToTest Members + + /// + /// Modifies a test by adding properties to it. + /// + /// The test to modify + public virtual void ApplyToTest(Test test) + { + foreach (string key in Properties.Keys) + foreach(object value in Properties[key]) + test.Properties.Add(key, value); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RandomAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RandomAttribute.cs new file mode 100644 index 00000000000..ea9ad65fc2f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RandomAttribute.cs @@ -0,0 +1,126 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// RandomAttribute is used to supply a set of random values + /// to a single parameter of a parameterized test. + /// + public class RandomAttribute : ValuesAttribute, IParameterDataSource + { + enum SampleType + { + Auto, + Raw, + IntRange, + DoubleRange + } + + SampleType sampleType; + private int count; + private int min, max; + private double dmin, dmax; + + /// + /// Construct a set of Enums if the type is an Enum otherwise + /// Construct a set of doubles from 0.0 to 1.0, + /// specifying only the count. + /// + /// + public RandomAttribute(int count) + { + this.count = count; + this.sampleType = SampleType.Raw; + } + + /// + /// Construct a set of doubles from min to max + /// + /// + /// + /// + public RandomAttribute(double min, double max, int count) + { + this.count = count; + this.dmin = min; + this.dmax = max; + this.sampleType = SampleType.DoubleRange; + } + + /// + /// Construct a set of ints from min to max + /// + /// + /// + /// + public RandomAttribute(int min, int max, int count) + { + this.count = count; + this.min = min; + this.max = max; + this.sampleType = SampleType.IntRange; + } + + /// + /// Get the collection of values to be used as arguments + /// + public new IEnumerable GetData(ParameterInfo parameter) + { + Randomizer r = Randomizer.GetRandomizer(parameter); + IList values; + + switch (sampleType) + { + default: + case SampleType.Raw: + if (parameter.ParameterType.IsEnum) + values = r.GetEnums(count,parameter.ParameterType); + else + values = r.GetDoubles(count); + break; + case SampleType.IntRange: + values = r.GetInts(min, max, count); + break; + case SampleType.DoubleRange: + values = r.GetDoubles(dmin, dmax, count); + break; + } + + // Copy the random values into the data array + // and call the base class which may need to + // convert them to another type. + this.data = new object[values.Count]; + for (int i = 0; i < values.Count; i++) + this.data[i] = values[i]; + + return base.GetData(parameter); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RangeAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RangeAttribute.cs new file mode 100644 index 00000000000..2c6a113a567 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RangeAttribute.cs @@ -0,0 +1,104 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; + +namespace NUnit.Framework +{ + /// + /// RangeAttribute is used to supply a range of values to an + /// individual parameter of a parameterized test. + /// + public class RangeAttribute : ValuesAttribute + { + /// + /// Construct a range of ints using default step of 1 + /// + /// + /// + public RangeAttribute(int from, int to) : this(from, to, 1) { } + + /// + /// Construct a range of ints specifying the step size + /// + /// + /// + /// + public RangeAttribute(int from, int to, int step) + { + int count = (to - from) / step + 1; + this.data = new object[count]; + int index = 0; + for (int val = from; index < count; val += step) + this.data[index++] = val; + } + + /// + /// Construct a range of longs + /// + /// + /// + /// + public RangeAttribute(long from, long to, long step) + { + long count = (to - from) / step + 1; + this.data = new object[count]; + int index = 0; + for (long val = from; index < count; val += step) + this.data[index++] = val; + } + + /// + /// Construct a range of doubles + /// + /// + /// + /// + public RangeAttribute(double from, double to, double step) + { + double tol = step / 1000; + int count = (int)((to - from) / step + tol + 1); + this.data = new object[count]; + int index = 0; + for (double val = from; index < count; val += step) + this.data[index++] = val; + } + + /// + /// Construct a range of floats + /// + /// + /// + /// + public RangeAttribute(float from, float to, float step) + { + float tol = step / 1000; + int count = (int)((to - from) / step + tol + 1); + this.data = new object[count]; + int index = 0; + for (float val = from; index < count; val += step) + this.data[index++] = val; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RepeatAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RepeatAttribute.cs new file mode 100644 index 00000000000..3eba6c064e3 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/RepeatAttribute.cs @@ -0,0 +1,90 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +#if false +// TODO: Rework this +// RepeatAttribute should either +// 1) Apply at load time to create the exact number of tests, or +// 2) Apply at run time, generating tests or results dynamically +// +// #1 is feasible but doesn't provide much benefit +// #2 requires infrastructure for dynamic test cases first +using System; +using NUnit.Framework.Api; +using NUnit.Framework.Internal.Commands; + +namespace NUnit.Framework +{ + /// + /// RepeatAttribute may be applied to test case in order + /// to run it multiple times. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)] + public class RepeatAttribute : PropertyAttribute, ICommandDecorator + { + /// + /// Construct a RepeatAttribute + /// + /// The number of times to run the test + public RepeatAttribute(int count) : base(count) { } + + //private int count; + + ///// + ///// Construct a RepeatAttribute + ///// + ///// The number of times to run the test + //public RepeatAttribute(int count) + //{ + // this.count = count; + //} + + ///// + ///// Gets the number of times to run the test. + ///// + //public int Count + //{ + // get { return count; } + //} + + #region ICommandDecorator Members + + CommandStage ICommandDecorator.Stage + { + get { return CommandStage.Repeat; } + } + + int ICommandDecorator.Priority + { + get { return 0; } + } + + TestCommand ICommandDecorator.Decorate(TestCommand command) + { + return new RepeatedTestCommand(command); + } + + #endregion + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SequentialAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SequentialAttribute.cs new file mode 100644 index 00000000000..df026345ba7 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SequentialAttribute.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Marks a test to use a Sequential join of any argument + /// data provided. Arguments will be combined into test cases, + /// taking the next value of each argument until all are used. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=false)] + public class SequentialAttribute : PropertyAttribute + { + /// + /// Default constructor + /// + public SequentialAttribute() : base(PropertyNames.JoinType, "Sequential") { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetCultureAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetCultureAttribute.cs new file mode 100644 index 00000000000..efd8e83495f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetCultureAttribute.cs @@ -0,0 +1,55 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Summary description for SetCultureAttribute. + /// + [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Assembly, AllowMultiple=false, Inherited=true)] + public class SetCultureAttribute : PropertyAttribute, IApplyToContext + { + private string _culture; + + /// + /// Construct given the name of a culture + /// + /// + public SetCultureAttribute( string culture ) : base( PropertyNames.SetCulture, culture ) + { + _culture = culture; + } + + #region IApplyToContext Members + + void IApplyToContext.ApplyToContext(TestExecutionContext context) + { + context.CurrentCulture = new System.Globalization.CultureInfo(_culture); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetUICultureAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetUICultureAttribute.cs new file mode 100644 index 00000000000..d410fad1db1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetUICultureAttribute.cs @@ -0,0 +1,55 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Summary description for SetUICultureAttribute. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Assembly, AllowMultiple = false, Inherited=true)] + public class SetUICultureAttribute : PropertyAttribute, IApplyToContext + { + private string _culture; + + /// + /// Construct given the name of a culture + /// + /// + public SetUICultureAttribute(string culture) : base("SetUICulture", culture) + { + _culture = culture; + } + + #region IApplyToContext Members + + void IApplyToContext.ApplyToContext(TestExecutionContext context) + { + context.CurrentUICulture = new System.Globalization.CultureInfo(_culture); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetUpAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetUpAttribute.cs new file mode 100644 index 00000000000..9ac173b4b04 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/SetUpAttribute.cs @@ -0,0 +1,54 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Attribute used to mark a class that contains one-time SetUp + /// and/or TearDown methods that apply to all the tests in a + /// namespace or an assembly. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=true)] + public class SetUpAttribute : NUnitAttribute + { } + + /// + /// Attribute used to mark a class that contains one-time SetUp + /// and/or TearDown methods that apply to all the tests in a + /// namespace or an assembly. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=true)] + public class PreTestAttribute : NUnitAttribute + { } + + /// + /// Attribute used to mark a class that contains one-time SetUp + /// and/or TearDown methods that apply to all the tests in a + /// namespace or an assembly. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=true)] + public class PostTestAttribute : NUnitAttribute + { } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TearDownAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TearDownAttribute.cs new file mode 100644 index 00000000000..c4b88b590d1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TearDownAttribute.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Attribute used to identify a method that is called + /// immediately after each test is run. The method is + /// guaranteed to be called, even if an exception is thrown. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public class TearDownAttribute : NUnitAttribute + {} +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestAttribute.cs new file mode 100644 index 00000000000..e6dcd9a40cb --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestAttribute.cs @@ -0,0 +1,79 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + using NUnit.Framework.Api; + using NUnit.Framework.Internal; + + /// + /// Adding this attribute to a method within a + /// class makes the method callable from the NUnit test runner. There is a property + /// called Description which is optional which you can provide a more detailed test + /// description. This class cannot be inherited. + /// + /// + /// + /// [TestFixture] + /// public class Fixture + /// { + /// [Test] + /// public void MethodToTest() + /// {} + /// + /// [Test(Description = "more detailed description")] + /// publc void TestDescriptionMethod() + /// {} + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public class TestAttribute : NUnitAttribute, IApplyToTest + { + private string description; + + /// + /// Descriptive text for this test + /// + public string Description + { + get { return description; } + set { description = value; } + } + + #region IApplyToTest Members + + /// + /// Modifies a test by adding a description, if not already set. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + if (!test.Properties.ContainsKey(PropertyNames.Description) && description != null) + test.Properties.Set(PropertyNames.Description, description); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestCaseAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestCaseAttribute.cs new file mode 100644 index 00000000000..25d7933d26f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestCaseAttribute.cs @@ -0,0 +1,446 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// TestCaseAttribute is used to mark parameterized test cases + /// and provide them with their arguments. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited=false)] + public class TestCaseAttribute : DataAttribute, ITestCaseData, ITestCaseSource + { + #region Instance variables + + private object[] arguments; + // NOTE: Ignore unsupressed warning about exceptionData in .NET 1.1 build + private ExpectedExceptionData exceptionData; + private object expectedResult; + private bool hasExpectedResult; + private IPropertyBag properties; + private RunState runState; + + #endregion + + #region Constructors + + /// + /// Construct a TestCaseAttribute with a list of arguments. + /// This constructor is not CLS-Compliant + /// + /// + public TestCaseAttribute(params object[] arguments) + { + this.runState = RunState.Runnable; + + if (arguments == null) + this.arguments = new object[] { null }; + else + this.arguments = arguments; + } + + /// + /// Construct a TestCaseAttribute with a single argument + /// + /// + public TestCaseAttribute(object arg) + { + this.runState = RunState.Runnable; + this.arguments = new object[] { arg }; + } + + /// + /// Construct a TestCaseAttribute with a two arguments + /// + /// + /// + public TestCaseAttribute(object arg1, object arg2) + { + this.runState = RunState.Runnable; + this.arguments = new object[] { arg1, arg2 }; + } + + /// + /// Construct a TestCaseAttribute with a three arguments + /// + /// + /// + /// + public TestCaseAttribute(object arg1, object arg2, object arg3) + { + this.runState = RunState.Runnable; + this.arguments = new object[] { arg1, arg2, arg3 }; + } + + #endregion + + #region Properties + + /// + /// Gets the list of arguments to a test case + /// + public object[] Arguments + { + get { return arguments; } + } + + /// + /// Gets or sets the expected result. + /// + /// The result. + public object ExpectedResult + { + get { return expectedResult; } + set + { + expectedResult = value; + hasExpectedResult = true; + } + } + + /// + /// Gets the expected result (alias for use + /// by NUnit 2.6.x runners and for use + /// in legacy code. Remove the setter + /// after a time.) + /// + [Obsolete("Use ExpectedResult")] + public object Result + { + get { return ExpectedResult; } + set { ExpectedResult = value; } + } + + /// + /// Returns true if the expected result has been set + /// + public bool HasExpectedResult + { + get { return hasExpectedResult; } + } + + /// + /// Gets data about any expected exception for this test case. + /// + public ExpectedExceptionData ExceptionData + { + get { return exceptionData; } + } + + /// + /// Gets or sets the expected exception. + /// + /// The expected exception. + public Type ExpectedException + { + get { return exceptionData.ExpectedExceptionType; } + set { exceptionData.ExpectedExceptionType = value; } + } + + /// + /// Gets or sets the name the expected exception. + /// + /// The expected name of the exception. + public string ExpectedExceptionName + { + get { return exceptionData.ExpectedExceptionName; } + set { exceptionData.ExpectedExceptionName = value; } + } + + /// + /// Gets or sets the expected message of the expected exception + /// + /// The expected message of the exception. + public string ExpectedMessage + { + get { return exceptionData.ExpectedMessage; } + set { exceptionData.ExpectedMessage = value; } + } + + /// + /// Gets or sets the type of match to be performed on the expected message + /// + public MessageMatch MatchType + { + get { return exceptionData.MatchType; } + set { exceptionData.MatchType = value; } + } + + /// + /// Gets or sets the description. + /// + /// The description. + public string Description + { + get { return this.Properties.Get(PropertyNames.Description) as string; } + set { this.Properties.Set(PropertyNames.Description, value); } + } + + private string testName; + /// + /// Gets or sets the name of the test. + /// + /// The name of the test. + public string TestName + { + get { return testName; } + set { testName = value; } + } + + /// + /// Gets or sets the ignored status of the test + /// + public bool Ignore + { + get { return this.RunState == RunState.Ignored; } + set { this.runState = value ? RunState.Ignored : RunState.Runnable; } + } + + /// + /// Gets or sets a value indicating whether this is explicit. + /// + /// + /// true if explicit; otherwise, false. + /// + public bool Explicit + { + get { return this.RunState == RunState.Explicit; } + set { this.runState = value ? RunState.Explicit : RunState.Runnable; } + } + + /// + /// Gets the RunState of this test case. + /// + public RunState RunState + { + get { return runState; } + } + + /// + /// Gets or sets the reason for not running the test. + /// + /// The reason. + public string Reason + { + get { return this.Properties.Get(PropertyNames.SkipReason) as string; } + set { this.Properties.Set(PropertyNames.SkipReason, value); } + } + + /// + /// Gets or sets the ignore reason. When set to a non-null + /// non-empty value, the test is marked as ignored. + /// + /// The ignore reason. + public string IgnoreReason + { + get { return this.Reason; } + set + { + this.runState = RunState.Ignored; + this.Reason = value; + } + } + + /// + /// Gets and sets the category for this fixture. + /// May be a comma-separated list of categories. + /// + public string Category + { + get { return Properties.Get(PropertyNames.Category) as string; } + set + { + foreach (string cat in value.Split(new char[] { ',' }) ) + Properties.Add(PropertyNames.Category, cat); + } + } + + /// + /// Gets a list of categories for this fixture + /// + public IList Categories + { + get { return Properties[PropertyNames.Category] as IList; } + } + + /// + /// NYI + /// + public IPropertyBag Properties + { + get + { + if (properties == null) + properties = new PropertyBag(); + + return properties; + } + } + + #endregion + + #region ITestCaseSource Members + + /// + /// Returns an collection containing a single ITestCaseData item, + /// constructed from the arguments provided in the constructor and + /// possibly converted to match the specified method. + /// + /// The method for which data is being provided + /// +#if CLR_2_0 || CLR_4_0 + public System.Collections.Generic.IEnumerable GetTestCasesFor(System.Reflection.MethodInfo method) +#else + public System.Collections.IEnumerable GetTestCasesFor(System.Reflection.MethodInfo method) +#endif + { + ParameterSet parms; + + try + { + ParameterInfo[] parameters = method.GetParameters(); + int argsNeeded = parameters.Length; + int argsProvided = Arguments.Length; + + parms = new ParameterSet(this); + + // Special handling for params arguments + if (argsNeeded > 0 && argsProvided >= argsNeeded - 1) + { + ParameterInfo lastParameter = parameters[argsNeeded - 1]; + Type lastParameterType = lastParameter.ParameterType; + Type elementType = lastParameterType.GetElementType(); + + if (lastParameterType.IsArray && lastParameter.IsDefined(typeof(ParamArrayAttribute), false)) + { + if (argsProvided == argsNeeded) + { + Type lastArgumentType = parms.Arguments[argsProvided - 1].GetType(); + if (!lastParameterType.IsAssignableFrom(lastArgumentType)) + { + Array array = Array.CreateInstance(elementType, 1); + array.SetValue(parms.Arguments[argsProvided - 1], 0); + parms.Arguments[argsProvided - 1] = array; + } + } + else + { + object[] newArglist = new object[argsNeeded]; + for (int i = 0; i < argsNeeded && i < argsProvided; i++) + newArglist[i] = parms.Arguments[i]; + + int length = argsProvided - argsNeeded + 1; + Array array = Array.CreateInstance(elementType, length); + for (int i = 0; i < length; i++) + array.SetValue(parms.Arguments[argsNeeded + i - 1], i); + + newArglist[argsNeeded - 1] = array; + parms.Arguments = newArglist; + argsProvided = argsNeeded; + } + } + } + + //if (method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType == typeof(object[])) + // parms.Arguments = new object[]{parms.Arguments}; + + // Special handling when sole argument is an object[] + if (argsNeeded == 1 && method.GetParameters()[0].ParameterType == typeof(object[])) + { + if (argsProvided > 1 || + argsProvided == 1 && parms.Arguments[0].GetType() != typeof(object[])) + { + parms.Arguments = new object[] { parms.Arguments }; + } + } + + if (argsProvided == argsNeeded) + PerformSpecialConversions(parms.Arguments, parameters); + } + catch (Exception ex) + { + parms = new ParameterSet(ex); + } + + return new ITestCaseData[] { parms }; + } + + #endregion + + #region Helper Methods + /// + /// Performs several special conversions allowed by NUnit in order to + /// permit arguments with types that cannot be used in the constructor + /// of an Attribute such as TestCaseAttribute or to simplify their use. + /// + /// The arguments to be converted + /// The ParameterInfo array for the method + private static void PerformSpecialConversions(object[] arglist, ParameterInfo[] parameters) + { + for (int i = 0; i < arglist.Length; i++) + { + object arg = arglist[i]; + Type targetType = parameters[i].ParameterType; + + if (arg == null) + continue; + + if (arg is SpecialValue && (SpecialValue)arg == SpecialValue.Null) + { + arglist[i] = null; + continue; + } + + if (targetType.IsAssignableFrom(arg.GetType())) + continue; + + if (arg is DBNull) + { + arglist[i] = null; + continue; + } + + bool convert = false; + + if (targetType == typeof(short) || targetType == typeof(byte) || targetType == typeof(sbyte)) + convert = arg is int; + else + if (targetType == typeof(decimal)) + convert = arg is double || arg is string || arg is int; + else + if (targetType == typeof(DateTime) || targetType == typeof(TimeSpan)) + convert = arg is string; + + if (convert) + arglist[i] = Convert.ChangeType(arg, targetType, System.Globalization.CultureInfo.InvariantCulture); + } + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestCaseSourceAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestCaseSourceAttribute.cs new file mode 100644 index 00000000000..5fc8fe12be3 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestCaseSourceAttribute.cs @@ -0,0 +1,212 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// TestCaseSourceAttribute indicates the source to be used to + /// provide test cases for a test method. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] + public class TestCaseSourceAttribute : DataAttribute, ITestCaseSource + { + private readonly string sourceName; + private readonly Type sourceType; + + /// + /// Construct with the name of the method, property or field that will prvide data + /// + /// The name of the method, property or field that will provide data + public TestCaseSourceAttribute(string sourceName) + { + this.sourceName = sourceName; + } + + /// + /// Construct with a Type and name + /// + /// The Type that will provide data + /// The name of the method, property or field that will provide data + public TestCaseSourceAttribute(Type sourceType, string sourceName) + { + this.sourceType = sourceType; + this.sourceName = sourceName; + } + + /// + /// Construct with a Type + /// + /// The type that will provide data + public TestCaseSourceAttribute(Type sourceType) + { + this.sourceType = sourceType; + } + + /// + /// The name of a the method, property or fiend to be used as a source + /// + public string SourceName + { + get { return sourceName; } + } + + /// + /// A Type to be used as a source + /// + public Type SourceType + { + get { return sourceType; } + } + + private string category; + /// + /// Gets or sets the category associated with this test. + /// May be a single category or a comma-separated list. + /// + public string Category + { + get { return category; } + set { category = value; } + } + + #region ITestCaseSource Members + /// + /// Returns a set of ITestCaseDataItems for use as arguments + /// to a parameterized test method. + /// + /// The method for which data is needed. + /// +#if CLR_2_0 || CLR_4_0 + public IEnumerable GetTestCasesFor(MethodInfo method) + { + List data = new List(); +#else + public IEnumerable GetTestCasesFor(MethodInfo method) + { + ArrayList data = new ArrayList(); +#endif + IEnumerable source = GetTestCaseSource(method); + + if (source != null) + { + ParameterInfo[] parameters = method.GetParameters(); + + foreach (object item in source) + { + ParameterSet parms = new ParameterSet(); + ITestCaseData testCaseData = item as ITestCaseData; + + if (testCaseData != null) + parms = new ParameterSet(testCaseData); + else if (item is object[]) + { + object[] array = item as object[]; + parms.Arguments = array.Length == parameters.Length + ? array + : new object[] { item }; + } + //else if (parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(item.GetType())) + //{ + // parms.Arguments = new object[] { item }; + //} + else if (item is Array) + { + Array array = item as Array; + + if (array.Rank == 1 && array.Length == parameters.Length) + { + parms.Arguments = new object[array.Length]; + for (int i = 0; i < array.Length; i++) + parms.Arguments[i] = (object)array.GetValue(i); + } + else + { + parms.Arguments = new object[] { item }; + } + } + else + { + parms.Arguments = new object[] { item }; + } + + if (this.Category != null) + foreach (string cat in this.Category.Split(new char[] { ',' })) + parms.Properties.Add(PropertyNames.Category, cat); + + data.Add(parms); + } + } + + return data; + } + + private IEnumerable GetTestCaseSource(MethodInfo method) + { + IEnumerable source = null; + + Type sourceType = this.sourceType; + if (sourceType == null) + sourceType = method.ReflectedType; + + if (this.sourceName == null) + { + return Reflect.Construct(sourceType) as IEnumerable; + } + + MemberInfo[] members = sourceType.GetMember(sourceName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + if (members.Length == 1) + { + MemberInfo member = members[0]; + object sourceobject = Internal.Reflect.Construct(sourceType); + switch (member.MemberType) + { + case MemberTypes.Field: + FieldInfo field = member as FieldInfo; + source = (IEnumerable)field.GetValue(sourceobject); + break; + case MemberTypes.Property: + PropertyInfo property = member as PropertyInfo; + source = (IEnumerable)property.GetValue(sourceobject, null); + break; + case MemberTypes.Method: + MethodInfo m = member as MethodInfo; + source = (IEnumerable)m.Invoke(sourceobject, null); + break; + } + } + return source; + } + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureAttribute.cs new file mode 100644 index 00000000000..a272345ae96 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureAttribute.cs @@ -0,0 +1,202 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// [TestFixture] + /// public class ExampleClass + /// {} + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + public class TestFixtureAttribute : NUnitAttribute, IApplyToTest + { + private string description; + + private object[] originalArgs; + private object[] constructorArgs; + private Type[] typeArgs; + private bool argsInitialized; + + private bool isIgnored; + private string ignoreReason; + private string category; + + /// + /// Default constructor + /// + public TestFixtureAttribute() : this( null ) { } + + /// + /// Construct with a object[] representing a set of arguments. + /// In .NET 2.0, the arguments may later be separated into + /// type arguments and constructor arguments. + /// + /// + public TestFixtureAttribute(params object[] arguments) + { + this.originalArgs = arguments == null + ? new object[0] + : arguments; + this.constructorArgs = this.originalArgs; + this.typeArgs = new Type[0]; + } + + /// + /// Descriptive text for this fixture + /// + public string Description + { + get { return description; } + set { description = value; } + } + + /// + /// The arguments originally provided to the attribute + /// + public object[] Arguments + { + get + { + if (!argsInitialized) + InitializeArgs(); + return constructorArgs; + } + } + + /// + /// Gets or sets a value indicating whether this should be ignored. + /// + /// true if ignore; otherwise, false. + public bool Ignore + { + get { return isIgnored; } + set { isIgnored = value; } + } + + /// + /// Gets or sets the ignore reason. May set Ignored as a side effect. + /// + /// The ignore reason. + public string IgnoreReason + { + get { return ignoreReason; } + set + { + ignoreReason = value; + isIgnored = ignoreReason != null && ignoreReason != string.Empty; + } + } + + /// + /// Get or set the type arguments. If not set + /// explicitly, any leading arguments that are + /// Types are taken as type arguments. + /// + public Type[] TypeArgs + { + get + { + if (!argsInitialized) + InitializeArgs(); + return typeArgs; + } + set + { + typeArgs = value; + argsInitialized = true; + } + } + + /// + /// Gets and sets the category for this fixture. + /// May be a comma-separated list of categories. + /// + public string Category + { + get { return category; } + set { category = value; } + } + + /// + /// Gets a list of categories for this fixture + /// + public IList Categories + { + get { return category == null ? null : category.Split(','); } + } + + /// + /// Helper method to split the original argument list + /// into type arguments and constructor arguments. + /// This action has to be delayed rather than done in + /// the constructor, since TypeArgs may be set by + /// menas of a named parameter. + /// + private void InitializeArgs() + { + int typeArgCount = 0; + + if (this.originalArgs != null) + { + foreach (object o in this.originalArgs) + if (o is Type) typeArgCount++; + else break; + } + + this.typeArgs = new Type[typeArgCount]; + for (int i = 0; i < typeArgCount; i++) + this.typeArgs[i] = (Type)this.originalArgs[i]; + + int constructorArgCount = originalArgs.Length - typeArgCount; + this.constructorArgs = new object[constructorArgCount]; + for (int i = 0; i < constructorArgCount; i++) + this.constructorArgs[i] = this.originalArgs[typeArgCount + i]; + + argsInitialized = true; + } + + #region IApplyToTest Members + + /// + /// Modifies a test by adding a description, if not already set. + /// + /// The test to modify + public void ApplyToTest(Test test) + { + if (!test.Properties.ContainsKey(PropertyNames.Description) && description != null) + test.Properties.Set(PropertyNames.Description, description); + + if (category != null) + foreach (string cat in category.Split(new char[] { ',' }) ) + test.Properties.Add(PropertyNames.Category, cat); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureSetUpAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureSetUpAttribute.cs new file mode 100644 index 00000000000..5a51f35e259 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureSetUpAttribute.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Attribute used to identify a method that is + /// called before any tests in a fixture are run. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public class TestFixtureSetUpAttribute : NUnitAttribute + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureTearDownAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureTearDownAttribute.cs new file mode 100644 index 00000000000..90c286d5cf2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TestFixtureTearDownAttribute.cs @@ -0,0 +1,37 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Attribute used to identify a method that is called after + /// all the tests in a fixture have run. The method is + /// guaranteed to be called, even if an exception is thrown. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)] + public class TestFixtureTearDownAttribute : NUnitAttribute + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TheoryAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TheoryAttribute.cs new file mode 100644 index 00000000000..8d594687d69 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TheoryAttribute.cs @@ -0,0 +1,63 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Adding this attribute to a method within a + /// class makes the method callable from the NUnit test runner. There is a property + /// called Description which is optional which you can provide a more detailed test + /// description. This class cannot be inherited. + /// + /// + /// + /// [TestFixture] + /// public class Fixture + /// { + /// [Test] + /// public void MethodToTest() + /// {} + /// + /// [Test(Description = "more detailed description")] + /// publc void TestDescriptionMethod() + /// {} + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited=true)] + public class TheoryAttribute : NUnitAttribute + { + //private string description; + + ///// + ///// Descriptive text for this test + ///// + //public string Description + //{ + // get { return description; } + // set { description = value; } + //} + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TimeoutAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TimeoutAttribute.cs new file mode 100644 index 00000000000..ac7033f003f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/TimeoutAttribute.cs @@ -0,0 +1,60 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +#if (CLR_2_0 || CLR_4_0) +using System; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Api; + +namespace NUnit.Framework +{ + /// + /// Used on a method, marks the test with a timeout value in milliseconds. + /// The test will be run in a separate thread and is cancelled if the timeout + /// is exceeded. Used on a class or assembly, sets the default timeout + /// for all contained test methods. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false, Inherited=false)] + public class TimeoutAttribute : PropertyAttribute, IApplyToContext + { + private int _timeout; + + /// + /// Construct a TimeoutAttribute given a time in milliseconds + /// + /// The timeout value in milliseconds + public TimeoutAttribute(int timeout) + : base(timeout) + { + _timeout = timeout; + } + + void IApplyToContext.ApplyToContext(TestExecutionContext context) + { + context.TestCaseTimeout = _timeout; + } + } +} +#endif + diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ValueSourceAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ValueSourceAttribute.cs new file mode 100644 index 00000000000..38ff59e28b4 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ValueSourceAttribute.cs @@ -0,0 +1,146 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// ValueSourceAttribute indicates the source to be used to + /// provide data for one parameter of a test method. + /// + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)] + public class ValueSourceAttribute : DataAttribute, Api.IParameterDataSource + { + private readonly string sourceName; + private readonly Type sourceType; + + /// + /// Construct with the name of the factory - for use with languages + /// that don't support params arrays. + /// + /// The name of the data source to be used + public ValueSourceAttribute(string sourceName) + { + this.sourceName = sourceName; + } + + /// + /// Construct with a Type and name - for use with languages + /// that don't support params arrays. + /// + /// The Type that will provide data + /// The name of the method, property or field that will provide data + public ValueSourceAttribute(Type sourceType, string sourceName) + { + this.sourceType = sourceType; + this.sourceName = sourceName; + } + + /// + /// The name of a the method, property or fiend to be used as a source + /// + public string SourceName + { + get { return sourceName; } + } + + /// + /// A Type to be used as a source + /// + public Type SourceType + { + get { return sourceType; } + } + + #region IParameterDataSource Members + + /// + /// Gets an enumeration of data items for use as arguments + /// for a test method parameter. + /// + /// The parameter for which data is needed + /// + /// An enumeration containing individual data items + /// + public IEnumerable GetData(ParameterInfo parameter) + { + ObjectList data = new ObjectList(); + IEnumerable source = GetDataSource(parameter); + + if (source != null) + foreach (object item in source) + data.Add(item); + + return source; + } + + #endregion + + #region Helper Methods + + private IEnumerable GetDataSource(ParameterInfo parameter) + { + IEnumerable source = null; + + Type sourceType = this.sourceType; + if (sourceType == null) + sourceType = parameter.Member.ReflectedType; + + // TODO: Test this + if (this.sourceName == null) + { + return Reflect.Construct(sourceType) as IEnumerable; + } + + MemberInfo[] members = sourceType.GetMember(sourceName, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + if (members.Length == 1) + { + MemberInfo member = members[0]; + object sourceobject = Internal.Reflect.Construct(sourceType); + switch (member.MemberType) + { + case MemberTypes.Field: + FieldInfo field = member as FieldInfo; + source = (IEnumerable)field.GetValue(sourceobject); + break; + case MemberTypes.Property: + PropertyInfo property = member as PropertyInfo; + source = (IEnumerable)property.GetValue(sourceobject, null); + break; + case MemberTypes.Method: + MethodInfo m = member as MethodInfo; + source = (IEnumerable)m.Invoke(sourceobject, null); + break; + } + } + return source; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ValuesAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ValuesAttribute.cs new file mode 100644 index 00000000000..9ae2b269d72 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Attributes/ValuesAttribute.cs @@ -0,0 +1,134 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; + +namespace NUnit.Framework +{ + /// + /// ValuesAttribute is used to provide literal arguments for + /// an individual parameter of a test. + /// + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + public class ValuesAttribute : DataAttribute, Api.IParameterDataSource + { + /// + /// The collection of data to be returned. Must + /// be set by any derived attribute classes. + /// We use an object[] so that the individual + /// elements may have their type changed in GetData + /// if necessary + /// + // TODO: This causes a lot of boxing so we should eliminate it + protected object[] data; + + /// + /// Construct with one argument + /// + /// + public ValuesAttribute(object arg1) + { + data = new object[] { arg1 }; + } + + /// + /// Construct with two arguments + /// + /// + /// + public ValuesAttribute(object arg1, object arg2) + { + data = new object[] { arg1, arg2 }; + } + + /// + /// Construct with three arguments + /// + /// + /// + /// + public ValuesAttribute(object arg1, object arg2, object arg3) + { + data = new object[] { arg1, arg2, arg3 }; + } + + /// + /// Construct with an array of arguments + /// + /// + public ValuesAttribute(params object[] args) + { + data = args; + } + + /// + /// Get the collection of values to be used as arguments + /// + public IEnumerable GetData(ParameterInfo parameter) + { + Type targetType = parameter.ParameterType; + + for (int i = 0; i < data.Length; i++) + { + object arg = data[i]; + + if (arg == null) + continue; + + if (arg.GetType().FullName == "NUnit.Framework.SpecialValue" && + arg.ToString() == "Null") + { + data[i] = null; + continue; + } + + if (targetType.IsAssignableFrom(arg.GetType())) + continue; + + if (arg is DBNull) + { + data[i] = null; + continue; + } + + bool convert = false; + + if (targetType == typeof(short) || targetType == typeof(byte) || targetType == typeof(sbyte)) + convert = arg is int; + else + if (targetType == typeof(decimal)) + convert = arg is double || arg is string || arg is int; + else + if (targetType == typeof(DateTime) || targetType == typeof(TimeSpan)) + convert = arg is string; + + if (convert) + data[i] = Convert.ChangeType(arg, targetType, System.Globalization.CultureInfo.InvariantCulture); + } + + return data; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Compatibility/SerializableAttribute.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Compatibility/SerializableAttribute.cs new file mode 100644 index 00000000000..ae05dc72741 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Compatibility/SerializableAttribute.cs @@ -0,0 +1,35 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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. +// *********************************************************************** + +#if NETCF_1_0 || SILVERLIGHT +namespace System +{ + /// + /// Replacement for the SerializableAttribute so we compile + /// under Silverlight. + /// + public class SerializableAttribute : Attribute + { + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AllItemsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AllItemsConstraint.cs new file mode 100644 index 00000000000..cf537f4ef2e --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AllItemsConstraint.cs @@ -0,0 +1,75 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// AllItemsConstraint applies another constraint to each + /// item in a collection, succeeding if they all succeed. + /// + public class AllItemsConstraint : PrefixConstraint + { + /// + /// Construct an AllItemsConstraint on top of an existing constraint + /// + /// + public AllItemsConstraint(Constraint itemConstraint) + : base(itemConstraint) + { + this.DisplayName = "all"; + } + + /// + /// Apply the item constraint to each item in the collection, + /// failing if any item fails. + /// + /// + /// + public override bool Matches(object actual) + { + this.actual = actual; + + if (!(actual is IEnumerable)) + throw new ArgumentException("The actual value must be an IEnumerable", "actual"); + + foreach (object item in (IEnumerable)actual) + if (!baseConstraint.Matches(item)) + return false; + + return true; + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("all items"); + baseConstraint.WriteDescriptionTo(writer); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AndConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AndConstraint.cs new file mode 100644 index 00000000000..19b9e3c28a1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AndConstraint.cs @@ -0,0 +1,100 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// AndConstraint succeeds only if both members succeed. + /// + public class AndConstraint : BinaryConstraint + { + private enum FailurePoint + { + None, + Left, + Right + }; + + private FailurePoint failurePoint; + + /// + /// Create an AndConstraint from two other constraints + /// + /// The first constraint + /// The second constraint + public AndConstraint(Constraint left, Constraint right) : base(left, right) { } + + /// + /// Apply both member constraints to an actual value, succeeding + /// succeeding only if both of them succeed. + /// + /// The actual value + /// True if the constraints both succeeded + public override bool Matches(object actual) + { + this.actual = actual; + + failurePoint = left.Matches(actual) + ? right.Matches(actual) + ? FailurePoint.None + : FailurePoint.Right + : FailurePoint.Left; + + return failurePoint == FailurePoint.None; + } + + /// + /// Write a description for this contraint to a MessageWriter + /// + /// The MessageWriter to receive the description + public override void WriteDescriptionTo(MessageWriter writer) + { + left.WriteDescriptionTo(writer); + writer.WriteConnector("and"); + right.WriteDescriptionTo(writer); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + switch (failurePoint) + { + case FailurePoint.Left: + left.WriteActualValueTo(writer); + break; + case FailurePoint.Right: + right.WriteActualValueTo(writer); + break; + default: + base.WriteActualValueTo(writer); + break; + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AssignableFromConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AssignableFromConstraint.cs new file mode 100644 index 00000000000..4ec97570efe --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AssignableFromConstraint.cs @@ -0,0 +1,61 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// AssignableFromConstraint is used to test that an object + /// can be assigned from a given Type. + /// + public class AssignableFromConstraint : TypeConstraint + { + /// + /// Construct an AssignableFromConstraint for the type provided + /// + /// + public AssignableFromConstraint(Type type) : base(type) { } + + /// + /// Test whether an object can be assigned from the specified type + /// + /// The object to be tested + /// True if the object can be assigned a value of the expected Type, otherwise false. + public override bool Matches(object actual) + { + this.actual = actual; + return actual != null && actual.GetType().IsAssignableFrom(expectedType); + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// The MessageWriter to use + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("assignable from"); + writer.WriteExpectedValue(expectedType); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AssignableToConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AssignableToConstraint.cs new file mode 100644 index 00000000000..619c37e8123 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AssignableToConstraint.cs @@ -0,0 +1,61 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// AssignableToConstraint is used to test that an object + /// can be assigned to a given Type. + /// + public class AssignableToConstraint : TypeConstraint + { + /// + /// Construct an AssignableToConstraint for the type provided + /// + /// + public AssignableToConstraint(Type type) : base(type) { } + + /// + /// Test whether an object can be assigned to the specified type + /// + /// The object to be tested + /// True if the object can be assigned a value of the expected Type, otherwise false. + public override bool Matches(object actual) + { + this.actual = actual; + return actual != null && expectedType.IsAssignableFrom(actual.GetType()); + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// The MessageWriter to use + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("assignable to"); + writer.WriteExpectedValue(expectedType); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AttributeConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AttributeConstraint.cs new file mode 100644 index 00000000000..84025a65062 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AttributeConstraint.cs @@ -0,0 +1,106 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// AttributeConstraint tests that a specified attribute is present + /// on a Type or other provider and that the value of the attribute + /// satisfies some other constraint. + /// + public class AttributeConstraint : PrefixConstraint + { + private readonly Type expectedType; + private Attribute attrFound; + + /// + /// Constructs an AttributeConstraint for a specified attriute + /// Type and base constraint. + /// + /// + /// + public AttributeConstraint(Type type, Constraint baseConstraint) + : base(baseConstraint) + { + this.expectedType = type; + + if (!typeof(Attribute).IsAssignableFrom(expectedType)) + throw new ArgumentException(string.Format( + "Type {0} is not an attribute", expectedType), "type"); + } + + /// + /// Determines whether the Type or other provider has the + /// expected attribute and if its value matches the + /// additional constraint specified. + /// + public override bool Matches(object actual) + { + this.actual = actual; + System.Reflection.ICustomAttributeProvider attrProvider = + actual as System.Reflection.ICustomAttributeProvider; + + if (attrProvider == null) + throw new ArgumentException(string.Format("Actual value {0} does not implement ICustomAttributeProvider", actual), "actual"); + + Attribute[] attrs = (Attribute[])attrProvider.GetCustomAttributes(expectedType, true); + if (attrs.Length == 0) + throw new ArgumentException(string.Format("Attribute {0} was not found", expectedType), "actual"); + + attrFound = attrs[0]; + return baseConstraint.Matches(attrFound); + } + + /// + /// Writes a description of the attribute to the specified writer. + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("attribute " + expectedType.FullName); + if (baseConstraint != null) + { + if (baseConstraint is EqualConstraint) + writer.WritePredicate("equal to"); + baseConstraint.WriteDescriptionTo(writer); + } + } + + /// + /// Writes the actual value supplied to the specified writer. + /// + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(attrFound); + } + + /// + /// Returns a string representation of the constraint. + /// + protected override string GetStringRepresentation() + { + return string.Format("", expectedType, baseConstraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AttributeExistsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AttributeExistsConstraint.cs new file mode 100644 index 00000000000..5fb098f7df5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/AttributeExistsConstraint.cs @@ -0,0 +1,76 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// AttributeExistsConstraint tests for the presence of a + /// specified attribute on a Type. + /// + public class AttributeExistsConstraint : Constraint + { + private Type expectedType; + + /// + /// Constructs an AttributeExistsConstraint for a specific attribute Type + /// + /// + public AttributeExistsConstraint(Type type) + : base(type) + { + this.expectedType = type; + + if (!typeof(Attribute).IsAssignableFrom(expectedType)) + throw new ArgumentException(string.Format( + "Type {0} is not an attribute", expectedType), "type"); + } + + /// + /// Tests whether the object provides the expected attribute. + /// + /// A Type, MethodInfo, or other ICustomAttributeProvider + /// True if the expected attribute is present, otherwise false + public override bool Matches(object actual) + { + this.actual = actual; + System.Reflection.ICustomAttributeProvider attrProvider = + actual as System.Reflection.ICustomAttributeProvider; + + if (attrProvider == null) + throw new ArgumentException(string.Format("Actual value {0} does not implement ICustomAttributeProvider", actual), "actual"); + + return attrProvider.GetCustomAttributes(expectedType, true).Length > 0; + } + + /// + /// Writes the description of the constraint to the specified writer + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("type with attribute"); + writer.WriteExpectedValue(expectedType); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BasicConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BasicConstraint.cs new file mode 100644 index 00000000000..b55c95b151d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BasicConstraint.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// BasicConstraint is the abstract base for constraints that + /// perform a simple comparison to a constant value. + /// + public abstract class BasicConstraint : Constraint + { + private readonly object expected; + private readonly string description; + + /// + /// Initializes a new instance of the class. + /// + /// The expected. + /// The description. + protected BasicConstraint(object expected, string description) + { + this.expected = expected; + this.description = description; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (actual == null && expected == null) + return true; + + if (actual == null || expected == null) + return false; + + return expected.Equals(actual); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write(description); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BinaryConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BinaryConstraint.cs new file mode 100644 index 00000000000..37bc69d0867 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BinaryConstraint.cs @@ -0,0 +1,53 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// BinaryConstraint is the abstract base of all constraints + /// that combine two other constraints in some fashion. + /// + public abstract class BinaryConstraint : Constraint + { + /// + /// The first constraint being combined + /// + protected Constraint left; + /// + /// The second constraint being combined + /// + protected Constraint right; + + /// + /// Construct a BinaryConstraint from two other constraints + /// + /// The first constraint + /// The second constraint + protected BinaryConstraint(Constraint left, Constraint right) + : base(left, right) + { + this.left = left; + this.right = right; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BinarySerializableConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BinarySerializableConstraint.cs new file mode 100644 index 00000000000..c11bd91ed67 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/BinarySerializableConstraint.cs @@ -0,0 +1,100 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +#if !NETCF && !SILVERLIGHT +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; + +namespace NUnit.Framework.Constraints +{ + /// + /// BinarySerializableConstraint tests whether + /// an object is serializable in binary format. + /// + public class BinarySerializableConstraint : Constraint + { + readonly BinaryFormatter serializer = new BinaryFormatter(); + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (actual == null) + throw new ArgumentException(); + + MemoryStream stream = new MemoryStream(); + + try + { + serializer.Serialize(stream, actual); + + stream.Seek(0, SeekOrigin.Begin); + + object value = serializer.Deserialize(stream); + + return value != null; + } + catch (SerializationException) + { + return false; + } + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write("binary serializable"); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + writer.Write("<{0}>", actual.GetType().Name); + } + + /// + /// Returns the string representation + /// + protected override string GetStringRepresentation() + { + return ""; + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionConstraint.cs new file mode 100644 index 00000000000..5d0ad412c16 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionConstraint.cs @@ -0,0 +1,89 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionConstraint is the abstract base class for + /// constraints that operate on collections. + /// + public abstract class CollectionConstraint : Constraint + { + /// + /// Construct an empty CollectionConstraint + /// + protected CollectionConstraint() { } + + /// + /// Construct a CollectionConstraint + /// + /// + protected CollectionConstraint(object arg) : base(arg) { } + + /// + /// Determines whether the specified enumerable is empty. + /// + /// The enumerable. + /// + /// true if the specified enumerable is empty; otherwise, false. + /// + protected static bool IsEmpty(IEnumerable enumerable) + { + ICollection collection = enumerable as ICollection; + if (collection != null) + return collection.Count == 0; + + // NOTE: Ignore unsuppressed warning about o in .NET 1.1 build + foreach (object o in enumerable) + return false; + + return true; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + IEnumerable enumerable = actual as IEnumerable; + if (enumerable == null) + throw new ArgumentException("The actual value must be an IEnumerable", "actual"); + + return doMatch(enumerable); + } + + /// + /// Protected method to be implemented by derived classes + /// + /// + /// + protected abstract bool doMatch(IEnumerable collection); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionContainsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionContainsConstraint.cs new file mode 100644 index 00000000000..5c11c241df6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionContainsConstraint.cs @@ -0,0 +1,71 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionContainsConstraint is used to test whether a collection + /// contains an expected object as a member. + /// + public class CollectionContainsConstraint : CollectionItemsEqualConstraint + { + private readonly object expected; + + /// + /// Construct a CollectionContainsConstraint + /// + /// + public CollectionContainsConstraint(object expected) + : base(expected) + { + this.expected = expected; + this.DisplayName = "contains"; + } + + /// + /// Test whether the expected item is contained in the collection + /// + /// + /// + protected override bool doMatch(IEnumerable actual) + { + foreach (object obj in actual) + if (ItemsEqual(obj, expected)) + return true; + + return false; + } + + /// + /// Write a descripton of the constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("collection containing"); + writer.WriteExpectedValue(expected); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionEquivalentConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionEquivalentConstraint.cs new file mode 100644 index 00000000000..601f74bc966 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionEquivalentConstraint.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionEquivalentCOnstraint is used to determine whether two + /// collections are equivalent. + /// + public class CollectionEquivalentConstraint : CollectionItemsEqualConstraint + { + private readonly IEnumerable expected; + + /// + /// Construct a CollectionEquivalentConstraint + /// + /// + public CollectionEquivalentConstraint(IEnumerable expected) + : base(expected) + { + this.expected = expected; + this.DisplayName = "equivalent"; + } + + /// + /// Test whether two collections are equivalent + /// + /// + /// + protected override bool doMatch(IEnumerable actual) + { + // This is just an optimization + if (expected is ICollection && actual is ICollection) + if (((ICollection)actual).Count != ((ICollection)expected).Count) + return false; + + CollectionTally tally = Tally(expected); + return tally.TryRemove(actual) && tally.Count == 0; + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("equivalent to"); + writer.WriteExpectedValue(expected); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionItemsEqualConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionItemsEqualConstraint.cs new file mode 100644 index 00000000000..36e01d25d51 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionItemsEqualConstraint.cs @@ -0,0 +1,150 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionItemsEqualConstraint is the abstract base class for all + /// collection constraints that apply some notion of item equality + /// as a part of their operation. + /// + public abstract class CollectionItemsEqualConstraint : CollectionConstraint + { + private readonly NUnitEqualityComparer comparer = NUnitEqualityComparer.Default; + + /// + /// Construct an empty CollectionConstraint + /// + protected CollectionItemsEqualConstraint() { } + + /// + /// Construct a CollectionConstraint + /// + /// + protected CollectionItemsEqualConstraint(object arg) : base(arg) { } + + #region Modifiers + + /// + /// Flag the constraint to ignore case and return self. + /// + public CollectionItemsEqualConstraint IgnoreCase + { + get + { + comparer.IgnoreCase = true; + return this; + } + } + + /// + /// Flag the constraint to use the supplied EqualityAdapter. + /// NOTE: For internal use only. + /// + /// The EqualityAdapter to use. + /// Self. + internal CollectionItemsEqualConstraint Using(EqualityAdapter adapter) + { + this.comparer.ExternalComparers.Add(adapter); + return this; + } + + /// + /// Flag the constraint to use the supplied IComparer object. + /// + /// The IComparer object to use. + /// Self. + public CollectionItemsEqualConstraint Using(IComparer comparer) + { + return Using(EqualityAdapter.For(comparer)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Flag the constraint to use the supplied IComparer object. + /// + /// The IComparer object to use. + /// Self. + public CollectionItemsEqualConstraint Using(IComparer comparer) + { + return Using(EqualityAdapter.For(comparer)); + } + + /// + /// Flag the constraint to use the supplied Comparison object. + /// + /// The IComparer object to use. + /// Self. + public CollectionItemsEqualConstraint Using(Comparison comparer) + { + return Using(EqualityAdapter.For(comparer)); + } + + /// + /// Flag the constraint to use the supplied IEqualityComparer object. + /// + /// The IComparer object to use. + /// Self. + public CollectionItemsEqualConstraint Using(IEqualityComparer comparer) + { + return Using(EqualityAdapter.For(comparer)); + } + + /// + /// Flag the constraint to use the supplied IEqualityComparer object. + /// + /// The IComparer object to use. + /// Self. + public CollectionItemsEqualConstraint Using(IEqualityComparer comparer) + { + return Using(EqualityAdapter.For(comparer)); + } +#endif + + #endregion + + /// + /// Compares two collection members for equality + /// + protected bool ItemsEqual(object x, object y) + { + Tolerance tolerance = Tolerance.Zero; + return comparer.AreEqual(x, y, ref tolerance); + } + + /// + /// Return a new CollectionTally for use in making tests + /// + /// The collection to be included in the tally + protected CollectionTally Tally(IEnumerable c) + { + return new CollectionTally(comparer, c); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionOrderedConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionOrderedConstraint.cs new file mode 100644 index 00000000000..9fef7dd03e4 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionOrderedConstraint.cs @@ -0,0 +1,185 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +using System.Reflection; +using System.Text; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionOrderedConstraint is used to test whether a collection is ordered. + /// + public class CollectionOrderedConstraint : CollectionConstraint + { + private ComparisonAdapter comparer = ComparisonAdapter.Default; + private string comparerName; + private string propertyName; + private bool descending; + + /// + /// Construct a CollectionOrderedConstraint + /// + public CollectionOrderedConstraint() + { + this.DisplayName = "ordered"; + } + + /// + /// If used performs a reverse comparison + /// + public CollectionOrderedConstraint Descending + { + get + { + descending = true; + return this; + } + } + + /// + /// Modifies the constraint to use an IComparer and returns self. + /// + public CollectionOrderedConstraint Using(IComparer comparer) + { + this.comparer = ComparisonAdapter.For(comparer); + this.comparerName = comparer.GetType().FullName; + return this; + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Modifies the constraint to use an IComparer<T> and returns self. + /// + public CollectionOrderedConstraint Using(IComparer comparer) + { + this.comparer = ComparisonAdapter.For(comparer); + this.comparerName = comparer.GetType().FullName; + return this; + } + + /// + /// Modifies the constraint to use a Comparison<T> and returns self. + /// + public CollectionOrderedConstraint Using(Comparison comparer) + { + this.comparer = ComparisonAdapter.For(comparer); + this.comparerName = comparer.GetType().FullName; + return this; + } +#endif + + /// + /// Modifies the constraint to test ordering by the value of + /// a specified property and returns self. + /// + public CollectionOrderedConstraint By(string propertyName) + { + this.propertyName = propertyName; + return this; + } + + /// + /// Test whether the collection is ordered + /// + /// + /// + protected override bool doMatch(IEnumerable actual) + { + object previous = null; + int index = 0; + foreach (object obj in actual) + { + object objToCompare = obj; + if (obj == null) + throw new ArgumentNullException("actual", "Null value at index " + index.ToString()); + + if (this.propertyName != null) + { + PropertyInfo prop = obj.GetType().GetProperty(propertyName); + objToCompare = prop.GetValue(obj, null); + if (objToCompare == null) + throw new ArgumentNullException("actual", "Null property value at index " + index.ToString()); + } + + if (previous != null) + { + //int comparisonResult = comparer.Compare(al[i], al[i + 1]); + int comparisonResult = comparer.Compare(previous, objToCompare); + + if (descending && comparisonResult < 0) + return false; + if (!descending && comparisonResult > 0) + return false; + } + + previous = objToCompare; + index++; + } + + return true; + } + + /// + /// Write a description of the constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + if (propertyName == null) + writer.Write("collection ordered"); + else + { + writer.WritePredicate("collection ordered by"); + writer.WriteExpectedValue(propertyName); + } + + if (descending) + writer.WriteModifier("descending"); + } + + /// + /// Returns the string representation of the constraint. + /// + /// + protected override string GetStringRepresentation() + { + StringBuilder sb = new StringBuilder(""); + + return sb.ToString(); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionSubsetConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionSubsetConstraint.cs new file mode 100644 index 00000000000..68e903bdcb1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionSubsetConstraint.cs @@ -0,0 +1,67 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionSubsetConstraint is used to determine whether + /// one collection is a subset of another + /// + public class CollectionSubsetConstraint : CollectionItemsEqualConstraint + { + private IEnumerable expected; + + /// + /// Construct a CollectionSubsetConstraint + /// + /// The collection that the actual value is expected to be a subset of + public CollectionSubsetConstraint(IEnumerable expected) : base(expected) + { + this.expected = expected; + this.DisplayName = "subsetof"; + } + + /// + /// Test whether the actual collection is a subset of + /// the expected collection provided. + /// + /// + /// + protected override bool doMatch(IEnumerable actual) + { + return Tally(expected).TryRemove( actual ); + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate( "subset of" ); + writer.WriteExpectedValue(expected); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionTally.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionTally.cs new file mode 100644 index 00000000000..88f0048f202 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/CollectionTally.cs @@ -0,0 +1,95 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// CollectionTally counts (tallies) the number of + /// occurences of each object in one or more enumerations. + /// + public class CollectionTally + { + // Internal list used to track occurences + private readonly ObjectList list = new ObjectList(); + + private readonly NUnitEqualityComparer comparer; + + /// + /// Construct a CollectionTally object from a comparer and a collection + /// + public CollectionTally(NUnitEqualityComparer comparer, IEnumerable c) + { + this.comparer = comparer; + + foreach (object o in c) + list.Add(o); + } + + /// + /// The number of objects remaining in the tally + /// + public int Count + { + get { return list.Count; } + } + + private bool ItemsEqual(object expected, object actual) + { + Tolerance tolerance = Tolerance.Zero; + return comparer.AreEqual(expected, actual, ref tolerance); + } + + /// + /// Try to remove an object from the tally + /// + /// The object to remove + /// True if successful, false if the object was not found + public bool TryRemove(object o) + { + for (int index = 0; index < list.Count; index++) + if (ItemsEqual(list[index], o)) + { + list.RemoveAt(index); + return true; + } + + return false; + } + + /// + /// Try to remove a set of objects from the tally + /// + /// The objects to remove + /// True if successful, false if any object was not found + public bool TryRemove(IEnumerable c) + { + foreach (object o in c) + if (!TryRemove(o)) + return false; + + return true; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ComparisonAdapter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ComparisonAdapter.cs new file mode 100644 index 00000000000..0f64fbcf0d7 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ComparisonAdapter.cs @@ -0,0 +1,172 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// ComparisonAdapter class centralizes all comparisons of + /// values in NUnit, adapting to the use of any provided + /// IComparer, IComparer<T> or Comparison<T> + /// + public abstract class ComparisonAdapter + { + /// + /// Gets the default ComparisonAdapter, which wraps an + /// NUnitComparer object. + /// + public static ComparisonAdapter Default + { + get { return new DefaultComparisonAdapter(); } + } + + /// + /// Returns a ComparisonAdapter that wraps an IComparer + /// + public static ComparisonAdapter For(IComparer comparer) + { + return new ComparerAdapter(comparer); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a ComparisonAdapter that wraps an IComparer<T> + /// + public static ComparisonAdapter For(IComparer comparer) + { + return new ComparerAdapter(comparer); + } + + /// + /// Returns a ComparisonAdapter that wraps a Comparison<T> + /// + public static ComparisonAdapter For(Comparison comparer) + { + return new ComparisonAdapterForComparison(comparer); + } +#endif + + /// + /// Compares two objects + /// + public abstract int Compare(object expected, object actual); + + class DefaultComparisonAdapter : ComparerAdapter + { + /// + /// Construct a default ComparisonAdapter + /// + public DefaultComparisonAdapter() : base( NUnitComparer.Default ) { } + } + + class ComparerAdapter : ComparisonAdapter + { + private readonly IComparer comparer; + + /// + /// Construct a ComparisonAdapter for an IComparer + /// + public ComparerAdapter(IComparer comparer) + { + this.comparer = comparer; + } + + /// + /// Compares two objects + /// + /// + /// + /// + public override int Compare(object expected, object actual) + { + return comparer.Compare(expected, actual); + } + } + +#if CLR_2_0 || CLR_4_0 + /// + /// ComparisonAdapter<T> extends ComparisonAdapter and + /// allows use of an IComparer<T> or Comparison<T> + /// to actually perform the comparison. + /// + class ComparerAdapter : ComparisonAdapter + { + private readonly IComparer comparer; + + /// + /// Construct a ComparisonAdapter for an IComparer<T> + /// + public ComparerAdapter(IComparer comparer) + { + this.comparer = comparer; + } + + /// + /// Compare a Type T to an object + /// + public override int Compare(object expected, object actual) + { + if (!typeof(T).IsAssignableFrom(expected.GetType())) + throw new ArgumentException("Cannot compare " + expected.ToString()); + + if (!typeof(T).IsAssignableFrom(actual.GetType())) + throw new ArgumentException("Cannot compare to " + actual.ToString()); + + return comparer.Compare((T)expected, (T)actual); + } + } + + class ComparisonAdapterForComparison : ComparisonAdapter + { + private readonly Comparison comparison; + + /// + /// Construct a ComparisonAdapter for a Comparison<T> + /// + public ComparisonAdapterForComparison(Comparison comparer) + { + this.comparison = comparer; + } + + /// + /// Compare a Type T to an object + /// + public override int Compare(object expected, object actual) + { + if (!typeof(T).IsAssignableFrom(expected.GetType())) + throw new ArgumentException("Cannot compare " + expected.ToString()); + + if (!typeof(T).IsAssignableFrom(actual.GetType())) + throw new ArgumentException("Cannot compare to " + actual.ToString()); + + return comparison.Invoke((T)expected, (T)actual); + } + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ComparisonConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ComparisonConstraint.cs new file mode 100644 index 00000000000..d8af7c21103 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ComparisonConstraint.cs @@ -0,0 +1,83 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// Abstract base class for constraints that compare values to + /// determine if one is greater than, equal to or less than + /// the other. This class supplies the Using modifiers. + /// + public abstract class ComparisonConstraint : Constraint + { + /// + /// ComparisonAdapter to be used in making the comparison + /// + protected ComparisonAdapter comparer = ComparisonAdapter.Default; + + /// + /// Initializes a new instance of the class. + /// + public ComparisonConstraint(object arg) : base(arg) { } + + /// + /// Initializes a new instance of the class. + /// + public ComparisonConstraint(object arg1, object arg2) : base(arg1, arg2) { } + + /// + /// Modifies the constraint to use an IComparer and returns self + /// + public ComparisonConstraint Using(IComparer comparer) + { + this.comparer = ComparisonAdapter.For(comparer); + return this; + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Modifies the constraint to use an IComparer<T> and returns self + /// + public ComparisonConstraint Using(IComparer comparer) + { + this.comparer = ComparisonAdapter.For(comparer); + return this; + } + + /// + /// Modifies the constraint to use a Comparison<T> and returns self + /// + public ComparisonConstraint Using(Comparison comparer) + { + this.comparer = ComparisonAdapter.For(comparer); + return this; + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Constraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Constraint.cs new file mode 100644 index 00000000000..4074c1245e3 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Constraint.cs @@ -0,0 +1,416 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Constraints +{ + /// + /// Delegate used to delay evaluation of the actual value + /// to be used in evaluating a constraint + /// +#if CLR_2_0 || CLR_4_0 + public delegate T ActualValueDelegate(); +#else + public delegate object ActualValueDelegate(); +#endif + + /// + /// The Constraint class is the base of all built-in constraints + /// within NUnit. It provides the operator overloads used to combine + /// constraints. + /// + public abstract class Constraint : IResolveConstraint + { + #region UnsetObject Class + /// + /// Class used to detect any derived constraints + /// that fail to set the actual value in their + /// Matches override. + /// + private class UnsetObject + { + public override string ToString() + { + return "UNSET"; + } + } + #endregion + + #region Static and Instance Fields + /// + /// Static UnsetObject used to detect derived constraints + /// failing to set the actual value. + /// + protected static object UNSET = new UnsetObject(); + + /// + /// The actual value being tested against a constraint + /// + protected object actual = UNSET; + + /// + /// The display name of this Constraint for use by ToString() + /// + private string displayName; + + /// + /// Argument fields used by ToString(); + /// + private readonly int argcnt; + private readonly object arg1; + private readonly object arg2; + + /// + /// The builder holding this constraint + /// + private ConstraintBuilder builder; + #endregion + + #region Constructors + /// + /// Construct a constraint with no arguments + /// + protected Constraint() + { + argcnt = 0; + } + + /// + /// Construct a constraint with one argument + /// + protected Constraint(object arg) + { + argcnt = 1; + this.arg1 = arg; + } + + /// + /// Construct a constraint with two arguments + /// + protected Constraint(object arg1, object arg2) + { + argcnt = 2; + this.arg1 = arg1; + this.arg2 = arg2; + } + #endregion + + #region Set Containing ConstraintBuilder + /// + /// Sets the ConstraintBuilder holding this constraint + /// + internal void SetBuilder(ConstraintBuilder builder) + { + this.builder = builder; + } + #endregion + + #region Properties + /// + /// The display name of this Constraint for use by ToString(). + /// The default value is the name of the constraint with + /// trailing "Constraint" removed. Derived classes may set + /// this to another name in their constructors. + /// + protected string DisplayName + { + get + { + if (displayName == null) + { + displayName = this.GetType().Name.ToLower(); + if (displayName.EndsWith("`1") || displayName.EndsWith("`2")) + displayName = displayName.Substring(0, displayName.Length - 2); + if (displayName.EndsWith("constraint")) + displayName = displayName.Substring(0, displayName.Length - 10); + } + + return displayName; + } + + set { displayName = value; } + } + #endregion + + #region Abstract and Virtual Methods + /// + /// Write the failure message to the MessageWriter provided + /// as an argument. The default implementation simply passes + /// the constraint and the actual value to the writer, which + /// then displays the constraint description and the value. + /// + /// Constraints that need to provide additional details, + /// such as where the error occured can override this. + /// + /// The MessageWriter on which to display the message + public virtual void WriteMessageTo(MessageWriter writer) + { + writer.DisplayDifferences(this); + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public abstract bool Matches(object actual); + +#if CLR_2_0 || CLR_4_0 + /// + /// Test whether the constraint is satisfied by an + /// ActualValueDelegate that returns the value to be tested. + /// The default implementation simply evaluates the delegate + /// but derived classes may override it to provide for delayed + /// processing. + /// + /// An + /// True for success, false for failure + public virtual bool Matches(ActualValueDelegate del) + { +#if NET_4_5 + if (AsyncInvocationRegion.IsAsyncOperation(del)) + using (var region = AsyncInvocationRegion.Create(del)) + return Matches(region.WaitForPendingOperationsToComplete(del())); +#endif + return Matches(del()); + } +#else + /// + /// Test whether the constraint is satisfied by an + /// ActualValueDelegate that returns the value to be tested. + /// The default implementation simply evaluates the delegate + /// but derived classes may override it to provide for delayed + /// processing. + /// + /// An + /// True for success, false for failure + public virtual bool Matches(ActualValueDelegate del) + { + return Matches(del()); + } +#endif + + /// + /// Test whether the constraint is satisfied by a given reference. + /// The default implementation simply dereferences the value but + /// derived classes may override it to provide for delayed processing. + /// + /// A reference to the value to be tested + /// True for success, false for failure +#if CLR_2_0 || CLR_4_0 + public virtual bool Matches(ref T actual) +#else + public virtual bool Matches(ref bool actual) +#endif + { + return Matches(actual); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public abstract void WriteDescriptionTo(MessageWriter writer); + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public virtual void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(actual); + } + #endregion + + #region ToString Override + /// + /// Default override of ToString returns the constraint DisplayName + /// followed by any arguments within angle brackets. + /// + /// + public override string ToString() + { + string rep = GetStringRepresentation(); + + return this.builder == null ? rep : string.Format("", rep); + } + + /// + /// Returns the string representation of this constraint + /// + protected virtual string GetStringRepresentation() + { + switch (argcnt) + { + default: + case 0: + return string.Format("<{0}>", DisplayName); + case 1: + return string.Format("<{0} {1}>", DisplayName, _displayable(arg1)); + case 2: + return string.Format("<{0} {1} {2}>", DisplayName, _displayable(arg1), _displayable(arg2)); + } + } + + private static string _displayable(object o) + { + if (o == null) return "null"; + + string fmt = o is string ? "\"{0}\"" : "{0}"; + return string.Format(System.Globalization.CultureInfo.InvariantCulture, fmt, o); + } + #endregion + + #region Operator Overloads + /// + /// This operator creates a constraint that is satisfied only if both + /// argument constraints are satisfied. + /// + public static Constraint operator &(Constraint left, Constraint right) + { + IResolveConstraint l = (IResolveConstraint)left; + IResolveConstraint r = (IResolveConstraint)right; + return new AndConstraint(l.Resolve(), r.Resolve()); + } + + /// + /// This operator creates a constraint that is satisfied if either + /// of the argument constraints is satisfied. + /// + public static Constraint operator |(Constraint left, Constraint right) + { + IResolveConstraint l = (IResolveConstraint)left; + IResolveConstraint r = (IResolveConstraint)right; + return new OrConstraint(l.Resolve(), r.Resolve()); + } + + /// + /// This operator creates a constraint that is satisfied if the + /// argument constraint is not satisfied. + /// + public static Constraint operator !(Constraint constraint) + { + IResolveConstraint r = constraint as IResolveConstraint; + return new NotConstraint(r == null ? new NullConstraint() : r.Resolve()); + } + #endregion + + #region Binary Operators + /// + /// Returns a ConstraintExpression by appending And + /// to the current constraint. + /// + public ConstraintExpression And + { + get + { + ConstraintBuilder builder = this.builder; + if (builder == null) + { + builder = new ConstraintBuilder(); + builder.Append(this); + } + + builder.Append(new AndOperator()); + + return new ConstraintExpression(builder); + } + } + + /// + /// Returns a ConstraintExpression by appending And + /// to the current constraint. + /// + public ConstraintExpression With + { + get { return this.And; } + } + + /// + /// Returns a ConstraintExpression by appending Or + /// to the current constraint. + /// + public ConstraintExpression Or + { + get + { + ConstraintBuilder builder = this.builder; + if (builder == null) + { + builder = new ConstraintBuilder(); + builder.Append(this); + } + + builder.Append(new OrOperator()); + + return new ConstraintExpression(builder); + } + } + #endregion + + #region After Modifier + +#if !SILVERLIGHT + /// + /// Returns a DelayedConstraint with the specified delay time. + /// + /// The delay in milliseconds. + /// + public DelayedConstraint After(int delayInMilliseconds) + { + return new DelayedConstraint( + builder == null ? this : builder.Resolve(), + delayInMilliseconds); + } + + /// + /// Returns a DelayedConstraint with the specified delay time + /// and polling interval. + /// + /// The delay in milliseconds. + /// The interval at which to test the constraint. + /// + public DelayedConstraint After(int delayInMilliseconds, int pollingInterval) + { + return new DelayedConstraint( + builder == null ? this : builder.Resolve(), + delayInMilliseconds, + pollingInterval); + } +#endif + + #endregion + + #region IResolveConstraint Members + Constraint IResolveConstraint.Resolve() + { + return builder == null ? this : builder.Resolve(); + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintBuilder.cs new file mode 100644 index 00000000000..7bc79d65689 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintBuilder.cs @@ -0,0 +1,286 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// ConstraintBuilder maintains the stacks that are used in + /// processing a ConstraintExpression. An OperatorStack + /// is used to hold operators that are waiting for their + /// operands to be reognized. a ConstraintStack holds + /// input constraints as well as the results of each + /// operator applied. + /// + public class ConstraintBuilder + { + #region Nested Operator Stack Class + /// + /// OperatorStack is a type-safe stack for holding ConstraintOperators + /// + public class OperatorStack + { +#if CLR_2_0 || CLR_4_0 + private Stack stack = new Stack(); +#else + private Stack stack = new Stack(); +#endif + /// + /// Initializes a new instance of the class. + /// + /// The builder. + public OperatorStack(ConstraintBuilder builder) + { + } + + /// + /// Gets a value indicating whether this is empty. + /// + /// true if empty; otherwise, false. + public bool Empty + { + get { return stack.Count == 0; } + } + + /// + /// Gets the topmost operator without modifying the stack. + /// + /// The top. + public ConstraintOperator Top + { + get { return (ConstraintOperator)stack.Peek(); } + } + + /// + /// Pushes the specified operator onto the stack. + /// + /// The op. + public void Push(ConstraintOperator op) + { + stack.Push(op); + } + + /// + /// Pops the topmost operator from the stack. + /// + /// + public ConstraintOperator Pop() + { + return (ConstraintOperator)stack.Pop(); + } + } + #endregion + + #region Nested Constraint Stack Class + /// + /// ConstraintStack is a type-safe stack for holding Constraints + /// + public class ConstraintStack + { +#if CLR_2_0 || CLR_4_0 + private Stack stack = new Stack(); +#else + private Stack stack = new Stack(); +#endif + private ConstraintBuilder builder; + + /// + /// Initializes a new instance of the class. + /// + /// The builder. + public ConstraintStack(ConstraintBuilder builder) + { + this.builder = builder; + } + + /// + /// Gets a value indicating whether this is empty. + /// + /// true if empty; otherwise, false. + public bool Empty + { + get { return stack.Count == 0; } + } + + /// + /// Gets the topmost constraint without modifying the stack. + /// + /// The topmost constraint + public Constraint Top + { + get { return (Constraint)stack.Peek(); } + } + + /// + /// Pushes the specified constraint. As a side effect, + /// the constraint's builder field is set to the + /// ConstraintBuilder owning this stack. + /// + /// The constraint. + public void Push(Constraint constraint) + { + stack.Push(constraint); + constraint.SetBuilder( this.builder ); + } + + /// + /// Pops this topmost constrait from the stack. + /// As a side effect, the constraint's builder + /// field is set to null. + /// + /// + public Constraint Pop() + { + Constraint constraint = (Constraint)stack.Pop(); + constraint.SetBuilder( null ); + return constraint; + } + } + #endregion + + #region Instance Fields + private readonly OperatorStack ops; + + private readonly ConstraintStack constraints; + + private object lastPushed; + #endregion + + #region Constructor + /// + /// Initializes a new instance of the class. + /// + public ConstraintBuilder() + { + this.ops = new OperatorStack(this); + this.constraints = new ConstraintStack(this); + } + #endregion + + #region Properties + /// + /// Gets a value indicating whether this instance is resolvable. + /// + /// + /// true if this instance is resolvable; otherwise, false. + /// + public bool IsResolvable + { + get { return lastPushed is Constraint || lastPushed is SelfResolvingOperator; } + } + #endregion + + #region Public Methods + /// + /// Appends the specified operator to the expression by first + /// reducing the operator stack and then pushing the new + /// operator on the stack. + /// + /// The operator to push. + public void Append(ConstraintOperator op) + { + op.LeftContext = lastPushed; + if (lastPushed is ConstraintOperator) + SetTopOperatorRightContext(op); + + // Reduce any lower precedence operators + ReduceOperatorStack(op.LeftPrecedence); + + ops.Push(op); + lastPushed = op; + } + + /// + /// Appends the specified constraint to the expresson by pushing + /// it on the constraint stack. + /// + /// The constraint to push. + public void Append(Constraint constraint) + { + if (lastPushed is ConstraintOperator) + SetTopOperatorRightContext(constraint); + + constraints.Push(constraint); + lastPushed = constraint; + constraint.SetBuilder( this ); + } + + /// + /// Sets the top operator right context. + /// + /// The right context. + private void SetTopOperatorRightContext(object rightContext) + { + // Some operators change their precedence based on + // the right context - save current precedence. + int oldPrecedence = ops.Top.LeftPrecedence; + + ops.Top.RightContext = rightContext; + + // If the precedence increased, we may be able to + // reduce the region of the stack below the operator + if (ops.Top.LeftPrecedence > oldPrecedence) + { + ConstraintOperator changedOp = ops.Pop(); + ReduceOperatorStack(changedOp.LeftPrecedence); + ops.Push(changedOp); + } + } + + /// + /// Reduces the operator stack until the topmost item + /// precedence is greater than or equal to the target precedence. + /// + /// The target precedence. + private void ReduceOperatorStack(int targetPrecedence) + { + while (!ops.Empty && ops.Top.RightPrecedence < targetPrecedence) + ops.Pop().Reduce(constraints); + } + + /// + /// Resolves this instance, returning a Constraint. If the builder + /// is not currently in a resolvable state, an exception is thrown. + /// + /// The resolved constraint + public Constraint Resolve() + { + if (!IsResolvable) + throw new InvalidOperationException("A partial expression may not be resolved"); + + while (!ops.Empty) + { + ConstraintOperator op = ops.Pop(); + op.Reduce(constraints); + } + + return constraints.Pop(); + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintExpression.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintExpression.cs new file mode 100644 index 00000000000..46fc7d85796 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintExpression.cs @@ -0,0 +1,803 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// ConstraintExpression represents a compound constraint in the + /// process of being constructed from a series of syntactic elements. + /// + /// Individual elements are appended to the expression as they are + /// reognized. Once an actual Constraint is appended, the expression + /// returns a resolvable Constraint. + /// + public class ConstraintExpression : ConstraintExpressionBase + { + /// + /// Initializes a new instance of the class. + /// + public ConstraintExpression() { } + + /// + /// Initializes a new instance of the + /// class passing in a ConstraintBuilder, which may be pre-populated. + /// + /// The builder. + public ConstraintExpression(ConstraintBuilder builder) + : base( builder ) { } + + #region Not + + /// + /// Returns a ConstraintExpression that negates any + /// following constraint. + /// + public ConstraintExpression Not + { + get { return this.Append(new NotOperator()); } + } + + /// + /// Returns a ConstraintExpression that negates any + /// following constraint. + /// + public ConstraintExpression No + { + get { return this.Append(new NotOperator()); } + } + + #endregion + + #region All + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them succeed. + /// + public ConstraintExpression All + { + get { return this.Append(new AllOperator()); } + } + + #endregion + + #region Some + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if at least one of them succeeds. + /// + public ConstraintExpression Some + { + get { return this.Append(new SomeOperator()); } + } + + #endregion + + #region None + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them fail. + /// + public ConstraintExpression None + { + get { return this.Append(new NoneOperator()); } + } + + #endregion + + #region Exactly(n) + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding only if a specified number of them succeed. + /// + public ConstraintExpression Exactly(int expectedCount) + { + return this.Append(new ExactCountOperator(expectedCount)); + } + + #endregion + + #region Property + + /// + /// Returns a new PropertyConstraintExpression, which will either + /// test for the existence of the named property on the object + /// being tested or apply any following constraint to that property. + /// + public ResolvableConstraintExpression Property(string name) + { + return this.Append(new PropOperator(name)); + } + + #endregion + + #region Length + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Length property of the object being tested. + /// + public ResolvableConstraintExpression Length + { + get { return Property("Length"); } + } + + #endregion + + #region Count + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Count property of the object being tested. + /// + public ResolvableConstraintExpression Count + { + get { return Property("Count"); } + } + + #endregion + + #region Message + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Message property of the object being tested. + /// + public ResolvableConstraintExpression Message + { + get { return Property("Message"); } + } + + #endregion + + #region InnerException + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the InnerException property of the object being tested. + /// + public ResolvableConstraintExpression InnerException + { + get { return Property("InnerException"); } + } + + #endregion + + #region Attribute + + /// + /// Returns a new AttributeConstraint checking for the + /// presence of a particular attribute on an object. + /// + public ResolvableConstraintExpression Attribute(Type expectedType) + { + return this.Append(new AttributeOperator(expectedType)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a new AttributeConstraint checking for the + /// presence of a particular attribute on an object. + /// + public ResolvableConstraintExpression Attribute() + { + return Attribute(typeof(T)); + } +#endif + + #endregion + + #region With + + /// + /// With is currently a NOP - reserved for future use. + /// + public ConstraintExpression With + { + get { return this.Append(new WithOperator()); } + } + + #endregion + + #region Matches + + /// + /// Returns the constraint provided as an argument - used to allow custom + /// custom constraints to easily participate in the syntax. + /// + public Constraint Matches(Constraint constraint) + { + return this.Append(constraint); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns the constraint provided as an argument - used to allow custom + /// custom constraints to easily participate in the syntax. + /// + public Constraint Matches(Predicate predicate) + { + return this.Append(new PredicateConstraint(predicate)); + } +#endif + + #endregion + + #region Null + + /// + /// Returns a constraint that tests for null + /// + public NullConstraint Null + { + get { return (NullConstraint)this.Append(new NullConstraint()); } + } + + #endregion + + #region True + + /// + /// Returns a constraint that tests for True + /// + public TrueConstraint True + { + get { return (TrueConstraint)this.Append(new TrueConstraint()); } + } + + #endregion + + #region False + + /// + /// Returns a constraint that tests for False + /// + public FalseConstraint False + { + get { return (FalseConstraint)this.Append(new FalseConstraint()); } + } + + #endregion + + #region Positive + + /// + /// Returns a constraint that tests for a positive value + /// + public GreaterThanConstraint Positive + { + get { return (GreaterThanConstraint)this.Append(new GreaterThanConstraint(0)); } + } + + #endregion + + #region Negative + + /// + /// Returns a constraint that tests for a negative value + /// + public LessThanConstraint Negative + { + get { return (LessThanConstraint)this.Append(new LessThanConstraint(0)); } + } + + #endregion + + #region NaN + + /// + /// Returns a constraint that tests for NaN + /// + public NaNConstraint NaN + { + get { return (NaNConstraint)this.Append(new NaNConstraint()); } + } + + #endregion + + #region Empty + + /// + /// Returns a constraint that tests for empty + /// + public EmptyConstraint Empty + { + get { return (EmptyConstraint)this.Append(new EmptyConstraint()); } + } + + #endregion + + #region Unique + + /// + /// Returns a constraint that tests whether a collection + /// contains all unique items. + /// + public UniqueItemsConstraint Unique + { + get { return (UniqueItemsConstraint)this.Append(new UniqueItemsConstraint()); } + } + + #endregion + + #region BinarySerializable + +#if !NETCF && !SILVERLIGHT + /// + /// Returns a constraint that tests whether an object graph is serializable in binary format. + /// + public BinarySerializableConstraint BinarySerializable + { + get { return (BinarySerializableConstraint)this.Append(new BinarySerializableConstraint()); } + } +#endif + + #endregion + + #region XmlSerializable + +#if !SILVERLIGHT + /// + /// Returns a constraint that tests whether an object graph is serializable in xml format. + /// + public XmlSerializableConstraint XmlSerializable + { + get { return (XmlSerializableConstraint)this.Append(new XmlSerializableConstraint()); } + } +#endif + + #endregion + + #region EqualTo + + /// + /// Returns a constraint that tests two items for equality + /// + public EqualConstraint EqualTo(object expected) + { + return (EqualConstraint)this.Append(new EqualConstraint(expected)); + } + + #endregion + + #region SameAs + + /// + /// Returns a constraint that tests that two references are the same object + /// + public SameAsConstraint SameAs(object expected) + { + return (SameAsConstraint)this.Append(new SameAsConstraint(expected)); + } + + #endregion + + #region GreaterThan + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than the suppled argument + /// + public GreaterThanConstraint GreaterThan(object expected) + { + return (GreaterThanConstraint)this.Append(new GreaterThanConstraint(expected)); + } + + #endregion + + #region GreaterThanOrEqualTo + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than or equal to the suppled argument + /// + public GreaterThanOrEqualConstraint GreaterThanOrEqualTo(object expected) + { + return (GreaterThanOrEqualConstraint)this.Append(new GreaterThanOrEqualConstraint(expected)); + } + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than or equal to the suppled argument + /// + public GreaterThanOrEqualConstraint AtLeast(object expected) + { + return (GreaterThanOrEqualConstraint)this.Append(new GreaterThanOrEqualConstraint(expected)); + } + + #endregion + + #region LessThan + + /// + /// Returns a constraint that tests whether the + /// actual value is less than the suppled argument + /// + public LessThanConstraint LessThan(object expected) + { + return (LessThanConstraint)this.Append(new LessThanConstraint(expected)); + } + + #endregion + + #region LessThanOrEqualTo + + /// + /// Returns a constraint that tests whether the + /// actual value is less than or equal to the suppled argument + /// + public LessThanOrEqualConstraint LessThanOrEqualTo(object expected) + { + return (LessThanOrEqualConstraint)this.Append(new LessThanOrEqualConstraint(expected)); + } + + /// + /// Returns a constraint that tests whether the + /// actual value is less than or equal to the suppled argument + /// + public LessThanOrEqualConstraint AtMost(object expected) + { + return (LessThanOrEqualConstraint)this.Append(new LessThanOrEqualConstraint(expected)); + } + + #endregion + + #region TypeOf + + /// + /// Returns a constraint that tests whether the actual + /// value is of the exact type supplied as an argument. + /// + public ExactTypeConstraint TypeOf(Type expectedType) + { + return (ExactTypeConstraint)this.Append(new ExactTypeConstraint(expectedType)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual + /// value is of the exact type supplied as an argument. + /// + public ExactTypeConstraint TypeOf() + { + return (ExactTypeConstraint)this.Append(new ExactTypeConstraint(typeof(T))); + } +#endif + + #endregion + + #region InstanceOf + + /// + /// Returns a constraint that tests whether the actual value + /// is of the type supplied as an argument or a derived type. + /// + public InstanceOfTypeConstraint InstanceOf(Type expectedType) + { + return (InstanceOfTypeConstraint)this.Append(new InstanceOfTypeConstraint(expectedType)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is of the type supplied as an argument or a derived type. + /// + public InstanceOfTypeConstraint InstanceOf() + { + return (InstanceOfTypeConstraint)this.Append(new InstanceOfTypeConstraint(typeof(T))); + } +#endif + + #endregion + + #region AssignableFrom + + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableFromConstraint AssignableFrom(Type expectedType) + { + return (AssignableFromConstraint)this.Append(new AssignableFromConstraint(expectedType)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableFromConstraint AssignableFrom() + { + return (AssignableFromConstraint)this.Append(new AssignableFromConstraint(typeof(T))); + } +#endif + + #endregion + + #region AssignableTo + + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableToConstraint AssignableTo(Type expectedType) + { + return (AssignableToConstraint)this.Append(new AssignableToConstraint(expectedType)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableToConstraint AssignableTo() + { + return (AssignableToConstraint)this.Append(new AssignableToConstraint(typeof(T))); + } +#endif + + #endregion + + #region EquivalentTo + + /// + /// Returns a constraint that tests whether the actual value + /// is a collection containing the same elements as the + /// collection supplied as an argument. + /// + public CollectionEquivalentConstraint EquivalentTo(IEnumerable expected) + { + return (CollectionEquivalentConstraint)this.Append(new CollectionEquivalentConstraint(expected)); + } + + #endregion + + #region SubsetOf + + /// + /// Returns a constraint that tests whether the actual value + /// is a subset of the collection supplied as an argument. + /// + public CollectionSubsetConstraint SubsetOf(IEnumerable expected) + { + return (CollectionSubsetConstraint)this.Append(new CollectionSubsetConstraint(expected)); + } + + #endregion + + #region Ordered + + /// + /// Returns a constraint that tests whether a collection is ordered + /// + public CollectionOrderedConstraint Ordered + { + get { return (CollectionOrderedConstraint)this.Append(new CollectionOrderedConstraint()); } + } + + #endregion + + #region Member + + /// + /// Returns a new CollectionContainsConstraint checking for the + /// presence of a particular object in the collection. + /// + public CollectionContainsConstraint Member(object expected) + { + return (CollectionContainsConstraint)this.Append(new CollectionContainsConstraint(expected)); + } + + /// + /// Returns a new CollectionContainsConstraint checking for the + /// presence of a particular object in the collection. + /// + public CollectionContainsConstraint Contains(object expected) + { + return (CollectionContainsConstraint)this.Append(new CollectionContainsConstraint(expected)); + } + + #endregion + + #region Contains + + /// + /// Returns a new ContainsConstraint. This constraint + /// will, in turn, make use of the appropriate second-level + /// constraint, depending on the type of the actual argument. + /// This overload is only used if the item sought is a string, + /// since any other type implies that we are looking for a + /// collection member. + /// + public ContainsConstraint Contains(string expected) + { + return (ContainsConstraint)this.Append(new ContainsConstraint(expected)); + } + + #endregion + + #region StringContaining + + /// + /// Returns a constraint that succeeds if the actual + /// value contains the substring supplied as an argument. + /// + public SubstringConstraint StringContaining(string expected) + { + return (SubstringConstraint)this.Append(new SubstringConstraint(expected)); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value contains the substring supplied as an argument. + /// + public SubstringConstraint ContainsSubstring(string expected) + { + return (SubstringConstraint)this.Append(new SubstringConstraint(expected)); + } + + #endregion + + #region StartsWith + + /// + /// Returns a constraint that succeeds if the actual + /// value starts with the substring supplied as an argument. + /// + public StartsWithConstraint StartsWith(string expected) + { + return (StartsWithConstraint)this.Append(new StartsWithConstraint(expected)); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value starts with the substring supplied as an argument. + /// + public StartsWithConstraint StringStarting(string expected) + { + return (StartsWithConstraint)this.Append(new StartsWithConstraint(expected)); + } + + #endregion + + #region EndsWith + + /// + /// Returns a constraint that succeeds if the actual + /// value ends with the substring supplied as an argument. + /// + public EndsWithConstraint EndsWith(string expected) + { + return (EndsWithConstraint)this.Append(new EndsWithConstraint(expected)); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value ends with the substring supplied as an argument. + /// + public EndsWithConstraint StringEnding(string expected) + { + return (EndsWithConstraint)this.Append(new EndsWithConstraint(expected)); + } + + #endregion + + #region Matches + +#if !NETCF + /// + /// Returns a constraint that succeeds if the actual + /// value matches the regular expression supplied as an argument. + /// + public RegexConstraint Matches(string pattern) + { + return (RegexConstraint)this.Append(new RegexConstraint(pattern)); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value matches the regular expression supplied as an argument. + /// + public RegexConstraint StringMatching(string pattern) + { + return (RegexConstraint)this.Append(new RegexConstraint(pattern)); + } +#endif + + #endregion + + #region SamePath + + /// + /// Returns a constraint that tests whether the path provided + /// is the same as an expected path after canonicalization. + /// + public SamePathConstraint SamePath(string expected) + { + return (SamePathConstraint)this.Append(new SamePathConstraint(expected)); + } + + #endregion + + #region SubPath + + /// + /// Returns a constraint that tests whether the path provided + /// is the same path or under an expected path after canonicalization. + /// + public SubPathConstraint SubPath(string expected) + { + return (SubPathConstraint)this.Append(new SubPathConstraint(expected)); + } + + #endregion + + #region SamePathOrUnder + + /// + /// Returns a constraint that tests whether the path provided + /// is the same path or under an expected path after canonicalization. + /// + public SamePathOrUnderConstraint SamePathOrUnder(string expected) + { + return (SamePathOrUnderConstraint)this.Append(new SamePathOrUnderConstraint(expected)); + } + + #endregion + + #region InRange + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value falls + /// within a specified range. + /// + public RangeConstraint InRange(T from, T to) where T : IComparable + { + return (RangeConstraint)this.Append(new RangeConstraint(from, to)); + } +#else + /// + /// Returns a constraint that tests whether the actual value falls + /// within a specified range. + /// + public RangeConstraint InRange(IComparable from, IComparable to) + { + return (RangeConstraint)this.Append(new RangeConstraint(from, to)); + } +#endif + + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintExpressionBase.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintExpressionBase.cs new file mode 100644 index 00000000000..7548dcf22d4 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintExpressionBase.cs @@ -0,0 +1,115 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// ConstraintExpressionBase is the abstract base class for the + /// ConstraintExpression class, which represents a + /// compound constraint in the process of being constructed + /// from a series of syntactic elements. + /// + /// NOTE: ConstraintExpressionBase is separate because the + /// ConstraintExpression class was generated in earlier + /// versions of NUnit. The two classes may be combined + /// in a future version. + /// + public abstract class ConstraintExpressionBase + { + #region Instance Fields + /// + /// The ConstraintBuilder holding the elements recognized so far + /// + protected ConstraintBuilder builder; + #endregion + + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public ConstraintExpressionBase() + { + this.builder = new ConstraintBuilder(); + } + + /// + /// Initializes a new instance of the + /// class passing in a ConstraintBuilder, which may be pre-populated. + /// + /// The builder. + public ConstraintExpressionBase(ConstraintBuilder builder) + { + this.builder = builder; + } + #endregion + + #region ToString() + /// + /// Returns a string representation of the expression as it + /// currently stands. This should only be used for testing, + /// since it has the side-effect of resolving the expression. + /// + /// + public override string ToString() + { + return builder.Resolve().ToString(); + } + #endregion + + #region Append Methods + /// + /// Appends an operator to the expression and returns the + /// resulting expression itself. + /// + public ConstraintExpression Append(ConstraintOperator op) + { + builder.Append(op); + return (ConstraintExpression)this; + } + + /// + /// Appends a self-resolving operator to the expression and + /// returns a new ResolvableConstraintExpression. + /// + public ResolvableConstraintExpression Append(SelfResolvingOperator op) + { + builder.Append(op); + return new ResolvableConstraintExpression(builder); + } + + /// + /// Appends a constraint to the expression and returns that + /// constraint, which is associated with the current state + /// of the expression being built. + /// + public Constraint Append(Constraint constraint) + { + builder.Append(constraint); + return constraint; + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintFactory.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintFactory.cs new file mode 100644 index 00000000000..f0737fb6946 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ConstraintFactory.cs @@ -0,0 +1,804 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// Helper class with properties and methods that supply + /// a number of constraints used in Asserts. + /// + public class ConstraintFactory + { + #region Not + + /// + /// Returns a ConstraintExpression that negates any + /// following constraint. + /// + public ConstraintExpression Not + { + get { return Is.Not; } + } + + /// + /// Returns a ConstraintExpression that negates any + /// following constraint. + /// + public ConstraintExpression No + { + get { return Has.No; } + } + + #endregion + + #region All + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them succeed. + /// + public ConstraintExpression All + { + get { return Is.All; } + } + + #endregion + + #region Some + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if at least one of them succeeds. + /// + public ConstraintExpression Some + { + get { return Has.Some; } + } + + #endregion + + #region None + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them fail. + /// + public ConstraintExpression None + { + get { return Has.None; } + } + + #endregion + + #region Exactly(n) + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding only if a specified number of them succeed. + /// + public static ConstraintExpression Exactly(int expectedCount) + { + return Has.Exactly(expectedCount); + } + + #endregion + + #region Property + + /// + /// Returns a new PropertyConstraintExpression, which will either + /// test for the existence of the named property on the object + /// being tested or apply any following constraint to that property. + /// + public ResolvableConstraintExpression Property(string name) + { + return Has.Property(name); + } + + #endregion + + #region Length + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Length property of the object being tested. + /// + public ResolvableConstraintExpression Length + { + get { return Has.Length; } + } + + #endregion + + #region Count + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Count property of the object being tested. + /// + public ResolvableConstraintExpression Count + { + get { return Has.Count; } + } + + #endregion + + #region Message + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Message property of the object being tested. + /// + public ResolvableConstraintExpression Message + { + get { return Has.Message; } + } + + #endregion + + #region InnerException + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the InnerException property of the object being tested. + /// + public ResolvableConstraintExpression InnerException + { + get { return Has.InnerException; } + } + + #endregion + + #region Attribute + + /// + /// Returns a new AttributeConstraint checking for the + /// presence of a particular attribute on an object. + /// + public ResolvableConstraintExpression Attribute(Type expectedType) + { + return Has.Attribute(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a new AttributeConstraint checking for the + /// presence of a particular attribute on an object. + /// + public ResolvableConstraintExpression Attribute() + { + return Attribute(typeof(T)); + } +#endif + + #endregion + + #region Null + + /// + /// Returns a constraint that tests for null + /// + public NullConstraint Null + { + get { return new NullConstraint(); } + } + + #endregion + + #region True + + /// + /// Returns a constraint that tests for True + /// + public TrueConstraint True + { + get { return new TrueConstraint(); } + } + + #endregion + + #region False + + /// + /// Returns a constraint that tests for False + /// + public FalseConstraint False + { + get { return new FalseConstraint(); } + } + + #endregion + + #region Positive + + /// + /// Returns a constraint that tests for a positive value + /// + public GreaterThanConstraint Positive + { + get { return new GreaterThanConstraint(0); } + } + + #endregion + + #region Negative + + /// + /// Returns a constraint that tests for a negative value + /// + public LessThanConstraint Negative + { + get { return new LessThanConstraint(0); } + } + + #endregion + + #region NaN + + /// + /// Returns a constraint that tests for NaN + /// + public NaNConstraint NaN + { + get { return new NaNConstraint(); } + } + + #endregion + + #region Empty + + /// + /// Returns a constraint that tests for empty + /// + public EmptyConstraint Empty + { + get { return new EmptyConstraint(); } + } + + #endregion + + #region Unique + + /// + /// Returns a constraint that tests whether a collection + /// contains all unique items. + /// + public UniqueItemsConstraint Unique + { + get { return new UniqueItemsConstraint(); } + } + + #endregion + + #region BinarySerializable + +#if !NETCF && !SILVERLIGHT + /// + /// Returns a constraint that tests whether an object graph is serializable in binary format. + /// + public BinarySerializableConstraint BinarySerializable + { + get { return new BinarySerializableConstraint(); } + } +#endif + + #endregion + + #region XmlSerializable + +#if !SILVERLIGHT + /// + /// Returns a constraint that tests whether an object graph is serializable in xml format. + /// + public XmlSerializableConstraint XmlSerializable + { + get { return new XmlSerializableConstraint(); } + } +#endif + + #endregion + + #region EqualTo + + /// + /// Returns a constraint that tests two items for equality + /// + public EqualConstraint EqualTo(object expected) + { + return new EqualConstraint(expected); + } + + #endregion + + #region SameAs + + /// + /// Returns a constraint that tests that two references are the same object + /// + public SameAsConstraint SameAs(object expected) + { + return new SameAsConstraint(expected); + } + + #endregion + + #region GreaterThan + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than the suppled argument + /// + public GreaterThanConstraint GreaterThan(object expected) + { + return new GreaterThanConstraint(expected); + } + + #endregion + + #region GreaterThanOrEqualTo + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than or equal to the suppled argument + /// + public GreaterThanOrEqualConstraint GreaterThanOrEqualTo(object expected) + { + return new GreaterThanOrEqualConstraint(expected); + } + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than or equal to the suppled argument + /// + public GreaterThanOrEqualConstraint AtLeast(object expected) + { + return new GreaterThanOrEqualConstraint(expected); + } + + #endregion + + #region LessThan + + /// + /// Returns a constraint that tests whether the + /// actual value is less than the suppled argument + /// + public LessThanConstraint LessThan(object expected) + { + return new LessThanConstraint(expected); + } + + #endregion + + #region LessThanOrEqualTo + + /// + /// Returns a constraint that tests whether the + /// actual value is less than or equal to the suppled argument + /// + public LessThanOrEqualConstraint LessThanOrEqualTo(object expected) + { + return new LessThanOrEqualConstraint(expected); + } + + /// + /// Returns a constraint that tests whether the + /// actual value is less than or equal to the suppled argument + /// + public LessThanOrEqualConstraint AtMost(object expected) + { + return new LessThanOrEqualConstraint(expected); + } + + #endregion + + #region TypeOf + + /// + /// Returns a constraint that tests whether the actual + /// value is of the exact type supplied as an argument. + /// + public ExactTypeConstraint TypeOf(Type expectedType) + { + return new ExactTypeConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual + /// value is of the exact type supplied as an argument. + /// + public ExactTypeConstraint TypeOf() + { + return new ExactTypeConstraint(typeof(T)); + } +#endif + + #endregion + + #region InstanceOf + + /// + /// Returns a constraint that tests whether the actual value + /// is of the type supplied as an argument or a derived type. + /// + public InstanceOfTypeConstraint InstanceOf(Type expectedType) + { + return new InstanceOfTypeConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is of the type supplied as an argument or a derived type. + /// + public InstanceOfTypeConstraint InstanceOf() + { + return new InstanceOfTypeConstraint(typeof(T)); + } +#endif + + #endregion + + #region AssignableFrom + + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableFromConstraint AssignableFrom(Type expectedType) + { + return new AssignableFromConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableFromConstraint AssignableFrom() + { + return new AssignableFromConstraint(typeof(T)); + } +#endif + + #endregion + + #region AssignableTo + + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableToConstraint AssignableTo(Type expectedType) + { + return new AssignableToConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public AssignableToConstraint AssignableTo() + { + return new AssignableToConstraint(typeof(T)); + } +#endif + + #endregion + + #region EquivalentTo + + /// + /// Returns a constraint that tests whether the actual value + /// is a collection containing the same elements as the + /// collection supplied as an argument. + /// + public CollectionEquivalentConstraint EquivalentTo(IEnumerable expected) + { + return new CollectionEquivalentConstraint(expected); + } + + #endregion + + #region SubsetOf + + /// + /// Returns a constraint that tests whether the actual value + /// is a subset of the collection supplied as an argument. + /// + public CollectionSubsetConstraint SubsetOf(IEnumerable expected) + { + return new CollectionSubsetConstraint(expected); + } + + #endregion + + #region Ordered + + /// + /// Returns a constraint that tests whether a collection is ordered + /// + public CollectionOrderedConstraint Ordered + { + get { return new CollectionOrderedConstraint(); } + } + + #endregion + + #region Member + + /// + /// Returns a new CollectionContainsConstraint checking for the + /// presence of a particular object in the collection. + /// + public CollectionContainsConstraint Member(object expected) + { + return new CollectionContainsConstraint(expected); + } + + /// + /// Returns a new CollectionContainsConstraint checking for the + /// presence of a particular object in the collection. + /// + public CollectionContainsConstraint Contains(object expected) + { + return new CollectionContainsConstraint(expected); + } + + #endregion + + #region Contains + + /// + /// Returns a new ContainsConstraint. This constraint + /// will, in turn, make use of the appropriate second-level + /// constraint, depending on the type of the actual argument. + /// This overload is only used if the item sought is a string, + /// since any other type implies that we are looking for a + /// collection member. + /// + public ContainsConstraint Contains(string expected) + { + return new ContainsConstraint(expected); + } + + #endregion + + #region StringContaining + + /// + /// Returns a constraint that succeeds if the actual + /// value contains the substring supplied as an argument. + /// + public SubstringConstraint StringContaining(string expected) + { + return new SubstringConstraint(expected); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value contains the substring supplied as an argument. + /// + public SubstringConstraint ContainsSubstring(string expected) + { + return new SubstringConstraint(expected); + } + + #endregion + + #region DoesNotContain + + /// + /// Returns a constraint that fails if the actual + /// value contains the substring supplied as an argument. + /// + public SubstringConstraint DoesNotContain(string expected) + { + return new ConstraintExpression().Not.ContainsSubstring(expected); + } + + #endregion + + #region StartsWith + + /// + /// Returns a constraint that succeeds if the actual + /// value starts with the substring supplied as an argument. + /// + public StartsWithConstraint StartsWith(string expected) + { + return new StartsWithConstraint(expected); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value starts with the substring supplied as an argument. + /// + public StartsWithConstraint StringStarting(string expected) + { + return new StartsWithConstraint(expected); + } + + #endregion + + #region DoesNotStartWith + + /// + /// Returns a constraint that fails if the actual + /// value starts with the substring supplied as an argument. + /// + public StartsWithConstraint DoesNotStartWith(string expected) + { + return new ConstraintExpression().Not.StartsWith(expected); + } + + #endregion + + #region EndsWith + + /// + /// Returns a constraint that succeeds if the actual + /// value ends with the substring supplied as an argument. + /// + public EndsWithConstraint EndsWith(string expected) + { + return new EndsWithConstraint(expected); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value ends with the substring supplied as an argument. + /// + public EndsWithConstraint StringEnding(string expected) + { + return new EndsWithConstraint(expected); + } + + #endregion + + #region DoesNotEndWith + + /// + /// Returns a constraint that fails if the actual + /// value ends with the substring supplied as an argument. + /// + public EndsWithConstraint DoesNotEndWith(string expected) + { + return new ConstraintExpression().Not.EndsWith(expected); + } + + #endregion + + #region Matches + +#if !NETCF + /// + /// Returns a constraint that succeeds if the actual + /// value matches the regular expression supplied as an argument. + /// + public RegexConstraint Matches(string pattern) + { + return new RegexConstraint(pattern); + } + + /// + /// Returns a constraint that succeeds if the actual + /// value matches the regular expression supplied as an argument. + /// + public RegexConstraint StringMatching(string pattern) + { + return new RegexConstraint(pattern); + } +#endif + + #endregion + + #region DoesNotMatch + +#if !NETCF + /// + /// Returns a constraint that fails if the actual + /// value matches the pattern supplied as an argument. + /// + public RegexConstraint DoesNotMatch(string pattern) + { + return new ConstraintExpression().Not.Matches(pattern); + } +#endif + + #endregion + + #region SamePath + + /// + /// Returns a constraint that tests whether the path provided + /// is the same as an expected path after canonicalization. + /// + public SamePathConstraint SamePath(string expected) + { + return new SamePathConstraint(expected); + } + + #endregion + + #region SubPath + + /// + /// Returns a constraint that tests whether the path provided + /// is the same path or under an expected path after canonicalization. + /// + public SubPathConstraint SubPath(string expected) + { + return new SubPathConstraint(expected); + } + + #endregion + + #region SamePathOrUnder + + /// + /// Returns a constraint that tests whether the path provided + /// is the same path or under an expected path after canonicalization. + /// + public SamePathOrUnderConstraint SamePathOrUnder(string expected) + { + return new SamePathOrUnderConstraint(expected); + } + + #endregion + + #region InRange + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value falls + /// within a specified range. + /// + public RangeConstraint InRange(T from, T to) where T : IComparable + { + return new RangeConstraint(from, to); + } +#else + /// + /// Returns a constraint that tests whether the actual value falls + /// within a specified range. + /// + public RangeConstraint InRange(IComparable from, IComparable to) + { + return new RangeConstraint(from, to); + } +#endif + + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ContainsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ContainsConstraint.cs new file mode 100644 index 00000000000..f5e23ad9b3e --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ContainsConstraint.cs @@ -0,0 +1,183 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + // TODO Needs tests + /// + /// ContainsConstraint tests a whether a string contains a substring + /// or a collection contains an object. It postpones the decision of + /// which test to use until the type of the actual argument is known. + /// This allows testing whether a string is contained in a collection + /// or as a substring of another string using the same syntax. + /// + public class ContainsConstraint : Constraint + { + readonly object expected; + Constraint realConstraint; + bool ignoreCase; + +#if CLR_2_0 || CLR_4_0 + private List equalityAdapters = new List(); +#else + private ArrayList equalityAdapters = new ArrayList(); +#endif + + private Constraint RealConstraint + { + get + { + if ( realConstraint == null ) + { + if (actual is string) + { + StringConstraint constraint = new SubstringConstraint((string)expected); + if (this.ignoreCase) + constraint = constraint.IgnoreCase; + this.realConstraint = constraint; + } + else + { + CollectionItemsEqualConstraint constraint = new CollectionContainsConstraint(expected); + + foreach (EqualityAdapter adapter in equalityAdapters) + constraint = constraint.Using(adapter); + + this.realConstraint = constraint; + } + } + + return realConstraint; + } + set + { + realConstraint = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The expected. + public ContainsConstraint( object expected ) : base(expected) + { + this.expected = expected; + } + + /// + /// Flag the constraint to ignore case and return self. + /// + public ContainsConstraint IgnoreCase + { + get { this.ignoreCase = true; return this; } + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + return this.RealConstraint.Matches( actual ); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + this.RealConstraint.WriteDescriptionTo(writer); + } + + /// + /// Flag the constraint to use the supplied IComparer object. + /// + /// The IComparer object to use. + /// Self. + public ContainsConstraint Using(IComparer comparer) + { + return AddAdapter(EqualityAdapter.For(comparer)); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Flag the constraint to use the supplied IComparer object. + /// + /// The IComparer object to use. + /// Self. + public ContainsConstraint Using(IComparer comparer) + { + return AddAdapter(EqualityAdapter.For(comparer)); + } + + /// + /// Flag the constraint to use the supplied Comparison object. + /// + /// The IComparer object to use. + /// Self. + public ContainsConstraint Using(Comparison comparer) + { + return AddAdapter(EqualityAdapter.For(comparer)); + } + + /// + /// Flag the constraint to use the supplied IEqualityComparer object. + /// + /// The IComparer object to use. + /// Self. + public ContainsConstraint Using(IEqualityComparer comparer) + { + return AddAdapter(EqualityAdapter.For(comparer)); + } + + /// + /// Flag the constraint to use the supplied IEqualityComparer object. + /// + /// The IComparer object to use. + /// Self. + public ContainsConstraint Using(IEqualityComparer comparer) + { + return AddAdapter(EqualityAdapter.For(comparer)); + } +#endif + + #region Helper Methods + + private ContainsConstraint AddAdapter(EqualityAdapter adapter) + { + this.equalityAdapters.Add(adapter); + return this; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/DelayedConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/DelayedConstraint.cs new file mode 100644 index 00000000000..74d16b46001 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/DelayedConstraint.cs @@ -0,0 +1,232 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Threading; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Constraints +{ + /// + /// Applies a delay to the match so that a match can be evaluated in the future. + /// + public class DelayedConstraint : PrefixConstraint + { + private readonly int delayInMilliseconds; + private readonly int pollingInterval; + + /// + /// Creates a new DelayedConstraint + /// + ///The inner constraint two decorate + ///The time interval after which the match is performed + ///If the value of is less than 0 + public DelayedConstraint(Constraint baseConstraint, int delayInMilliseconds) + : this(baseConstraint, delayInMilliseconds, 0) { } + + /// + /// Creates a new DelayedConstraint + /// + ///The inner constraint two decorate + ///The time interval after which the match is performed + ///The time interval used for polling + ///If the value of is less than 0 + public DelayedConstraint(Constraint baseConstraint, int delayInMilliseconds, int pollingInterval) + : base(baseConstraint) + { + if (delayInMilliseconds < 0) + throw new ArgumentException("Cannot check a condition in the past", "delayInMilliseconds"); + + this.delayInMilliseconds = delayInMilliseconds; + this.pollingInterval = pollingInterval; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for if the base constraint fails, false if it succeeds + public override bool Matches(object actual) + { + int remainingDelay = delayInMilliseconds; + + while (pollingInterval > 0 && pollingInterval < remainingDelay) + { + remainingDelay -= pollingInterval; + Thread.Sleep(pollingInterval); + this.actual = actual; + if (baseConstraint.Matches(actual)) + return true; + } + + if (remainingDelay > 0) + Thread.Sleep(remainingDelay); + this.actual = actual; + return baseConstraint.Matches(actual); + } + + /// + /// Test whether the constraint is satisfied by a delegate + /// + /// The delegate whose value is to be tested + /// True for if the base constraint fails, false if it succeeds +#if CLR_2_0 || CLR_4_0 + public override bool Matches(ActualValueDelegate del) +#else + public override bool Matches(ActualValueDelegate del) +#endif + { + int remainingDelay = delayInMilliseconds; + + while (pollingInterval > 0 && pollingInterval < remainingDelay) + { + remainingDelay -= pollingInterval; + Thread.Sleep(pollingInterval); + this.actual = InvokeDelegate(del); + + try + { + if (baseConstraint.Matches(actual)) + return true; + } + catch + { + // Ignore any exceptions when polling + } + } + + if (remainingDelay > 0) + Thread.Sleep(remainingDelay); + this.actual = InvokeDelegate(del); + return baseConstraint.Matches(actual); + } + +#if CLR_2_0 || CLR_4_0 + private static object InvokeDelegate(ActualValueDelegate del) + { +#if NET_4_5 + if (AsyncInvocationRegion.IsAsyncOperation(del)) + using (AsyncInvocationRegion region = AsyncInvocationRegion.Create(del)) + return region.WaitForPendingOperationsToComplete(del()); +#endif + + return del(); + } +#else + private static object InvokeDelegate(ActualValueDelegate del) + { + return del(); + } +#endif + +#if CLR_2_0 || CLR_4_0 + /// + /// Test whether the constraint is satisfied by a given reference. + /// Overridden to wait for the specified delay period before + /// calling the base constraint with the dereferenced value. + /// + /// A reference to the value to be tested + /// True for success, false for failure + public override bool Matches(ref T actual) + { + int remainingDelay = delayInMilliseconds; + + while (pollingInterval > 0 && pollingInterval < remainingDelay) + { + remainingDelay -= pollingInterval; + Thread.Sleep(pollingInterval); + this.actual = actual; + + try + { + if (baseConstraint.Matches(actual)) + return true; + } + catch (Exception) + { + // Ignore any exceptions when polling + } + } + + if (remainingDelay > 0) + Thread.Sleep(remainingDelay); + this.actual = actual; + return baseConstraint.Matches(actual); + } +#else + /// + /// Test whether the constraint is satisfied by a given boolean reference. + /// Overridden to wait for the specified delay period before + /// calling the base constraint with the dereferenced value. + /// + /// A reference to the value to be tested + /// True for success, false for failure + public override bool Matches(ref bool actual) + { + int remainingDelay = delayInMilliseconds; + + while (pollingInterval > 0 && pollingInterval < remainingDelay) + { + remainingDelay -= pollingInterval; + Thread.Sleep(pollingInterval); + this.actual = actual; + + if (baseConstraint.Matches(actual)) + return true; + } + + if (remainingDelay > 0) + Thread.Sleep(remainingDelay); + this.actual = actual; + return baseConstraint.Matches(actual); + } +#endif + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + baseConstraint.WriteDescriptionTo(writer); + writer.Write(string.Format(" after {0} millisecond delay", delayInMilliseconds)); + } + + /// + /// Write the actual value for a failing constraint test to a MessageWriter. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + baseConstraint.WriteActualValueTo(writer); + } + + /// + /// Returns the string representation of the constraint. + /// + protected override string GetStringRepresentation() + { + return string.Format("", delayInMilliseconds, baseConstraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyCollectionConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyCollectionConstraint.cs new file mode 100644 index 00000000000..28471ec48e9 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyCollectionConstraint.cs @@ -0,0 +1,52 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// EmptyCollectionConstraint tests whether a collection is empty. + /// + public class EmptyCollectionConstraint : CollectionConstraint + { + /// + /// Check that the collection is empty + /// + /// + /// + protected override bool doMatch(IEnumerable collection) + { + return IsEmpty(collection); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write(""); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyConstraint.cs new file mode 100644 index 00000000000..ef627117131 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyConstraint.cs @@ -0,0 +1,72 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// EmptyConstraint tests a whether a string or collection is empty, + /// postponing the decision about which test is applied until the + /// type of the actual argument is known. + /// + public class EmptyConstraint : Constraint + { + private Constraint RealConstraint + { + get + { + if (actual is string) + return new EmptyStringConstraint(); + else if (actual is System.IO.DirectoryInfo) + return new EmptyDirectoryConstraint(); + else + return new EmptyCollectionConstraint(); + } + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (actual == null) + throw new ArgumentException("The actual value must be a non-null string, IEnumerable or DirectoryInfo", "actual"); + + return this.RealConstraint.Matches( actual ); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + this.RealConstraint.WriteDescriptionTo( writer ); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyDirectoryConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyDirectoryConstraint.cs new file mode 100644 index 00000000000..e08b9cd02e3 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyDirectoryConstraint.cs @@ -0,0 +1,91 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// EmptyDirectoryConstraint is used to test that a directory is empty + /// + public class EmptyDirectoryConstraint : Constraint + { + private int files = 0; + private int subdirs = 0; + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + DirectoryInfo dirInfo = actual as DirectoryInfo; + if (dirInfo == null) + throw new ArgumentException("The actual value must be a DirectoryInfo", "actual"); + +#if SL_4_0 || SL_5_0 + foreach (FileInfo file in dirInfo.EnumerateFiles()) + files++; + foreach (DirectoryInfo dir in dirInfo.EnumerateDirectories()) + subdirs++; +#else + files = dirInfo.GetFiles().Length; + subdirs = dirInfo.GetDirectories().Length; +#endif + + return files == 0 && subdirs == 0; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write( "An empty directory" ); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + DirectoryInfo dir = actual as DirectoryInfo; + if (dir == null) + base.WriteActualValueTo(writer); + else + { + writer.WriteActualValue(dir); + writer.Write(" with {0} files and {1} directories", files, subdirs); + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyStringConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyStringConstraint.cs new file mode 100644 index 00000000000..dfc0f3df557 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EmptyStringConstraint.cs @@ -0,0 +1,52 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// EmptyStringConstraint tests whether a string is empty. + /// + public class EmptyStringConstraint : Constraint + { + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + return actual as string == string.Empty; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write(""); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EndsWithConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EndsWithConstraint.cs new file mode 100644 index 00000000000..282845321f0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EndsWithConstraint.cs @@ -0,0 +1,65 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// EndsWithConstraint can test whether a string ends + /// with an expected substring. + /// + public class EndsWithConstraint : StringConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The expected string + public EndsWithConstraint(string expected) : base(expected) { } + + /// + /// Test whether the constraint is matched by the actual value. + /// This is a template method, which calls the IsMatch method + /// of the derived class. + /// + /// + /// + protected override bool Matches(string actual) + { + if (this.caseInsensitive) + return actual.ToLower().EndsWith(expected.ToLower()); + else + return actual.EndsWith(expected); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("String ending with"); + writer.WriteExpectedValue(expected); + if (this.caseInsensitive) + writer.WriteModifier("ignoring case"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EqualConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EqualConstraint.cs new file mode 100644 index 00000000000..6be6b2955c1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EqualConstraint.cs @@ -0,0 +1,565 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// EqualConstraint is able to compare an actual value with the + /// expected value provided in its constructor. Two objects are + /// considered equal if both are null, or if both have the same + /// value. NUnit has special semantics for some object types. + /// + public class EqualConstraint : Constraint + { + #region Static and Instance Fields + + private readonly object expected; + + private Tolerance tolerance = Tolerance.Empty; + + /// + /// If true, strings in error messages will be clipped + /// + private bool clipStrings = true; + + /// + /// NUnitEqualityComparer used to test equality. + /// + private NUnitEqualityComparer comparer = new NUnitEqualityComparer(); + + #region Message Strings + private static readonly string StringsDiffer_1 = + "String lengths are both {0}. Strings differ at index {1}."; + private static readonly string StringsDiffer_2 = + "Expected string length {0} but was {1}. Strings differ at index {2}."; + private static readonly string StreamsDiffer_1 = + "Stream lengths are both {0}. Streams differ at offset {1}."; + private static readonly string StreamsDiffer_2 = + "Expected Stream length {0} but was {1}.";// Streams differ at offset {2}."; + private static readonly string CollectionType_1 = + "Expected and actual are both {0}"; + private static readonly string CollectionType_2 = + "Expected is {0}, actual is {1}"; + private static readonly string ValuesDiffer_1 = + "Values differ at index {0}"; + private static readonly string ValuesDiffer_2 = + "Values differ at expected index {0}, actual index {1}"; + #endregion + + #endregion + + #region Constructor + /// + /// Initializes a new instance of the class. + /// + /// The expected value. + public EqualConstraint(object expected) : base(expected) + { + this.expected = expected; + } + #endregion + + #region Constraint Modifiers + /// + /// Flag the constraint to ignore case and return self. + /// + public EqualConstraint IgnoreCase + { + get + { + comparer.IgnoreCase = true; + return this; + } + } + + /// + /// Flag the constraint to suppress string clipping + /// and return self. + /// + public EqualConstraint NoClip + { + get + { + clipStrings = false; + return this; + } + } + + /// + /// Flag the constraint to compare arrays as collections + /// and return self. + /// + public EqualConstraint AsCollection + { + get + { + comparer.CompareAsCollection = true; + return this; + } + } + + /// + /// Flag the constraint to use a tolerance when determining equality. + /// + /// Tolerance value to be used + /// Self. + public EqualConstraint Within(object amount) + { + if (!tolerance.IsEmpty) + throw new InvalidOperationException("Within modifier may appear only once in a constraint expression"); + + tolerance = new Tolerance(amount); + return this; + } + + /// + /// Switches the .Within() modifier to interpret its tolerance as + /// a distance in representable values (see remarks). + /// + /// Self. + /// + /// Ulp stands for "unit in the last place" and describes the minimum + /// amount a given value can change. For any integers, an ulp is 1 whole + /// digit. For floating point values, the accuracy of which is better + /// for smaller numbers and worse for larger numbers, an ulp depends + /// on the size of the number. Using ulps for comparison of floating + /// point results instead of fixed tolerances is safer because it will + /// automatically compensate for the added inaccuracy of larger numbers. + /// + public EqualConstraint Ulps + { + get + { + tolerance = tolerance.Ulps; + return this; + } + } + + /// + /// Switches the .Within() modifier to interpret its tolerance as + /// a percentage that the actual values is allowed to deviate from + /// the expected value. + /// + /// Self + public EqualConstraint Percent + { + get + { + tolerance = tolerance.Percent; + return this; + } + } + + /// + /// Causes the tolerance to be interpreted as a TimeSpan in days. + /// + /// Self + public EqualConstraint Days + { + get + { + tolerance = tolerance.Days; + return this; + } + } + + /// + /// Causes the tolerance to be interpreted as a TimeSpan in hours. + /// + /// Self + public EqualConstraint Hours + { + get + { + tolerance = tolerance.Hours; + return this; + } + } + + /// + /// Causes the tolerance to be interpreted as a TimeSpan in minutes. + /// + /// Self + public EqualConstraint Minutes + { + get + { + tolerance = tolerance.Minutes; + return this; + } + } + + /// + /// Causes the tolerance to be interpreted as a TimeSpan in seconds. + /// + /// Self + public EqualConstraint Seconds + { + get + { + tolerance = tolerance.Seconds; + return this; + } + } + + /// + /// Causes the tolerance to be interpreted as a TimeSpan in milliseconds. + /// + /// Self + public EqualConstraint Milliseconds + { + get + { + tolerance = tolerance.Milliseconds; + return this; + } + } + + /// + /// Causes the tolerance to be interpreted as a TimeSpan in clock ticks. + /// + /// Self + public EqualConstraint Ticks + { + get + { + tolerance = tolerance.Ticks; + return this; + } + } + + /// + /// Flag the constraint to use the supplied IComparer object. + /// + /// The IComparer object to use. + /// Self. + public EqualConstraint Using(IComparer comparer) + { + this.comparer.ExternalComparers.Add(EqualityAdapter.For(comparer)); + return this; + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Flag the constraint to use the supplied IComparer object. + /// + /// The IComparer object to use. + /// Self. + public EqualConstraint Using(IComparer comparer) + { + this.comparer.ExternalComparers.Add(EqualityAdapter.For(comparer)); + return this; + } + + /// + /// Flag the constraint to use the supplied Comparison object. + /// + /// The IComparer object to use. + /// Self. + public EqualConstraint Using(Comparison comparer) + { + this.comparer.ExternalComparers.Add(EqualityAdapter.For(comparer)); + return this; + } + + /// + /// Flag the constraint to use the supplied IEqualityComparer object. + /// + /// The IComparer object to use. + /// Self. + public EqualConstraint Using(IEqualityComparer comparer) + { + this.comparer.ExternalComparers.Add(EqualityAdapter.For(comparer)); + return this; + } + + /// + /// Flag the constraint to use the supplied IEqualityComparer object. + /// + /// The IComparer object to use. + /// Self. + public EqualConstraint Using(IEqualityComparer comparer) + { + this.comparer.ExternalComparers.Add(EqualityAdapter.For(comparer)); + return this; + } +#endif + + #endregion + + #region Public Methods + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + return comparer.AreEqual(expected, actual, ref tolerance); + } + + /// + /// Write a failure message. Overridden to provide custom + /// failure messages for EqualConstraint. + /// + /// The MessageWriter to write to + public override void WriteMessageTo(MessageWriter writer) + { + DisplayDifferences(writer, expected, actual, 0); + } + + + /// + /// Write description of this constraint + /// + /// The MessageWriter to write to + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WriteExpectedValue(expected); + + if (tolerance != null && !tolerance.IsEmpty) + { + writer.WriteConnector("+/-"); + writer.WriteExpectedValue(tolerance.Value); + if (tolerance.Mode != ToleranceMode.Linear) + writer.Write(" {0}", tolerance.Mode); + } + + if (comparer.IgnoreCase) + writer.WriteModifier("ignoring case"); + } + + private void DisplayDifferences(MessageWriter writer, object expected, object actual, int depth) + { + if (expected is string && actual is string) + DisplayStringDifferences(writer, (string)expected, (string)actual); + else if (expected is ICollection && actual is ICollection) + DisplayCollectionDifferences(writer, (ICollection)expected, (ICollection)actual, depth); + else if (expected is IEnumerable && actual is IEnumerable) + DisplayEnumerableDifferences(writer, (IEnumerable)expected, (IEnumerable)actual, depth); + else if (expected is Stream && actual is Stream) + DisplayStreamDifferences(writer, (Stream)expected, (Stream)actual, depth); + else if (tolerance != null) + writer.DisplayDifferences(expected, actual, tolerance); + else + writer.DisplayDifferences(expected, actual); + } + #endregion + + #region DisplayStringDifferences + private void DisplayStringDifferences(MessageWriter writer, string expected, string actual) + { + int mismatch = MsgUtils.FindMismatchPosition(expected, actual, 0, comparer.IgnoreCase); + + if (expected.Length == actual.Length) + writer.WriteMessageLine(StringsDiffer_1, expected.Length, mismatch); + else + writer.WriteMessageLine(StringsDiffer_2, expected.Length, actual.Length, mismatch); + + writer.DisplayStringDifferences(expected, actual, mismatch, comparer.IgnoreCase, clipStrings); + } + #endregion + + #region DisplayStreamDifferences + private void DisplayStreamDifferences(MessageWriter writer, Stream expected, Stream actual, int depth) + { + if (expected.Length == actual.Length) + { + FailurePoint fp = (FailurePoint)comparer.FailurePoints[depth]; + long offset = fp.Position; + writer.WriteMessageLine(StreamsDiffer_1, expected.Length, offset); + } + else + writer.WriteMessageLine(StreamsDiffer_2, expected.Length, actual.Length); + } + #endregion + + #region DisplayCollectionDifferences + /// + /// Display the failure information for two collections that did not match. + /// + /// The MessageWriter on which to display + /// The expected collection. + /// The actual collection + /// The depth of this failure in a set of nested collections + private void DisplayCollectionDifferences(MessageWriter writer, ICollection expected, ICollection actual, int depth) + { + DisplayTypesAndSizes(writer, expected, actual, depth); + + if (comparer.FailurePoints.Count > depth) + { + FailurePoint failurePoint = (FailurePoint)comparer.FailurePoints[depth]; + + DisplayFailurePoint(writer, expected, actual, failurePoint, depth); + + if (failurePoint.ExpectedHasData && failurePoint.ActualHasData) + DisplayDifferences( + writer, + failurePoint.ExpectedValue, + failurePoint.ActualValue, + ++depth); + else if (failurePoint.ActualHasData) + { + writer.Write(" Extra: "); + writer.WriteCollectionElements(actual, failurePoint.Position, 3); + } + else + { + writer.Write(" Missing: "); + writer.WriteCollectionElements(expected, failurePoint.Position, 3); + } + } + } + + /// + /// Displays a single line showing the types and sizes of the expected + /// and actual enumerations, collections or arrays. If both are identical, + /// the value is only shown once. + /// + /// The MessageWriter on which to display + /// The expected collection or array + /// The actual collection or array + /// The indentation level for the message line + private void DisplayTypesAndSizes(MessageWriter writer, IEnumerable expected, IEnumerable actual, int indent) + { + string sExpected = MsgUtils.GetTypeRepresentation(expected); + if (expected is ICollection && !(expected is Array)) + sExpected += string.Format(" with {0} elements", ((ICollection)expected).Count); + + string sActual = MsgUtils.GetTypeRepresentation(actual); + if (actual is ICollection && !(actual is Array)) + sActual += string.Format(" with {0} elements", ((ICollection)actual).Count); + + if (sExpected == sActual) + writer.WriteMessageLine(indent, CollectionType_1, sExpected); + else + writer.WriteMessageLine(indent, CollectionType_2, sExpected, sActual); + } + + /// + /// Displays a single line showing the point in the expected and actual + /// arrays at which the comparison failed. If the arrays have different + /// structures or dimensions, both values are shown. + /// + /// The MessageWriter on which to display + /// The expected array + /// The actual array + /// Index of the failure point in the underlying collections + /// The indentation level for the message line + private void DisplayFailurePoint(MessageWriter writer, IEnumerable expected, IEnumerable actual, FailurePoint failurePoint, int indent) + { + Array expectedArray = expected as Array; + Array actualArray = actual as Array; + + int expectedRank = expectedArray != null ? expectedArray.Rank : 1; + int actualRank = actualArray != null ? actualArray.Rank : 1; + + bool useOneIndex = expectedRank == actualRank; + + if (expectedArray != null && actualArray != null) + for (int r = 1; r < expectedRank && useOneIndex; r++) + if (expectedArray.GetLength(r) != actualArray.GetLength(r)) + useOneIndex = false; + + int[] expectedIndices = MsgUtils.GetArrayIndicesFromCollectionIndex(expected, failurePoint.Position); + if (useOneIndex) + { + writer.WriteMessageLine(indent, ValuesDiffer_1, MsgUtils.GetArrayIndicesAsString(expectedIndices)); + } + else + { + int[] actualIndices = MsgUtils.GetArrayIndicesFromCollectionIndex(actual, failurePoint.Position); + writer.WriteMessageLine(indent, ValuesDiffer_2, + MsgUtils.GetArrayIndicesAsString(expectedIndices), MsgUtils.GetArrayIndicesAsString(actualIndices)); + } + } + + private static object GetValueFromCollection(ICollection collection, int index) + { + Array array = collection as Array; + + if (array != null && array.Rank > 1) + return array.GetValue(MsgUtils.GetArrayIndicesFromCollectionIndex(array, index)); + + if (collection is IList) + return ((IList)collection)[index]; + + foreach (object obj in collection) + if (--index < 0) + return obj; + + return null; + } + #endregion + + #region DisplayEnumerableDifferences + + /// + /// Display the failure information for two IEnumerables that did not match. + /// + /// The MessageWriter on which to display + /// The expected enumeration. + /// The actual enumeration + /// The depth of this failure in a set of nested collections + private void DisplayEnumerableDifferences(MessageWriter writer, IEnumerable expected, IEnumerable actual, int depth) + { + DisplayTypesAndSizes(writer, expected, actual, depth); + + if (comparer.FailurePoints.Count > depth) + { + FailurePoint failurePoint = (FailurePoint)comparer.FailurePoints[depth]; + + DisplayFailurePoint(writer, expected, actual, failurePoint, depth); + + if (failurePoint.ExpectedHasData && failurePoint.ActualHasData) + DisplayDifferences( + writer, + failurePoint.ExpectedValue, + failurePoint.ActualValue, + ++depth); + //else if (failurePoint.ActualHasData) + //{ + // writer.Write(" Extra: "); + // writer.WriteCollectionElements(actual, failurePoint.Position, 3); + //} + //else + //{ + // writer.Write(" Missing: "); + // writer.WriteCollectionElements(expected, failurePoint.Position, 3); + //} + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EqualityAdapter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EqualityAdapter.cs new file mode 100644 index 00000000000..36cc53ad45a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/EqualityAdapter.cs @@ -0,0 +1,241 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// EqualityAdapter class handles all equality comparisons + /// that use an IEqualityComparer, IEqualityComparer<T> + /// or a ComparisonAdapter. + /// + public abstract class EqualityAdapter + { + /// + /// Compares two objects, returning true if they are equal + /// + public abstract bool AreEqual(object x, object y); + + /// + /// Returns true if the two objects can be compared by this adapter. + /// The base adapter cannot handle IEnumerables except for strings. + /// + public virtual bool CanCompare(object x, object y) + { + if (x is string && y is string) + return true; + + if (x is IEnumerable || y is IEnumerable) + return false; + + return true; + } + + #region Nested IComparer Adapter + + /// + /// Returns an EqualityAdapter that wraps an IComparer. + /// + public static EqualityAdapter For(IComparer comparer) + { + return new ComparerAdapter(comparer); + } + + /// + /// EqualityAdapter that wraps an IComparer. + /// + class ComparerAdapter : EqualityAdapter + { + private IComparer comparer; + + public ComparerAdapter(IComparer comparer) + { + this.comparer = comparer; + } + + public override bool AreEqual(object x, object y) + { + return comparer.Compare(x, y) == 0; + } + } + + #endregion + +#if CLR_2_0 || CLR_4_0 + #region Nested IEqualityComparer Adapter + + /// + /// Returns an EqualityAdapter that wraps an IEqualityComparer. + /// + public static EqualityAdapter For(IEqualityComparer comparer) + { + return new EqualityComparerAdapter(comparer); + } + + class EqualityComparerAdapter : EqualityAdapter + { + private IEqualityComparer comparer; + + public EqualityComparerAdapter(IEqualityComparer comparer) + { + this.comparer = comparer; + } + + public override bool AreEqual(object x, object y) + { + return comparer.Equals(x, y); + } + } + + #endregion + + #region Nested GenericEqualityAdapter + + abstract class GenericEqualityAdapter : EqualityAdapter + { + /// + /// Returns true if the two objects can be compared by this adapter. + /// Generic adapter requires objects of the specified type. + /// + public override bool CanCompare(object x, object y) + { + return typeof(T).IsAssignableFrom(x.GetType()) + && typeof(T).IsAssignableFrom(y.GetType()); + } + + protected void ThrowIfNotCompatible(object x, object y) + { + if (!typeof(T).IsAssignableFrom(x.GetType())) + throw new ArgumentException("Cannot compare " + x.ToString()); + + if (!typeof(T).IsAssignableFrom(y.GetType())) + throw new ArgumentException("Cannot compare " + y.ToString()); + } + } + + #endregion + + #region Nested IEqualityComparer Adapter + + /// + /// Returns an EqualityAdapter that wraps an IEqualityComparer<T>. + /// + public static EqualityAdapter For(IEqualityComparer comparer) + { + return new EqualityComparerAdapter(comparer); + } + + class EqualityComparerAdapter : GenericEqualityAdapter + { + private IEqualityComparer comparer; + + public EqualityComparerAdapter(IEqualityComparer comparer) + { + this.comparer = comparer; + } + + public override bool AreEqual(object x, object y) + { + ThrowIfNotCompatible(x, y); + return comparer.Equals((T)x, (T)y); + } + } + + #endregion + + #region Nested IComparer Adapter + + /// + /// Returns an EqualityAdapter that wraps an IComparer<T>. + /// + public static EqualityAdapter For(IComparer comparer) + { + return new ComparerAdapter(comparer); + } + + /// + /// EqualityAdapter that wraps an IComparer. + /// + class ComparerAdapter : GenericEqualityAdapter + { + private IComparer comparer; + + public ComparerAdapter(IComparer comparer) + { + this.comparer = comparer; + } + + public override bool AreEqual(object x, object y) + { + ThrowIfNotCompatible(x, y); + return comparer.Compare((T)x, (T)y) == 0; + } + } + + #endregion + + #region Nested Comparison Adapter + + /// + /// Returns an EqualityAdapter that wraps a Comparison<T>. + /// + public static EqualityAdapter For(Comparison comparer) + { + return new ComparisonAdapter(comparer); + } + + class ComparisonAdapter : GenericEqualityAdapter + { + private Comparison comparer; + + public ComparisonAdapter(Comparison comparer) + { + this.comparer = comparer; + } + + public override bool AreEqual(object x, object y) + { + ThrowIfNotCompatible(x, y); + return comparer.Invoke((T)x, (T)y) == 0; + } + } + + #endregion +#endif + } + + /// + /// EqualityAdapterList represents a list of EqualityAdapters + /// in a common class across platforms. + /// +#if CLR_2_0 || CLR_4_0 + class EqualityAdapterList : System.Collections.Generic.List { } +#else + class EqualityAdapterList : ArrayList { } +#endif +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExactCountConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExactCountConstraint.cs new file mode 100644 index 00000000000..9ef046144a8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExactCountConstraint.cs @@ -0,0 +1,94 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// ExactCountConstraint applies another constraint to each + /// item in a collection, succeeding only if a specified + /// number of items succeed. + /// + public class ExactCountConstraint : PrefixConstraint + { + private int expectedCount; + + /// + /// Construct an ExactCountConstraint on top of an existing constraint + /// + /// + /// + public ExactCountConstraint(int expectedCount, Constraint itemConstraint) + : base(itemConstraint) + { + this.DisplayName = "one"; + this.expectedCount = expectedCount; + } + + /// + /// Apply the item constraint to each item in the collection, + /// succeeding only if the expected number of items pass. + /// + /// + /// + public override bool Matches(object actual) + { + this.actual = actual; + + if (!(actual is IEnumerable)) + throw new ArgumentException("The actual value must be an IEnumerable", "actual"); + + int count = 0; + foreach (object item in (IEnumerable)actual) + if (baseConstraint.Matches(item)) + count++; + + return count == expectedCount; + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + switch(expectedCount) + { + case 0: + writer.WritePredicate("no item"); + break; + case 1: + writer.WritePredicate("exactly one item"); + break; + default: + writer.WritePredicate("exactly " + expectedCount.ToString() + " items"); + break; + } + + baseConstraint.WriteDescriptionTo(writer); + } + } +} + diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExactTypeConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExactTypeConstraint.cs new file mode 100644 index 00000000000..6d548b7958c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExactTypeConstraint.cs @@ -0,0 +1,64 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// ExactTypeConstraint is used to test that an object + /// is of the exact type provided in the constructor + /// + public class ExactTypeConstraint : TypeConstraint + { + /// + /// Construct an ExactTypeConstraint for a given Type + /// + /// The expected Type. + public ExactTypeConstraint(Type type) + : base(type) + { + this.DisplayName = "typeof"; + } + + /// + /// Test that an object is of the exact type specified + /// + /// The actual value. + /// True if the tested object is of the exact type provided, otherwise false. + public override bool Matches(object actual) + { + this.actual = actual; + return actual != null && actual.GetType() == this.expectedType; + } + + /// + /// Write the description of this constraint to a MessageWriter + /// + /// The MessageWriter to use + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WriteExpectedValue(expectedType); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExceptionTypeConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExceptionTypeConstraint.cs new file mode 100644 index 00000000000..21ddda0cf39 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ExceptionTypeConstraint.cs @@ -0,0 +1,59 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// ExceptionTypeConstraint is a special version of ExactTypeConstraint + /// used to provided detailed info about the exception thrown in + /// an error message. + /// + public class ExceptionTypeConstraint : ExactTypeConstraint + { + /// + /// Constructs an ExceptionTypeConstraint + /// + public ExceptionTypeConstraint(Type type) : base(type) { } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. Overriden to write additional information + /// in the case of an Exception. + /// + /// The MessageWriter to use + public override void WriteActualValueTo(MessageWriter writer) + { + Exception ex = actual as Exception; + base.WriteActualValueTo(writer); + + if (ex != null) + { + writer.WriteLine(" ({0})", ex.Message); + writer.Write(ex.StackTrace); + } + } + } +} + diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FailurePoint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FailurePoint.cs new file mode 100644 index 00000000000..f051db6ca47 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FailurePoint.cs @@ -0,0 +1,68 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// FailurePoint class represents one point of failure + /// in an equality test. + /// + public class FailurePoint + { + /// + /// The location of the failure + /// + public int Position; + + /// + /// The expected value + /// + public object ExpectedValue; + + /// + /// The actual value + /// + public object ActualValue; + + /// + /// Indicates whether the expected value is valid + /// + public bool ExpectedHasData; + + /// + /// Indicates whether the actual value is valid + /// + public bool ActualHasData; + } + + /// + /// FailurePointList represents a set of FailurePoints + /// in a cross-platform way. + /// +#if CLR_2_0 || CLR_4_0 + class FailurePointList : System.Collections.Generic.List { } +#else + class FailurePointList : System.Collections.ArrayList { } +#endif + +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FalseConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FalseConstraint.cs new file mode 100644 index 00000000000..05669e48c37 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FalseConstraint.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// FalseConstraint tests that the actual value is false + /// + public class FalseConstraint : BasicConstraint + { + /// + /// Initializes a new instance of the class. + /// + public FalseConstraint() : base(false, "False") { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FloatingPointNumerics.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FloatingPointNumerics.cs new file mode 100644 index 00000000000..901358fbcbf --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/FloatingPointNumerics.cs @@ -0,0 +1,251 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + + /// Helper routines for working with floating point numbers + /// + /// + /// The floating point comparison code is based on this excellent article: + /// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm + /// + /// + /// "ULP" means Unit in the Last Place and in the context of this library refers to + /// the distance between two adjacent floating point numbers. IEEE floating point + /// numbers can only represent a finite subset of natural numbers, with greater + /// accuracy for smaller numbers and lower accuracy for very large numbers. + /// + /// + /// If a comparison is allowed "2 ulps" of deviation, that means the values are + /// allowed to deviate by up to 2 adjacent floating point values, which might be + /// as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. + /// + /// + public class FloatingPointNumerics + { + + #region struct FloatIntUnion + + /// Union of a floating point variable and an integer + [StructLayout(LayoutKind.Explicit)] + private struct FloatIntUnion + { + /// The union's value as a floating point variable + [FieldOffset(0)] + public float Float; + + /// The union's value as an integer + [FieldOffset(0)] + public int Int; + + /// The union's value as an unsigned integer + [FieldOffset(0)] + public uint UInt; + } + + #endregion // struct FloatIntUnion + + #region struct DoubleLongUnion + + /// Union of a double precision floating point variable and a long + [StructLayout(LayoutKind.Explicit)] + private struct DoubleLongUnion + { + /// The union's value as a double precision floating point variable + [FieldOffset(0)] + public double Double; + + /// The union's value as a long + [FieldOffset(0)] + public long Long; + + /// The union's value as an unsigned long + [FieldOffset(0)] + public ulong ULong; + } + + #endregion // struct DoubleLongUnion + + /// Compares two floating point values for equality + /// First floating point value to be compared + /// Second floating point value t be compared + /// + /// Maximum number of representable floating point values that are allowed to + /// be between the left and the right floating point values + /// + /// True if both numbers are equal or close to being equal + /// + /// + /// Floating point values can only represent a finite subset of natural numbers. + /// For example, the values 2.00000000 and 2.00000024 can be stored in a float, + /// but nothing inbetween them. + /// + /// + /// This comparison will count how many possible floating point values are between + /// the left and the right number. If the number of possible values between both + /// numbers is less than or equal to maxUlps, then the numbers are considered as + /// being equal. + /// + /// + /// Implementation partially follows the code outlined here: + /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + /// + /// + public static bool AreAlmostEqualUlps(float left, float right, int maxUlps) + { + FloatIntUnion leftUnion = new FloatIntUnion(); + FloatIntUnion rightUnion = new FloatIntUnion(); + + leftUnion.Float = left; + rightUnion.Float = right; + + uint leftSignMask = (leftUnion.UInt >> 31); + uint rightSignMask = (rightUnion.UInt >> 31); + + uint leftTemp = ((0x80000000 - leftUnion.UInt) & leftSignMask); + leftUnion.UInt = leftTemp | (leftUnion.UInt & ~leftSignMask); + + uint rightTemp = ((0x80000000 - rightUnion.UInt) & rightSignMask); + rightUnion.UInt = rightTemp | (rightUnion.UInt & ~rightSignMask); + + return (Math.Abs(leftUnion.Int - rightUnion.Int) <= maxUlps); + } + + /// Compares two double precision floating point values for equality + /// First double precision floating point value to be compared + /// Second double precision floating point value t be compared + /// + /// Maximum number of representable double precision floating point values that are + /// allowed to be between the left and the right double precision floating point values + /// + /// True if both numbers are equal or close to being equal + /// + /// + /// Double precision floating point values can only represent a limited series of + /// natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 + /// can be stored in a double, but nothing inbetween them. + /// + /// + /// This comparison will count how many possible double precision floating point + /// values are between the left and the right number. If the number of possible + /// values between both numbers is less than or equal to maxUlps, then the numbers + /// are considered as being equal. + /// + /// + /// Implementation partially follows the code outlined here: + /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + /// + /// + public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) + { + DoubleLongUnion leftUnion = new DoubleLongUnion(); + DoubleLongUnion rightUnion = new DoubleLongUnion(); + + leftUnion.Double = left; + rightUnion.Double = right; + + ulong leftSignMask = (leftUnion.ULong >> 63); + ulong rightSignMask = (rightUnion.ULong >> 63); + + ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask); + leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask); + + ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask); + rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask); + + return (Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps); + } + + /// + /// Reinterprets the memory contents of a floating point value as an integer value + /// + /// + /// Floating point value whose memory contents to reinterpret + /// + /// + /// The memory contents of the floating point value interpreted as an integer + /// + public static int ReinterpretAsInt(float value) + { + FloatIntUnion union = new FloatIntUnion(); + union.Float = value; + return union.Int; + } + + /// + /// Reinterprets the memory contents of a double precision floating point + /// value as an integer value + /// + /// + /// Double precision floating point value whose memory contents to reinterpret + /// + /// + /// The memory contents of the double precision floating point value + /// interpreted as an integer + /// + public static long ReinterpretAsLong(double value) + { + DoubleLongUnion union = new DoubleLongUnion(); + union.Double = value; + return union.Long; + } + + /// + /// Reinterprets the memory contents of an integer as a floating point value + /// + /// Integer value whose memory contents to reinterpret + /// + /// The memory contents of the integer value interpreted as a floating point value + /// + public static float ReinterpretAsFloat(int value) + { + FloatIntUnion union = new FloatIntUnion(); + union.Int = value; + return union.Float; + } + + /// + /// Reinterprets the memory contents of an integer value as a double precision + /// floating point value + /// + /// Integer whose memory contents to reinterpret + /// + /// The memory contents of the integer interpreted as a double precision + /// floating point value + /// + public static double ReinterpretAsDouble(long value) + { + DoubleLongUnion union = new DoubleLongUnion(); + union.Long = value; + return union.Double; + } + + private FloatingPointNumerics() + { + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/GreaterThanConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/GreaterThanConstraint.cs new file mode 100644 index 00000000000..35acecbba37 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/GreaterThanConstraint.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// Tests whether a value is greater than the value supplied to its constructor + /// + public class GreaterThanConstraint : ComparisonConstraint + { + /// + /// The value against which a comparison is to be made + /// + private object expected; + + /// + /// Initializes a new instance of the class. + /// + /// The expected value. + public GreaterThanConstraint(object expected) + : base(expected) + { + this.expected = expected; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("greater than"); + writer.WriteExpectedValue(expected); + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (expected == null || actual == null) + throw new ArgumentException("Cannot compare using a null reference"); + + return comparer.Compare(actual, expected) > 0; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/GreaterThanOrEqualConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/GreaterThanOrEqualConstraint.cs new file mode 100644 index 00000000000..3e4ae43c678 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/GreaterThanOrEqualConstraint.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// Tests whether a value is greater than or equal to the value supplied to its constructor + /// + public class GreaterThanOrEqualConstraint : ComparisonConstraint + { + /// + /// The value against which a comparison is to be made + /// + private object expected; + + /// + /// Initializes a new instance of the class. + /// + /// The expected value. + public GreaterThanOrEqualConstraint(object expected) + : base(expected) + { + this.expected = expected; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("greater than or equal to"); + writer.WriteExpectedValue(expected); + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (expected == null || actual == null) + throw new ArgumentException("Cannot compare using a null reference"); + + return comparer.Compare(actual, expected) >= 0; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/IResolveConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/IResolveConstraint.cs new file mode 100644 index 00000000000..cc28c7f1c48 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/IResolveConstraint.cs @@ -0,0 +1,38 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// The IConstraintExpression interface is implemented by all + /// complete and resolvable constraints and expressions. + /// + public interface IResolveConstraint + { + /// + /// Return the top-level constraint for this expression + /// + /// + Constraint Resolve(); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/InstanceOfTypeConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/InstanceOfTypeConstraint.cs new file mode 100644 index 00000000000..c743c52953f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/InstanceOfTypeConstraint.cs @@ -0,0 +1,65 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// InstanceOfTypeConstraint is used to test that an object + /// is of the same type provided or derived from it. + /// + public class InstanceOfTypeConstraint : TypeConstraint + { + /// + /// Construct an InstanceOfTypeConstraint for the type provided + /// + /// The expected Type + public InstanceOfTypeConstraint(Type type) + : base(type) + { + this.DisplayName = "instanceof"; + } + + /// + /// Test whether an object is of the specified type or a derived type + /// + /// The object to be tested + /// True if the object is of the provided type or derives from it, otherwise false. + public override bool Matches(object actual) + { + this.actual = actual; + return actual != null && expectedType.IsInstanceOfType(actual); + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// The MessageWriter to use + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("instance of"); + writer.WriteExpectedValue(expectedType); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/LessThanConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/LessThanConstraint.cs new file mode 100644 index 00000000000..d81404bd62b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/LessThanConstraint.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// Tests whether a value is less than the value supplied to its constructor + /// + public class LessThanConstraint : ComparisonConstraint + { + /// + /// The value against which a comparison is to be made + /// + private object expected; + + /// + /// Initializes a new instance of the class. + /// + /// The expected value. + public LessThanConstraint(object expected) + : base(expected) + { + this.expected = expected; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("less than"); + writer.WriteExpectedValue(expected); + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (expected == null || actual == null) + throw new ArgumentException("Cannot compare using a null reference"); + + return comparer.Compare(actual, expected) < 0; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/LessThanOrEqualConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/LessThanOrEqualConstraint.cs new file mode 100644 index 00000000000..1d7ca21404f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/LessThanOrEqualConstraint.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// Tests whether a value is less than or equal to the value supplied to its constructor + /// + public class LessThanOrEqualConstraint : ComparisonConstraint + { + /// + /// The value against which a comparison is to be made + /// + private object expected; + + /// + /// Initializes a new instance of the class. + /// + /// The expected value. + public LessThanOrEqualConstraint(object expected) + : base(expected) + { + this.expected = expected; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("less than or equal to"); + writer.WriteExpectedValue(expected); + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (expected == null || actual == null) + throw new ArgumentException("Cannot compare using a null reference"); + + return comparer.Compare(actual, expected) <= 0; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/MessageWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/MessageWriter.cs new file mode 100644 index 00000000000..cdd89327016 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/MessageWriter.cs @@ -0,0 +1,154 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.IO; +using System.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// MessageWriter is the abstract base for classes that write + /// constraint descriptions and messages in some form. The + /// class has separate methods for writing various components + /// of a message, allowing implementations to tailor the + /// presentation as needed. + /// + public abstract class MessageWriter : StringWriter + { + + /// + /// Construct a MessageWriter given a culture + /// + protected MessageWriter() : base(System.Globalization.CultureInfo.InvariantCulture) { } + + /// + /// Abstract method to get the max line length + /// + public abstract int MaxLineLength { get; set; } + + /// + /// Method to write single line message with optional args, usually + /// written to precede the general failure message. + /// + /// The message to be written + /// Any arguments used in formatting the message + public void WriteMessageLine(string message, params object[] args) + { + WriteMessageLine(0, message, args); + } + + /// + /// Method to write single line message with optional args, usually + /// written to precede the general failure message, at a given + /// indentation level. + /// + /// The indentation level of the message + /// The message to be written + /// Any arguments used in formatting the message + public abstract void WriteMessageLine(int level, string message, params object[] args); + + /// + /// Display Expected and Actual lines for a constraint. This + /// is called by MessageWriter's default implementation of + /// WriteMessageTo and provides the generic two-line display. + /// + /// The constraint that failed + public abstract void DisplayDifferences(Constraint constraint); + + /// + /// Display Expected and Actual lines for given values. This + /// method may be called by constraints that need more control over + /// the display of actual and expected values than is provided + /// by the default implementation. + /// + /// The expected value + /// The actual value causing the failure + public abstract void DisplayDifferences(object expected, object actual); + + /// + /// Display Expected and Actual lines for given values, including + /// a tolerance value on the Expected line. + /// + /// The expected value + /// The actual value causing the failure + /// The tolerance within which the test was made + public abstract void DisplayDifferences(object expected, object actual, Tolerance tolerance); + + /// + /// Display the expected and actual string values on separate lines. + /// If the mismatch parameter is >=0, an additional line is displayed + /// line containing a caret that points to the mismatch point. + /// + /// The expected string value + /// The actual string value + /// The point at which the strings don't match or -1 + /// If true, case is ignored in locating the point where the strings differ + /// If true, the strings should be clipped to fit the line + public abstract void DisplayStringDifferences(string expected, string actual, int mismatch, bool ignoreCase, bool clipping); + + /// + /// Writes the text for a connector. + /// + /// The connector. + public abstract void WriteConnector(string connector); + + /// + /// Writes the text for a predicate. + /// + /// The predicate. + public abstract void WritePredicate(string predicate); + + /// + /// Writes the text for an expected value. + /// + /// The expected value. + public abstract void WriteExpectedValue(object expected); + + /// + /// Writes the text for a modifier + /// + /// The modifier. + public abstract void WriteModifier(string modifier); + + /// + /// Writes the text for an actual value. + /// + /// The actual value. + public abstract void WriteActualValue(object actual); + + /// + /// Writes the text for a generalized value. + /// + /// The value. + public abstract void WriteValue(object val); + + /// + /// Writes the text for a collection value, + /// starting at a particular point, to a max length + /// + /// The collection containing elements to write. + /// The starting point of the elements to write + /// The maximum number of elements to write + public abstract void WriteCollectionElements(IEnumerable collection, int start, int max); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/MsgUtils.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/MsgUtils.cs new file mode 100644 index 00000000000..56177e53656 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/MsgUtils.cs @@ -0,0 +1,282 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Text; +using System.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// Static methods used in creating messages + /// + public class MsgUtils + { + /// + /// Static string used when strings are clipped + /// + private const string ELLIPSIS = "..."; + + /// + /// Returns the representation of a type as used in NUnitLite. + /// This is the same as Type.ToString() except for arrays, + /// which are displayed with their declared sizes. + /// + /// + /// + public static string GetTypeRepresentation(object obj) + { + Array array = obj as Array; + if (array == null) + return string.Format("<{0}>", obj.GetType()); + + StringBuilder sb = new StringBuilder(); + Type elementType = array.GetType(); + int nest = 0; + while (elementType.IsArray) + { + elementType = elementType.GetElementType(); + ++nest; + } + sb.Append(elementType.ToString()); + sb.Append('['); + for (int r = 0; r < array.Rank; r++) + { + if (r > 0) sb.Append(','); + sb.Append(array.GetLength(r)); + } + sb.Append(']'); + + while (--nest > 0) + sb.Append("[]"); + + return string.Format("<{0}>", sb.ToString()); + } + /// + /// Converts any control characters in a string + /// to their escaped representation. + /// + /// The string to be converted + /// The converted string + public static string EscapeControlChars(string s) + { + if (s != null) + { + StringBuilder sb = new StringBuilder(); + + foreach (char c in s) + { + switch (c) + { + //case '\'': + // sb.Append("\\\'"); + // break; + //case '\"': + // sb.Append("\\\""); + // break; + case '\\': + sb.Append("\\\\"); + break; + case '\0': + sb.Append("\\0"); + break; + case '\a': + sb.Append("\\a"); + break; + case '\b': + sb.Append("\\b"); + break; + case '\f': + sb.Append("\\f"); + break; + case '\n': + sb.Append("\\n"); + break; + case '\r': + sb.Append("\\r"); + break; + case '\t': + sb.Append("\\t"); + break; + case '\v': + sb.Append("\\v"); + break; + + case '\x0085': + case '\x2028': + case '\x2029': + sb.Append(string.Format("\\x{0:X4}", (int)c)); + break; + + default: + sb.Append(c); + break; + } + } + + s = sb.ToString(); + } + + return s; + } + + /// + /// Return the a string representation for a set of indices into an array + /// + /// Array of indices for which a string is needed + public static string GetArrayIndicesAsString(int[] indices) + { + StringBuilder sb = new StringBuilder(); + sb.Append('['); + for (int r = 0; r < indices.Length; r++) + { + if (r > 0) sb.Append(','); + sb.Append(indices[r].ToString()); + } + sb.Append(']'); + return sb.ToString(); + } + + /// + /// Get an array of indices representing the point in a enumerable, + /// collection or array corresponding to a single int index into the + /// collection. + /// + /// The collection to which the indices apply + /// Index in the collection + /// Array of indices + public static int[] GetArrayIndicesFromCollectionIndex(IEnumerable collection, int index) + { + Array array = collection as Array; + + int rank = array == null ? 1 : array.Rank; + int[] result = new int[rank]; + + for (int r = rank; --r > 0; ) + { + int l = array.GetLength(r); + result[r] = index % l; + index /= l; + } + + result[0] = index; + return result; + } + + /// + /// Clip a string to a given length, starting at a particular offset, returning the clipped + /// string with ellipses representing the removed parts + /// + /// The string to be clipped + /// The maximum permitted length of the result string + /// The point at which to start clipping + /// The clipped string + public static string ClipString(string s, int maxStringLength, int clipStart) + { + int clipLength = maxStringLength; + StringBuilder sb = new StringBuilder(); + + if (clipStart > 0) + { + clipLength -= ELLIPSIS.Length; + sb.Append(ELLIPSIS); + } + + if (s.Length - clipStart > clipLength) + { + clipLength -= ELLIPSIS.Length; + sb.Append(s.Substring(clipStart, clipLength)); + sb.Append(ELLIPSIS); + } + else if (clipStart > 0) + sb.Append(s.Substring(clipStart)); + else + sb.Append(s); + + return sb.ToString(); + } + + /// + /// Clip the expected and actual strings in a coordinated fashion, + /// so that they may be displayed together. + /// + /// + /// + /// + /// + public static void ClipExpectedAndActual(ref string expected, ref string actual, int maxDisplayLength, int mismatch) + { + // Case 1: Both strings fit on line + int maxStringLength = Math.Max(expected.Length, actual.Length); + if (maxStringLength <= maxDisplayLength) + return; + + // Case 2: Assume that the tail of each string fits on line + int clipLength = maxDisplayLength - ELLIPSIS.Length; + int clipStart = maxStringLength - clipLength; + + // Case 3: If it doesn't, center the mismatch position + if (clipStart > mismatch) + clipStart = Math.Max(0, mismatch - clipLength / 2); + + expected = ClipString(expected, maxDisplayLength, clipStart); + actual = ClipString(actual, maxDisplayLength, clipStart); + } + + /// + /// Shows the position two strings start to differ. Comparison + /// starts at the start index. + /// + /// The expected string + /// The actual string + /// The index in the strings at which comparison should start + /// Boolean indicating whether case should be ignored + /// -1 if no mismatch found, or the index where mismatch found + static public int FindMismatchPosition(string expected, string actual, int istart, bool ignoreCase) + { + int length = Math.Min(expected.Length, actual.Length); + + string s1 = ignoreCase ? expected.ToLower() : expected; + string s2 = ignoreCase ? actual.ToLower() : actual; + + for (int i = istart; i < length; i++) + { + if (s1[i] != s2[i]) + return i; + } + + // + // Strings have same content up to the length of the shorter string. + // Mismatch occurs because string lengths are different, so show + // that they start differing where the shortest string ends + // + if (expected.Length != actual.Length) + return length; + + // + // Same strings : We shouldn't get here + // + return -1; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NUnitComparer.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NUnitComparer.cs new file mode 100644 index 00000000000..b8987b2df62 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NUnitComparer.cs @@ -0,0 +1,80 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using System.Reflection; + +namespace NUnit.Framework.Constraints +{ + /// + /// NUnitComparer encapsulates NUnit's default behavior + /// in comparing two objects. + /// + public class NUnitComparer : IComparer + { + /// + /// Returns the default NUnitComparer. + /// + public static NUnitComparer Default + { + get { return new NUnitComparer(); } + } + + /// + /// Compares two objects + /// + /// + /// + /// + public int Compare(object x, object y) + { + if (x == null) + return y == null ? 0 : -1; + else if (y == null) + return +1; + + if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) + return Numerics.Compare(x, y); + + if (x is IComparable) + return ((IComparable)x).CompareTo(y); + + if (y is IComparable) + return -((IComparable)y).CompareTo(x); + + Type xType = x.GetType(); + Type yType = y.GetType(); + + MethodInfo method = xType.GetMethod("CompareTo", new Type[] { yType }); + if (method != null) + return (int)method.Invoke(x, new object[] { y }); + + method = yType.GetMethod("CompareTo", new Type[] { xType }); + if (method != null) + return -(int)method.Invoke(y, new object[] { x }); + + throw new ArgumentException("Neither value implements IComparable or IComparable"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NUnitEqualityComparer.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NUnitEqualityComparer.cs new file mode 100644 index 00000000000..2d1353da3c9 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NUnitEqualityComparer.cs @@ -0,0 +1,482 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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.Collections; +using System.Reflection; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// NUnitEqualityComparer encapsulates NUnit's handling of + /// equality tests between objects. + /// + public class NUnitEqualityComparer + { + #region Static and Instance Fields + + /// + /// If true, all string comparisons will ignore case + /// + private bool caseInsensitive; + + /// + /// If true, arrays will be treated as collections, allowing + /// those of different dimensions to be compared + /// + private bool compareAsCollection; + + /// + /// Comparison objects used in comparisons for some constraints. + /// + private EqualityAdapterList externalComparers = new EqualityAdapterList(); + + /// + /// List of points at which a failure occured. + /// + private FailurePointList failurePoints; + + /// + /// RecursionDetector used to check for recursion when + /// evaluating self-referencing enumerables. + /// + private RecursionDetector recursionDetector; + + private static readonly int BUFFER_SIZE = 4096; + + #endregion + + #region Properties + + /// + /// Returns the default NUnitEqualityComparer + /// + public static NUnitEqualityComparer Default + { + get { return new NUnitEqualityComparer(); } + } + /// + /// Gets and sets a flag indicating whether case should + /// be ignored in determining equality. + /// + public bool IgnoreCase + { + get { return caseInsensitive; } + set { caseInsensitive = value; } + } + + /// + /// Gets and sets a flag indicating that arrays should be + /// compared as collections, without regard to their shape. + /// + public bool CompareAsCollection + { + get { return compareAsCollection; } + set { compareAsCollection = value; } + } + + /// + /// Gets the list of external comparers to be used to + /// test for equality. They are applied to members of + /// collections, in place of NUnit's own logic. + /// +#if CLR_2_0 || CLR_4_0 + public IList ExternalComparers +#else + public IList ExternalComparers +#endif + { + get { return externalComparers; } + } + + /// + /// Gets the list of failure points for the last Match performed. + /// The list consists of objects to be interpreted by the caller. + /// This generally means that the caller may only make use of + /// objects it has placed on the list at a particular depthy. + /// +#if CLR_2_0 || CLR_4_0 + public IList FailurePoints +#else + public IList FailurePoints +#endif + { + get { return failurePoints; } + } + #endregion + + #region Public Methods + /// + /// Compares two objects for equality within a tolerance, setting + /// the tolerance to the actual tolerance used if an empty + /// tolerance is supplied. + /// + public bool AreEqual(object expected, object actual, ref Tolerance tolerance) + { + this.failurePoints = new FailurePointList(); + this.recursionDetector = new RecursionDetector(); + + return ObjectsEqual(expected, actual, ref tolerance); + } + + #endregion + + #region Helper Methods + + private bool ObjectsEqual(object expected, object actual, ref Tolerance tolerance) + { + if (expected == null && actual == null) + return true; + + if (expected == null || actual == null) + return false; + + if (object.ReferenceEquals(expected, actual)) + return true; + + Type xType = expected.GetType(); + Type yType = actual.GetType(); + + EqualityAdapter externalComparer = GetExternalComparer(expected, actual); + if (externalComparer != null) + return externalComparer.AreEqual(expected, actual); + + if (xType.IsArray && yType.IsArray && !compareAsCollection) + return ArraysEqual((Array)expected, (Array)actual, ref tolerance); + + if (expected is IDictionary && actual is IDictionary) + return DictionariesEqual((IDictionary)expected, (IDictionary)actual, ref tolerance); + + if (expected is IEnumerable && actual is IEnumerable && !(expected is string && actual is string)) + return EnumerablesEqual((IEnumerable)expected, (IEnumerable)actual, ref tolerance); + + if (expected is string && actual is string) + return StringsEqual((string)expected, (string)actual); + + if (expected is Stream && actual is Stream) + return StreamsEqual((Stream)expected, (Stream)actual); + + if (expected is DirectoryInfo && actual is DirectoryInfo) + return DirectoriesEqual((DirectoryInfo)expected, (DirectoryInfo)actual); + + if (Numerics.IsNumericType(expected) && Numerics.IsNumericType(actual)) + return Numerics.AreEqual(expected, actual, ref tolerance); + + if (tolerance != null && tolerance.Value is TimeSpan) + { + TimeSpan amount = (TimeSpan)tolerance.Value; + + if (expected is DateTime && actual is DateTime) + return ((DateTime)expected - (DateTime)actual).Duration() <= amount; + + if (expected is TimeSpan && actual is TimeSpan) + return ((TimeSpan)expected - (TimeSpan)actual).Duration() <= amount; + } + +#if (CLR_2_0 || CLR_4_0) && !NETCF + if (FirstImplementsIEquatableOfSecond(xType, yType)) + return InvokeFirstIEquatableEqualsSecond(expected, actual); + else if (FirstImplementsIEquatableOfSecond(yType, xType)) + return InvokeFirstIEquatableEqualsSecond(actual, expected); +#endif + + return expected.Equals(actual); + } + +#if (CLR_2_0 || CLR_4_0) && !NETCF + private static bool FirstImplementsIEquatableOfSecond(Type first, Type second) + { + Type[] equatableArguments = GetEquatableGenericArguments(first); + + foreach (var xEquatableArgument in equatableArguments) + if (xEquatableArgument.Equals(second)) + return true; + + return false; + } + + private static Type[] GetEquatableGenericArguments(Type type) + { + foreach (Type @interface in type.GetInterfaces()) + if (@interface.IsGenericType && @interface.GetGenericTypeDefinition().Equals(typeof(IEquatable<>))) + return @interface.GetGenericArguments(); + + return new Type[0]; + } + + private static bool InvokeFirstIEquatableEqualsSecond(object first, object second) + { + MethodInfo equals = typeof(IEquatable<>).MakeGenericType(second.GetType()).GetMethod("Equals"); + + return (bool)equals.Invoke(first, new object[] { second }); + } +#endif + + private EqualityAdapter GetExternalComparer(object x, object y) + { + foreach (EqualityAdapter adapter in externalComparers) + if (adapter.CanCompare(x, y)) + return adapter; + + return null; + } + + /// + /// Helper method to compare two arrays + /// + private bool ArraysEqual(Array expected, Array actual, ref Tolerance tolerance) + { + int rank = expected.Rank; + + if (rank != actual.Rank) + return false; + + for (int r = 1; r < rank; r++) + if (expected.GetLength(r) != actual.GetLength(r)) + return false; + + return EnumerablesEqual((IEnumerable)expected, (IEnumerable)actual, ref tolerance); + } + + private bool DictionariesEqual(IDictionary expected, IDictionary actual, ref Tolerance tolerance) + { + if (expected.Count != actual.Count) + return false; + + CollectionTally tally = new CollectionTally(this, expected.Keys); + if (!tally.TryRemove(actual.Keys) || tally.Count > 0) + return false; + + foreach (object key in expected.Keys) + if (!ObjectsEqual(expected[key], actual[key], ref tolerance)) + return false; + + return true; + } + + private bool StringsEqual(string expected, string actual) + { + string s1 = caseInsensitive ? expected.ToLower() : expected; + string s2 = caseInsensitive ? actual.ToLower() : actual; + + return s1.Equals(s2); + } + + private bool EnumerablesEqual(IEnumerable expected, IEnumerable actual, ref Tolerance tolerance) + { + if (recursionDetector.CheckRecursion(expected, actual)) + return false; + + IEnumerator expectedEnum = expected.GetEnumerator(); + IEnumerator actualEnum = actual.GetEnumerator(); + + int count; + for (count = 0; ; count++) + { + bool expectedHasData = expectedEnum.MoveNext(); + bool actualHasData = actualEnum.MoveNext(); + + if (!expectedHasData && !actualHasData) + return true; + + if (expectedHasData != actualHasData || + !ObjectsEqual(expectedEnum.Current, actualEnum.Current, ref tolerance)) + { + FailurePoint fp = new FailurePoint(); + fp.Position = count; + fp.ExpectedHasData = expectedHasData; + if (expectedHasData) + fp.ExpectedValue = expectedEnum.Current; + fp.ActualHasData = actualHasData; + if (actualHasData) + fp.ActualValue = actualEnum.Current; + failurePoints.Insert(0, fp); + return false; + } + } + } + + /// + /// Method to compare two DirectoryInfo objects + /// + /// first directory to compare + /// second directory to compare + /// true if equivalent, false if not + private static bool DirectoriesEqual(DirectoryInfo expected, DirectoryInfo actual) + { + // Do quick compares first + if (expected.Attributes != actual.Attributes || + expected.CreationTime != actual.CreationTime || + expected.LastAccessTime != actual.LastAccessTime) + { + return false; + } + + // TODO: Find a cleaner way to do this + return new SamePathConstraint(expected.FullName).Matches(actual.FullName); + } + + private bool StreamsEqual(Stream expected, Stream actual) + { + if (expected == actual) return true; + + if (!expected.CanRead) + throw new ArgumentException("Stream is not readable", "expected"); + if (!actual.CanRead) + throw new ArgumentException("Stream is not readable", "actual"); + if (!expected.CanSeek) + throw new ArgumentException("Stream is not seekable", "expected"); + if (!actual.CanSeek) + throw new ArgumentException("Stream is not seekable", "actual"); + + if (expected.Length != actual.Length) return false; + + byte[] bufferExpected = new byte[BUFFER_SIZE]; + byte[] bufferActual = new byte[BUFFER_SIZE]; + + BinaryReader binaryReaderExpected = new BinaryReader(expected); + BinaryReader binaryReaderActual = new BinaryReader(actual); + + long expectedPosition = expected.Position; + long actualPosition = actual.Position; + + try + { + binaryReaderExpected.BaseStream.Seek(0, SeekOrigin.Begin); + binaryReaderActual.BaseStream.Seek(0, SeekOrigin.Begin); + + for (long readByte = 0; readByte < expected.Length; readByte += BUFFER_SIZE) + { + binaryReaderExpected.Read(bufferExpected, 0, BUFFER_SIZE); + binaryReaderActual.Read(bufferActual, 0, BUFFER_SIZE); + + for (int count = 0; count < BUFFER_SIZE; ++count) + { + if (bufferExpected[count] != bufferActual[count]) + { + FailurePoint fp = new FailurePoint(); + fp.Position = (int)readByte + count; + failurePoints.Insert(0, fp); + return false; + } + } + } + } + finally + { + expected.Position = expectedPosition; + actual.Position = actualPosition; + } + + return true; + } + + #endregion + + #region Nested RecursionDetector class + + /// + /// RecursionDetector detects when a comparison + /// between two enumerables has reached a point + /// where the same objects that were previously + /// compared are again being compared. This allows + /// the caller to stop the comparison if desired. + /// + class RecursionDetector + { +#if CLR_2_0 || CLR_4_0 + readonly Dictionary table = new Dictionary(); +#else + readonly Hashtable table = new Hashtable(); +#endif + + /// + /// Check whether two objects have previously + /// been compared, returning true if they have. + /// The two objects are remembered, so that a + /// second call will always return true. + /// + public bool CheckRecursion(IEnumerable expected, IEnumerable actual) + { + UnorderedReferencePair pair = new UnorderedReferencePair(expected, actual); + + if (ContainsPair(pair)) + return true; + + table.Add(pair, null); + return false; + } + + private bool ContainsPair(UnorderedReferencePair pair) + { +#if CLR_2_0 || CLR_4_0 + return table.ContainsKey(pair); +#else + return table.Contains(pair); +#endif + } + +#if CLR_2_0 || CLR_4_0 + class UnorderedReferencePair : IEquatable +#else + class UnorderedReferencePair +#endif + { + private readonly object first; + private readonly object second; + + public UnorderedReferencePair(object first, object second) + { + this.first = first; + this.second = second; + } + + public bool Equals(UnorderedReferencePair other) + { + return (Equals(first, other.first) && Equals(second, other.second)) || + (Equals(first, other.second) && Equals(second, other.first)); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is UnorderedReferencePair && Equals((UnorderedReferencePair)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((first != null ? first.GetHashCode() : 0) * 397) ^ ((second != null ? second.GetHashCode() : 0) * 397); + } + } + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NaNConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NaNConstraint.cs new file mode 100644 index 00000000000..5e28046c02e --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NaNConstraint.cs @@ -0,0 +1,52 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// NaNConstraint tests that the actual value is a double or float NaN + /// + public class NaNConstraint : Constraint + { + /// + /// Test that the actual value is an NaN + /// + /// + /// + public override bool Matches(object actual) + { + this.actual = actual; + return actual is double && double.IsNaN((double)actual) + || actual is float && float.IsNaN((float)actual); + } + + /// + /// Write the constraint description to a specified writer + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write("NaN"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NoItemConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NoItemConstraint.cs new file mode 100644 index 00000000000..75841300551 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NoItemConstraint.cs @@ -0,0 +1,75 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// NoItemConstraint applies another constraint to each + /// item in a collection, failing if any of them succeeds. + /// + public class NoItemConstraint : PrefixConstraint + { + /// + /// Construct a NoItemConstraint on top of an existing constraint + /// + /// + public NoItemConstraint(Constraint itemConstraint) + : base(itemConstraint) + { + this.DisplayName = "none"; + } + + /// + /// Apply the item constraint to each item in the collection, + /// failing if any item fails. + /// + /// + /// + public override bool Matches(object actual) + { + this.actual = actual; + + if (!(actual is IEnumerable)) + throw new ArgumentException("The actual value must be an IEnumerable", "actual"); + + foreach (object item in (IEnumerable)actual) + if (baseConstraint.Matches(item)) + return false; + + return true; + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("no item"); + baseConstraint.WriteDescriptionTo(writer); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NotConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NotConstraint.cs new file mode 100644 index 00000000000..a81fe3ac21f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NotConstraint.cs @@ -0,0 +1,68 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// NotConstraint negates the effect of some other constraint + /// + public class NotConstraint : PrefixConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The base constraint to be negated. + public NotConstraint(Constraint baseConstraint) + : base(baseConstraint) { } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for if the base constraint fails, false if it succeeds + public override bool Matches(object actual) + { + this.actual = actual; + return !baseConstraint.Matches(actual); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("not"); + baseConstraint.WriteDescriptionTo(writer); + } + + /// + /// Write the actual value for a failing constraint test to a MessageWriter. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + baseConstraint.WriteActualValueTo(writer); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NullConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NullConstraint.cs new file mode 100644 index 00000000000..9ffb55a6347 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NullConstraint.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// NullConstraint tests that the actual value is null + /// + public class NullConstraint : BasicConstraint + { + /// + /// Initializes a new instance of the class. + /// + public NullConstraint() : base(null, "null") { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NullOrEmptyStringConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NullOrEmptyStringConstraint.cs new file mode 100644 index 00000000000..ef2f3c933b7 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/NullOrEmptyStringConstraint.cs @@ -0,0 +1,72 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// NullEmptyStringConstraint tests whether a string is either null or empty. + /// + public class NullOrEmptyStringConstraint : Constraint + { + /// + /// Constructs a new NullOrEmptyStringConstraint + /// + public NullOrEmptyStringConstraint() + { + this.DisplayName = "nullorempty"; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + // NOTE: Do not change this to use string.IsNullOrEmpty + // since that won't work in earlier versions of .NET + + this.actual = actual; + + if (actual == null) return true; + + string actualAsString = actual as string; + + if (actualAsString == null) + throw new ArgumentException("Actual value must be a string", "actual"); + + return actualAsString == string.Empty; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write("null or empty string"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Numerics.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Numerics.cs new file mode 100644 index 00000000000..0721cea7084 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Numerics.cs @@ -0,0 +1,380 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// The Numerics class contains common operations on numeric values. + /// + public class Numerics + { + #region Numeric Type Recognition + /// + /// Checks the type of the object, returning true if + /// the object is a numeric type. + /// + /// The object to check + /// true if the object is a numeric type + public static bool IsNumericType(Object obj) + { + return IsFloatingPointNumeric(obj) || IsFixedPointNumeric(obj); + } + + /// + /// Checks the type of the object, returning true if + /// the object is a floating point numeric type. + /// + /// The object to check + /// true if the object is a floating point numeric type + public static bool IsFloatingPointNumeric(Object obj) + { + if (null != obj) + { + if (obj is System.Double) return true; + if (obj is System.Single) return true; + } + return false; + } + /// + /// Checks the type of the object, returning true if + /// the object is a fixed point numeric type. + /// + /// The object to check + /// true if the object is a fixed point numeric type + public static bool IsFixedPointNumeric(Object obj) + { + if (null != obj) + { + if (obj is System.Byte) return true; + if (obj is System.SByte) return true; + if (obj is System.Decimal) return true; + if (obj is System.Int32) return true; + if (obj is System.UInt32) return true; + if (obj is System.Int64) return true; + if (obj is System.UInt64) return true; + if (obj is System.Int16) return true; + if (obj is System.UInt16) return true; + } + return false; + } + #endregion + + #region Numeric Equality + /// + /// Test two numeric values for equality, performing the usual numeric + /// conversions and using a provided or default tolerance. If the tolerance + /// provided is Empty, this method may set it to a default tolerance. + /// + /// The expected value + /// The actual value + /// A reference to the tolerance in effect + /// True if the values are equal + public static bool AreEqual(object expected, object actual, ref Tolerance tolerance) + { + if (expected is double || actual is double) + return AreEqual(Convert.ToDouble(expected), Convert.ToDouble(actual), ref tolerance); + + if (expected is float || actual is float) + return AreEqual(Convert.ToSingle(expected), Convert.ToSingle(actual), ref tolerance); + + if (tolerance.Mode == ToleranceMode.Ulps) + throw new InvalidOperationException("Ulps may only be specified for floating point arguments"); + + if (expected is decimal || actual is decimal) + return AreEqual(Convert.ToDecimal(expected), Convert.ToDecimal(actual), tolerance); + + if (expected is ulong || actual is ulong) + return AreEqual(Convert.ToUInt64(expected), Convert.ToUInt64(actual), tolerance); + + if (expected is long || actual is long) + return AreEqual(Convert.ToInt64(expected), Convert.ToInt64(actual), tolerance); + + if (expected is uint || actual is uint) + return AreEqual(Convert.ToUInt32(expected), Convert.ToUInt32(actual), tolerance); + + return AreEqual(Convert.ToInt32(expected), Convert.ToInt32(actual), tolerance); + } + + private static bool AreEqual(double expected, double actual, ref Tolerance tolerance) + { + if (double.IsNaN(expected) && double.IsNaN(actual)) + return true; + + // Handle infinity specially since subtracting two infinite values gives + // NaN and the following test fails. mono also needs NaN to be handled + // specially although ms.net could use either method. Also, handle + // situation where no tolerance is used. + if (double.IsInfinity(expected) || double.IsNaN(expected) || double.IsNaN(actual)) + { + return expected.Equals(actual); + } + + if (tolerance.IsEmpty && GlobalSettings.DefaultFloatingPointTolerance > 0.0d) + tolerance = new Tolerance(GlobalSettings.DefaultFloatingPointTolerance); + + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + return Math.Abs(expected - actual) <= Convert.ToDouble(tolerance.Value); + + case ToleranceMode.Percent: + if (expected == 0.0) + return expected.Equals(actual); + + double relativeError = Math.Abs((expected - actual) / expected); + return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); + + case ToleranceMode.Ulps: + return FloatingPointNumerics.AreAlmostEqualUlps( + expected, actual, Convert.ToInt64(tolerance.Value)); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + + private static bool AreEqual(float expected, float actual, ref Tolerance tolerance) + { + if (float.IsNaN(expected) && float.IsNaN(actual)) + return true; + + // handle infinity specially since subtracting two infinite values gives + // NaN and the following test fails. mono also needs NaN to be handled + // specially although ms.net could use either method. + if (float.IsInfinity(expected) || float.IsNaN(expected) || float.IsNaN(actual)) + { + return expected.Equals(actual); + } + + if (tolerance.IsEmpty && GlobalSettings.DefaultFloatingPointTolerance > 0.0d) + tolerance = new Tolerance(GlobalSettings.DefaultFloatingPointTolerance); + + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + return Math.Abs(expected - actual) <= Convert.ToDouble(tolerance.Value); + + case ToleranceMode.Percent: + if (expected == 0.0f) + return expected.Equals(actual); + float relativeError = Math.Abs((expected - actual) / expected); + return (relativeError <= Convert.ToSingle(tolerance.Value) / 100.0f); + + case ToleranceMode.Ulps: + return FloatingPointNumerics.AreAlmostEqualUlps( + expected, actual, Convert.ToInt32(tolerance.Value)); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + + + private static bool AreEqual(decimal expected, decimal actual, Tolerance tolerance) + { + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + decimal decimalTolerance = Convert.ToDecimal(tolerance.Value); + if (decimalTolerance > 0m) + return Math.Abs(expected - actual) <= decimalTolerance; + + return expected.Equals(actual); + + case ToleranceMode.Percent: + if (expected == 0m) + return expected.Equals(actual); + + double relativeError = Math.Abs( + (double)(expected - actual) / (double)expected); + return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + + private static bool AreEqual(ulong expected, ulong actual, Tolerance tolerance) + { + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + ulong ulongTolerance = Convert.ToUInt64(tolerance.Value); + if (ulongTolerance > 0ul) + { + ulong diff = expected >= actual ? expected - actual : actual - expected; + return diff <= ulongTolerance; + } + + return expected.Equals(actual); + + case ToleranceMode.Percent: + if (expected == 0ul) + return expected.Equals(actual); + + // Can't do a simple Math.Abs() here since it's unsigned + ulong difference = Math.Max(expected, actual) - Math.Min(expected, actual); + double relativeError = Math.Abs((double)difference / (double)expected); + return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + + private static bool AreEqual(long expected, long actual, Tolerance tolerance) + { + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + long longTolerance = Convert.ToInt64(tolerance.Value); + if (longTolerance > 0L) + return Math.Abs(expected - actual) <= longTolerance; + + return expected.Equals(actual); + + case ToleranceMode.Percent: + if (expected == 0L) + return expected.Equals(actual); + + double relativeError = Math.Abs( + (double)(expected - actual) / (double)expected); + return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + + private static bool AreEqual(uint expected, uint actual, Tolerance tolerance) + { + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + uint uintTolerance = Convert.ToUInt32(tolerance.Value); + if (uintTolerance > 0) + { + uint diff = expected >= actual ? expected - actual : actual - expected; + return diff <= uintTolerance; + } + + return expected.Equals(actual); + + case ToleranceMode.Percent: + if (expected == 0u) + return expected.Equals(actual); + + // Can't do a simple Math.Abs() here since it's unsigned + uint difference = Math.Max(expected, actual) - Math.Min(expected, actual); + double relativeError = Math.Abs((double)difference / (double)expected); + return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + + private static bool AreEqual(int expected, int actual, Tolerance tolerance) + { + switch (tolerance.Mode) + { + case ToleranceMode.None: + return expected.Equals(actual); + + case ToleranceMode.Linear: + int intTolerance = Convert.ToInt32(tolerance.Value); + if (intTolerance > 0) + return Math.Abs(expected - actual) <= intTolerance; + + return expected.Equals(actual); + + case ToleranceMode.Percent: + if (expected == 0) + return expected.Equals(actual); + + double relativeError = Math.Abs( + (double)(expected - actual) / (double)expected); + return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); + + default: + throw new ArgumentException("Unknown tolerance mode specified", "mode"); + } + } + #endregion + + #region Numeric Comparisons + /// + /// Compare two numeric values, performing the usual numeric conversions. + /// + /// The expected value + /// The actual value + /// The relationship of the values to each other + public static int Compare(object expected, object actual) + { + if (!IsNumericType(expected) || !IsNumericType(actual)) + throw new ArgumentException("Both arguments must be numeric"); + + if (IsFloatingPointNumeric(expected) || IsFloatingPointNumeric(actual)) + return Convert.ToDouble(expected).CompareTo(Convert.ToDouble(actual)); + + if (expected is decimal || actual is decimal) + return Convert.ToDecimal(expected).CompareTo(Convert.ToDecimal(actual)); + + if (expected is ulong || actual is ulong) + return Convert.ToUInt64(expected).CompareTo(Convert.ToUInt64(actual)); + + if (expected is long || actual is long) + return Convert.ToInt64(expected).CompareTo(Convert.ToInt64(actual)); + + if (expected is uint || actual is uint) + return Convert.ToUInt32(expected).CompareTo(Convert.ToUInt32(actual)); + + return Convert.ToInt32(expected).CompareTo(Convert.ToInt32(actual)); + } + #endregion + + private Numerics() + { + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AllOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AllOperator.cs new file mode 100644 index 00000000000..e53923b0434 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AllOperator.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Represents a constraint that succeeds if all the + /// members of a collection match a base constraint. + /// + public class AllOperator : CollectionOperator + { + /// + /// Returns a constraint that will apply the argument + /// to the members of a collection, succeeding if + /// they all succeed. + /// + public override Constraint ApplyPrefix(Constraint constraint) + { + return new AllItemsConstraint(constraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AndOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AndOperator.cs new file mode 100644 index 00000000000..3b77643fd6f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AndOperator.cs @@ -0,0 +1,47 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Operator that requires both it's arguments to succeed + /// + public class AndOperator : BinaryOperator + { + /// + /// Construct an AndOperator + /// + public AndOperator() + { + this.left_precedence = this.right_precedence = 2; + } + + /// + /// Apply the operator to produce an AndConstraint + /// + public override Constraint ApplyOperator(Constraint left, Constraint right) + { + return new AndConstraint(left, right); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AttributeOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AttributeOperator.cs new file mode 100644 index 00000000000..b8c3be952e4 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/AttributeOperator.cs @@ -0,0 +1,62 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// Operator that tests for the presence of a particular attribute + /// on a type and optionally applies further tests to the attribute. + /// + public class AttributeOperator : SelfResolvingOperator + { + private readonly Type type; + + /// + /// Construct an AttributeOperator for a particular Type + /// + /// The Type of attribute tested + public AttributeOperator(Type type) + { + this.type = type; + + // Attribute stacks on anything and allows only + // prefix operators to stack on it. + this.left_precedence = this.right_precedence = 1; + } + + /// + /// Reduce produces a constraint from the operator and + /// any arguments. It takes the arguments from the constraint + /// stack and pushes the resulting constraint on it. + /// + public override void Reduce(ConstraintBuilder.ConstraintStack stack) + { + if (RightContext == null || RightContext is BinaryOperator) + stack.Push(new AttributeExistsConstraint(type)); + else + stack.Push(new AttributeConstraint(type, stack.Pop())); + } + } + } diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/BinaryOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/BinaryOperator.cs new file mode 100644 index 00000000000..8b1481439e5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/BinaryOperator.cs @@ -0,0 +1,76 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Abstract base class for all binary operators + /// + public abstract class BinaryOperator : ConstraintOperator + { + /// + /// Reduce produces a constraint from the operator and + /// any arguments. It takes the arguments from the constraint + /// stack and pushes the resulting constraint on it. + /// + /// + public override void Reduce(ConstraintBuilder.ConstraintStack stack) + { + Constraint right = stack.Pop(); + Constraint left = stack.Pop(); + stack.Push(ApplyOperator(left, right)); + } + + /// + /// Gets the left precedence of the operator + /// + public override int LeftPrecedence + { + get + { + return RightContext is CollectionOperator + ? base.LeftPrecedence + 10 + : base.LeftPrecedence; + } + } + + /// + /// Gets the right precedence of the operator + /// + public override int RightPrecedence + { + get + { + return RightContext is CollectionOperator + ? base.RightPrecedence + 10 + : base.RightPrecedence; + } + } + + /// + /// Abstract method that produces a constraint by applying + /// the operator to its left and right constraint arguments. + /// + public abstract Constraint ApplyOperator(Constraint left, Constraint right); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/CollectionOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/CollectionOperator.cs new file mode 100644 index 00000000000..a15798f2d25 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/CollectionOperator.cs @@ -0,0 +1,43 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Abstract base for operators that indicate how to + /// apply a constraint to items in a collection. + /// + public abstract class CollectionOperator : PrefixOperator + { + /// + /// Constructs a CollectionOperator + /// + protected CollectionOperator() + { + // Collection Operators stack on everything + // and allow all other ops to stack on them + this.left_precedence = 1; + this.right_precedence = 10; + } + } + } diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ConstraintOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ConstraintOperator.cs new file mode 100644 index 00000000000..a33bfdaae3b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ConstraintOperator.cs @@ -0,0 +1,96 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// The ConstraintOperator class is used internally by a + /// ConstraintBuilder to represent an operator that + /// modifies or combines constraints. + /// + /// Constraint operators use left and right precedence + /// values to determine whether the top operator on the + /// stack should be reduced before pushing a new operator. + /// + public abstract class ConstraintOperator + { + private object leftContext; + private object rightContext; + + /// + /// The precedence value used when the operator + /// is about to be pushed to the stack. + /// + protected int left_precedence; + + /// + /// The precedence value used when the operator + /// is on the top of the stack. + /// + protected int right_precedence; + + /// + /// The syntax element preceding this operator + /// + public object LeftContext + { + get { return leftContext; } + set { leftContext = value; } + } + + /// + /// The syntax element folowing this operator + /// + public object RightContext + { + get { return rightContext; } + set { rightContext = value; } + } + + /// + /// The precedence value used when the operator + /// is about to be pushed to the stack. + /// + public virtual int LeftPrecedence + { + get { return left_precedence; } + } + + /// + /// The precedence value used when the operator + /// is on the top of the stack. + /// + public virtual int RightPrecedence + { + get { return right_precedence; } + } + + /// + /// Reduce produces a constraint from the operator and + /// any arguments. It takes the arguments from the constraint + /// stack and pushes the resulting constraint on it. + /// + /// + public abstract void Reduce(ConstraintBuilder.ConstraintStack stack); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ExactCountOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ExactCountOperator.cs new file mode 100644 index 00000000000..1763d493125 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ExactCountOperator.cs @@ -0,0 +1,54 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Represents a constraint that succeeds if the specified + /// count of members of a collection match a base constraint. + /// + public class ExactCountOperator : CollectionOperator + { + private int expectedCount; + + /// + /// Construct an ExactCountOperator for a specified count + /// + /// The expected count + public ExactCountOperator(int expectedCount) + { + this.expectedCount = expectedCount; + } + + /// + /// Returns a constraint that will apply the argument + /// to the members of a collection, succeeding if + /// none of them succeed. + /// + public override Constraint ApplyPrefix(Constraint constraint) + { + return new ExactCountConstraint(expectedCount, constraint); + } + } +} + diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/NoneOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/NoneOperator.cs new file mode 100644 index 00000000000..3d9fde34c53 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/NoneOperator.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Represents a constraint that succeeds if none of the + /// members of a collection match a base constraint. + /// + public class NoneOperator : CollectionOperator + { + /// + /// Returns a constraint that will apply the argument + /// to the members of a collection, succeeding if + /// none of them succeed. + /// + public override Constraint ApplyPrefix(Constraint constraint) + { + return new NoItemConstraint(constraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/NotOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/NotOperator.cs new file mode 100644 index 00000000000..bde6e57f4ce --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/NotOperator.cs @@ -0,0 +1,49 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Negates the test of the constraint it wraps. + /// + public class NotOperator : PrefixOperator + { + /// + /// Constructs a new NotOperator + /// + public NotOperator() + { + // Not stacks on anything and only allows other + // prefix ops to stack on top of it. + this.left_precedence = this.right_precedence = 1; + } + + /// + /// Returns a NotConstraint applied to its argument. + /// + public override Constraint ApplyPrefix(Constraint constraint) + { + return new NotConstraint(constraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/OrOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/OrOperator.cs new file mode 100644 index 00000000000..a3c66542615 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/OrOperator.cs @@ -0,0 +1,47 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Operator that requires at least one of it's arguments to succeed + /// + public class OrOperator : BinaryOperator + { + /// + /// Construct an OrOperator + /// + public OrOperator() + { + this.left_precedence = this.right_precedence = 3; + } + + /// + /// Apply the operator to produce an OrConstraint + /// + public override Constraint ApplyOperator(Constraint left, Constraint right) + { + return new OrConstraint(left, right); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/PrefixOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/PrefixOperator.cs new file mode 100644 index 00000000000..1066f58f66e --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/PrefixOperator.cs @@ -0,0 +1,51 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// PrefixOperator takes a single constraint and modifies + /// it's action in some way. + /// + public abstract class PrefixOperator : ConstraintOperator + { + /// + /// Reduce produces a constraint from the operator and + /// any arguments. It takes the arguments from the constraint + /// stack and pushes the resulting constraint on it. + /// + /// + public override void Reduce(ConstraintBuilder.ConstraintStack stack) + { + stack.Push(ApplyPrefix(stack.Pop())); + } + + /// + /// Returns the constraint created by applying this + /// prefix to another constraint. + /// + /// + /// + public abstract Constraint ApplyPrefix(Constraint constraint); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/PropOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/PropOperator.cs new file mode 100644 index 00000000000..f60b61e2bcb --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/PropOperator.cs @@ -0,0 +1,69 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Operator used to test for the presence of a named Property + /// on an object and optionally apply further tests to the + /// value of that property. + /// + public class PropOperator : SelfResolvingOperator + { + private readonly string name; + + /// + /// Gets the name of the property to which the operator applies + /// + public string Name + { + get { return name; } + } + + /// + /// Constructs a PropOperator for a particular named property + /// + public PropOperator(string name) + { + this.name = name; + + // Prop stacks on anything and allows only + // prefix operators to stack on it. + this.left_precedence = this.right_precedence = 1; + } + + /// + /// Reduce produces a constraint from the operator and + /// any arguments. It takes the arguments from the constraint + /// stack and pushes the resulting constraint on it. + /// + /// + public override void Reduce(ConstraintBuilder.ConstraintStack stack) + { + if (RightContext == null || RightContext is BinaryOperator) + stack.Push(new PropertyExistsConstraint(name)); + else + stack.Push(new PropertyConstraint(name, stack.Pop())); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/SelfResolvingOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/SelfResolvingOperator.cs new file mode 100644 index 00000000000..5fb6177a428 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/SelfResolvingOperator.cs @@ -0,0 +1,33 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Abstract base class for operators that are able to reduce to a + /// constraint whether or not another syntactic element follows. + /// + public abstract class SelfResolvingOperator : ConstraintOperator + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/SomeOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/SomeOperator.cs new file mode 100644 index 00000000000..0dcbddd0a5a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/SomeOperator.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Represents a constraint that succeeds if any of the + /// members of a collection match a base constraint. + /// + public class SomeOperator : CollectionOperator + { + /// + /// Returns a constraint that will apply the argument + /// to the members of a collection, succeeding if + /// any of them succeed. + /// + public override Constraint ApplyPrefix(Constraint constraint) + { + return new SomeItemsConstraint(constraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ThrowsOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ThrowsOperator.cs new file mode 100644 index 00000000000..34500b1db21 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/ThrowsOperator.cs @@ -0,0 +1,57 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Operator that tests that an exception is thrown and + /// optionally applies further tests to the exception. + /// + public class ThrowsOperator : SelfResolvingOperator + { + /// + /// Construct a ThrowsOperator + /// + public ThrowsOperator() + { + // ThrowsOperator stacks on everything but + // it's always the first item on the stack + // anyway. It is evaluated last of all ops. + this.left_precedence = 1; + this.right_precedence = 100; + } + + /// + /// Reduce produces a constraint from the operator and + /// any arguments. It takes the arguments from the constraint + /// stack and pushes the resulting constraint on it. + /// + public override void Reduce(ConstraintBuilder.ConstraintStack stack) + { + if (RightContext == null || RightContext is BinaryOperator) + stack.Push(new ThrowsConstraint(null)); + else + stack.Push(new ThrowsConstraint(stack.Pop())); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/WithOperator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/WithOperator.cs new file mode 100644 index 00000000000..76962676ecc --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Operators/WithOperator.cs @@ -0,0 +1,51 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Represents a constraint that simply wraps the + /// constraint provided as an argument, without any + /// further functionality, but which modifes the + /// order of evaluation because of its precedence. + /// + public class WithOperator : PrefixOperator + { + /// + /// Constructor for the WithOperator + /// + public WithOperator() + { + this.left_precedence = 1; + this.right_precedence = 4; + } + + /// + /// Returns a constraint that wraps its argument + /// + public override Constraint ApplyPrefix(Constraint constraint) + { + return constraint; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/OrConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/OrConstraint.cs new file mode 100644 index 00000000000..11b01f44dea --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/OrConstraint.cs @@ -0,0 +1,61 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. + +namespace NUnit.Framework.Constraints +{ + /// + /// OrConstraint succeeds if either member succeeds + /// + public class OrConstraint : BinaryConstraint + { + /// + /// Create an OrConstraint from two other constraints + /// + /// The first constraint + /// The second constraint + public OrConstraint(Constraint left, Constraint right) : base(left, right) { } + + /// + /// Apply the member constraints to an actual value, succeeding + /// succeeding as soon as one of them succeeds. + /// + /// The actual value + /// True if either constraint succeeded + public override bool Matches(object actual) + { + this.actual = actual; + + return left.Matches(actual) || right.Matches(actual); + } + + /// + /// Write a description for this contraint to a MessageWriter + /// + /// The MessageWriter to receive the description + public override void WriteDescriptionTo(MessageWriter writer) + { + left.WriteDescriptionTo(writer); + writer.WriteConnector("or"); + right.WriteDescriptionTo(writer); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PathConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PathConstraint.cs new file mode 100644 index 00000000000..7c27fa5ef83 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PathConstraint.cs @@ -0,0 +1,181 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework.Constraints +{ + /// + /// PathConstraint serves as the abstract base of constraints + /// that operate on paths and provides several helper methods. + /// + public abstract class PathConstraint : Constraint + { + private static readonly char[] DirectorySeparatorChars = new char[] { '\\', '/' }; + + /// + /// The expected path used in the constraint + /// + protected string expectedPath; + + /// + /// Flag indicating whether a caseInsensitive comparison should be made + /// + protected bool caseInsensitive = Path.DirectorySeparatorChar == '\\'; + + /// + /// Construct a PathConstraint for a give expected path + /// + /// The expected path + protected PathConstraint(string expectedPath) : base(expectedPath) + { + this.expectedPath = expectedPath; + } + + /// + /// Modifies the current instance to be case-insensitve + /// and returns it. + /// + public PathConstraint IgnoreCase + { + get { caseInsensitive = true; return this; } + } + + /// + /// Modifies the current instance to be case-sensitve + /// and returns it. + /// + public PathConstraint RespectCase + { + get { caseInsensitive = false; return this; } + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + string actualPath = actual as string; + + return actualPath != null && IsMatch(expectedPath, actualPath); + } + + /// + /// Returns true if the expected path and actual path match + /// + protected abstract bool IsMatch(string expectedPath, string actualPath); + + /// + /// Returns the string representation of this constraint + /// + protected override string GetStringRepresentation() + { + return string.Format("<{0} \"{1}\" {2}>", DisplayName, expectedPath, caseInsensitive ? "ignorecase" : "respectcase"); + } + + #region Static Helper Methods + + /// + /// Transform the provided path to its canonical form so that it + /// may be more easily be compared with other paths. + /// + /// The original path + /// The path in canonical form + protected static string Canonicalize(string path) + { + if (Path.DirectorySeparatorChar != Path.AltDirectorySeparatorChar) + path = path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + string leadingSeparators = ""; + foreach (char c in path) + { + if (c == Path.DirectorySeparatorChar) + leadingSeparators += c; + else break; + } + +#if (CLR_2_0 || CLR_4_0) && !NETCF + string[] parts = path.Split(DirectorySeparatorChars, StringSplitOptions.RemoveEmptyEntries); +#else + string[] parts = path.Split(DirectorySeparatorChars); +#endif + int count = 0; + bool shifting = false; + foreach (string part in parts) + { + switch (part) + { + case "": + case ".": + shifting = true; + break; + + case "..": + shifting = true; + if (count > 0) + --count; + break; + + default: + if (shifting) + parts[count] = part; + ++count; + break; + } + } + + return leadingSeparators + String.Join(Path.DirectorySeparatorChar.ToString(), parts, 0, count); + } + + /// + /// Test whether one path in canonical form is under another. + /// + /// The first path - supposed to be the parent path + /// The second path - supposed to be the child path + /// Indicates whether case should be ignored + /// + protected static bool IsSubPath(string path1, string path2, bool ignoreCase) + { + int length1 = path1.Length; + int length2 = path2.Length; + + // if path1 is longer or equal, then path2 can't be under it + if (length1 >= length2) + return false; + + // path 2 is longer than path 1: see if initial parts match + if (!StringUtil.StringsEqual(path1, path2.Substring(0, length1), ignoreCase)) + return false; + + // must match through or up to a directory separator boundary + return path2[length1 - 1] == Path.DirectorySeparatorChar || + length2 > length1 && path2[length1] == Path.DirectorySeparatorChar; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PredicateConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PredicateConstraint.cs new file mode 100644 index 00000000000..5d76bf3da5f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PredicateConstraint.cs @@ -0,0 +1,76 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +#if CLR_2_0 || CLR_4_0 +using System; +using System.Collections.Generic; + +namespace NUnit.Framework.Constraints +{ + /// + /// Predicate constraint wraps a Predicate in a constraint, + /// returning success if the predicate is true. + /// + public class PredicateConstraint : Constraint + { + readonly Predicate predicate; + + /// + /// Construct a PredicateConstraint from a predicate + /// + public PredicateConstraint(Predicate predicate) + { + this.predicate = predicate; + } + + /// + /// Determines whether the predicate succeeds when applied + /// to the actual value. + /// + public override bool Matches(object actual) + { + this.actual = actual; + + if (!(actual is T)) + throw new ArgumentException("The actual value is not of type " + typeof(T).Name, "actual"); + + return predicate((T)actual); + } + + /// + /// Writes the description to a MessageWriter + /// + public override void WriteDescriptionTo(MessageWriter writer) + { +#if NETCF_2_0 + writer.Write("value matching predicate"); +#else + writer.WritePredicate("value matching"); + writer.Write(predicate.Method.Name.StartsWith("<") + ? "lambda expression" + : predicate.Method.Name); +#endif + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PrefixConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PrefixConstraint.cs new file mode 100644 index 00000000000..b4592272d2b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PrefixConstraint.cs @@ -0,0 +1,46 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Abstract base class used for prefixes + /// + public abstract class PrefixConstraint : Constraint + { + /// + /// The base constraint + /// + protected Constraint baseConstraint; + + /// + /// Construct given a base constraint + /// + /// + protected PrefixConstraint(IResolveConstraint resolvable) : base(resolvable) + { + if (resolvable != null) + this.baseConstraint = resolvable.Resolve(); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PropertyConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PropertyConstraint.cs new file mode 100644 index 00000000000..f1f43dd8aec --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PropertyConstraint.cs @@ -0,0 +1,110 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Reflection; + +namespace NUnit.Framework.Constraints +{ + /// + /// PropertyConstraint extracts a named property and uses + /// its value as the actual value for a chained constraint. + /// + public class PropertyConstraint : PrefixConstraint + { + private readonly string name; + private object propValue; + + /// + /// Initializes a new instance of the class. + /// + /// The name. + /// The constraint to apply to the property. + public PropertyConstraint(string name, Constraint baseConstraint) + : base(baseConstraint) + { + this.name = name; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + Guard.ArgumentNotNull(actual, "actual"); + + Type actualType = actual as Type; + if (actualType == null) + actualType = actual.GetType(); + + PropertyInfo property = actualType.GetProperty(name, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty); + + if (property == null) + throw new ArgumentException(string.Format("Property {0} was not found", name), "name"); + + propValue = property.GetValue(actual, null); + return baseConstraint.Matches(propValue); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("property " + name); + if (baseConstraint != null) + { + if (baseConstraint is EqualConstraint) + writer.WritePredicate("equal to"); + baseConstraint.WriteDescriptionTo(writer); + } + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(propValue); + } + + /// + /// Returns the string representation of the constraint. + /// + /// + protected override string GetStringRepresentation() + { + return string.Format("", name, baseConstraint); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PropertyExistsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PropertyExistsConstraint.cs new file mode 100644 index 00000000000..db22309d198 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/PropertyExistsConstraint.cs @@ -0,0 +1,102 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Reflection; + +namespace NUnit.Framework.Constraints +{ + /// + /// PropertyExistsConstraint tests that a named property + /// exists on the object provided through Match. + /// + /// Originally, PropertyConstraint provided this feature + /// in addition to making optional tests on the vaue + /// of the property. The two constraints are now separate. + /// + public class PropertyExistsConstraint : Constraint + { + private readonly string name; + + Type actualType; + + /// + /// Initializes a new instance of the class. + /// + /// The name of the property. + public PropertyExistsConstraint(string name) + : base(name) + { + this.name = name; + } + + /// + /// Test whether the property exists for a given object + /// + /// The object to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + Guard.ArgumentNotNull(actual, "actual"); + + this.actualType = actual as Type; + if (actualType == null) + actualType = actual.GetType(); + + PropertyInfo property = actualType.GetProperty(name, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty); + + return property != null; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write("property " + name); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(actualType); + } + + /// + /// Returns the string representation of the constraint. + /// + /// + protected override string GetStringRepresentation() + { + return string.Format("", name); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/RangeConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/RangeConstraint.cs new file mode 100644 index 00000000000..7f6514635a6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/RangeConstraint.cs @@ -0,0 +1,124 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif + +namespace NUnit.Framework.Constraints +{ + /// + /// RangeConstraint tests whether two values are within a + /// specified range. + /// +#if CLR_2_0 || CLR_4_0 + public class RangeConstraint : ComparisonConstraint where T : IComparable + { + private readonly T from; + private readonly T to; + + /// + /// Initializes a new instance of the class. + /// + /// From. + /// To. + public RangeConstraint(T from, T to) + : base(from, to) + { + this.from = from; + this.to = to; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if (from == null || to == null || actual == null) + throw new ArgumentException("Cannot compare using a null reference", "actual"); + + return comparer.Compare(from, actual) <= 0 && + comparer.Compare(to, actual) >= 0; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + + writer.Write("in range ({0},{1})", from, to); + } + } +#else + public class RangeConstraint : ComparisonConstraint + { + private readonly IComparable from; + private readonly IComparable to; + + /// + /// Initializes a new instance of the class. + /// + /// From. + /// To. + public RangeConstraint(IComparable from, IComparable to) : base( from, to ) + { + this.from = from; + this.to = to; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if ( from == null || to == null || actual == null) + throw new ArgumentException( "Cannot compare using a null reference", "actual" ); + + return comparer.Compare(from, actual) <= 0 && + comparer.Compare(to, actual) >= 0; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + + writer.Write("in range ({0},{1})", from, to); + } + } +#endif +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/RegexConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/RegexConstraint.cs new file mode 100644 index 00000000000..f8457c663de --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/RegexConstraint.cs @@ -0,0 +1,67 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +#if !NETCF +using System.Text.RegularExpressions; + +namespace NUnit.Framework.Constraints +{ + /// + /// RegexConstraint can test whether a string matches + /// the pattern provided. + /// + public class RegexConstraint : StringConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The pattern. + public RegexConstraint(string pattern) : base(pattern) { } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + protected override bool Matches(string actual) + { + return Regex.IsMatch( + actual, + this.expected, + this.caseInsensitive ? RegexOptions.IgnoreCase : RegexOptions.None); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("String matching"); + writer.WriteExpectedValue(this.expected); + if (this.caseInsensitive) + writer.WriteModifier("ignoring case"); + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ResolvableConstraintExpression.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ResolvableConstraintExpression.cs new file mode 100644 index 00000000000..590af35247a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ResolvableConstraintExpression.cs @@ -0,0 +1,153 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// ResolvableConstraintExpression is used to represent a compound + /// constraint being constructed at a point where the last operator + /// may either terminate the expression or may have additional + /// qualifying constraints added to it. + /// + /// It is used, for example, for a Property element or for + /// an Exception element, either of which may be optionally + /// followed by constraints that apply to the property or + /// exception. + /// + public class ResolvableConstraintExpression : ConstraintExpression, IResolveConstraint + { + /// + /// Create a new instance of ResolvableConstraintExpression + /// + public ResolvableConstraintExpression() { } + + /// + /// Create a new instance of ResolvableConstraintExpression, + /// passing in a pre-populated ConstraintBuilder. + /// + public ResolvableConstraintExpression(ConstraintBuilder builder) + : base(builder) { } + + /// + /// Appends an And Operator to the expression + /// + public ConstraintExpression And + { + get { return this.Append(new AndOperator()); } + } + + /// + /// Appends an Or operator to the expression. + /// + public ConstraintExpression Or + { + get { return this.Append(new OrOperator()); } + } + + #region IResolveConstraint Members + /// + /// Resolve the current expression to a Constraint + /// + Constraint IResolveConstraint.Resolve() + { + return builder.Resolve(); + } + #endregion + + #region Operator Overloads + /// + /// This operator creates a constraint that is satisfied only if both + /// argument constraints are satisfied. + /// + public static Constraint operator &(ResolvableConstraintExpression left, ResolvableConstraintExpression right) + { + return OperatorAndImplementation(left, right); + } + + /// + /// This operator creates a constraint that is satisfied only if both + /// argument constraints are satisfied. + /// + public static Constraint operator &(Constraint left, ResolvableConstraintExpression right) + { + return OperatorAndImplementation(left, right); + } + + /// + /// This operator creates a constraint that is satisfied only if both + /// argument constraints are satisfied. + /// + public static Constraint operator &(ResolvableConstraintExpression left, Constraint right) + { + return OperatorAndImplementation(left, right); + } + + private static Constraint OperatorAndImplementation(IResolveConstraint left, IResolveConstraint right) + { + return new AndConstraint(left.Resolve(), right.Resolve()); + } + + /// + /// This operator creates a constraint that is satisfied if either + /// of the argument constraints is satisfied. + /// + public static Constraint operator |(ResolvableConstraintExpression left, ResolvableConstraintExpression right) + { + return OperatorOrImplementation(left, right); + } + + /// + /// This operator creates a constraint that is satisfied if either + /// of the argument constraints is satisfied. + /// + public static Constraint operator |(ResolvableConstraintExpression left, Constraint right) + { + return OperatorOrImplementation(left, right); + } + + /// + /// This operator creates a constraint that is satisfied if either + /// of the argument constraints is satisfied. + /// + public static Constraint operator |(Constraint left, ResolvableConstraintExpression right) + { + return OperatorOrImplementation(left, right); + } + + private static Constraint OperatorOrImplementation(IResolveConstraint left, IResolveConstraint right) + { + return new OrConstraint(left.Resolve(), right.Resolve()); + } + + /// + /// This operator creates a constraint that is satisfied if the + /// argument constraint is not satisfied. + /// + public static Constraint operator !(ResolvableConstraintExpression constraint) + { + IResolveConstraint r = constraint as IResolveConstraint; + return new NotConstraint(r == null ? new NullConstraint() : r.Resolve()); + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ReusableConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ReusableConstraint.cs new file mode 100644 index 00000000000..caa1d9f14d5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ReusableConstraint.cs @@ -0,0 +1,76 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// ReusableConstraint wraps a constraint expression after + /// resolving it so that it can be reused consistently. + /// + public class ReusableConstraint : IResolveConstraint + { + private readonly Constraint constraint; + + /// + /// Construct a ReusableConstraint from a constraint expression + /// + /// The expression to be resolved and reused + public ReusableConstraint(IResolveConstraint c) + { + this.constraint = c.Resolve(); + } + + /// + /// Converts a constraint to a ReusableConstraint + /// + /// The constraint to be converted + /// A ReusableConstraint + public static implicit operator ReusableConstraint(Constraint c) + { + return new ReusableConstraint(c); + } + + /// + /// Returns the string representation of the constraint. + /// + /// A string representing the constraint + public override string ToString() + { + return constraint.ToString(); + } + + #region IResolveConstraint Members + + /// + /// Resolves the ReusableConstraint by returning the constraint + /// that it originally wrapped. + /// + /// A resolved constraint + public Constraint Resolve() + { + return constraint; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SameAsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SameAsConstraint.cs new file mode 100644 index 00000000000..4d08deee2db --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SameAsConstraint.cs @@ -0,0 +1,65 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// SameAsConstraint tests whether an object is identical to + /// the object passed to its constructor + /// + public class SameAsConstraint : Constraint + { + private readonly object expected; + + /// + /// Initializes a new instance of the class. + /// + /// The expected object. + public SameAsConstraint(object expected) : base(expected) + { + this.expected = expected; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + return ReferenceEquals(expected, actual); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("same as"); + writer.WriteExpectedValue(expected); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SamePathConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SamePathConstraint.cs new file mode 100644 index 00000000000..9594a601651 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SamePathConstraint.cs @@ -0,0 +1,60 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework.Constraints +{ + /// + /// Summary description for SamePathConstraint. + /// + public class SamePathConstraint : PathConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The expected path + public SamePathConstraint(string expected) : base(expected) { } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The expected path + /// The actual path + /// True for success, false for failure + protected override bool IsMatch(string expectedPath, string actualPath) + { + return StringUtil.StringsEqual(Canonicalize(expectedPath), Canonicalize(actualPath), caseInsensitive); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("Path matching"); + writer.WriteExpectedValue(expectedPath); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SamePathOrUnderConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SamePathOrUnderConstraint.cs new file mode 100644 index 00000000000..089da9d3bb8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SamePathOrUnderConstraint.cs @@ -0,0 +1,62 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework.Constraints +{ + /// + /// SamePathOrUnderConstraint tests that one path is under another + /// + public class SamePathOrUnderConstraint : PathConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The expected path + public SamePathOrUnderConstraint(string expected) : base(expected) { } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The expected path + /// The actual path + /// True for success, false for failure + protected override bool IsMatch(string expectedPath, string actualPath) + { + string path1 = Canonicalize(expectedPath); + string path2 = Canonicalize(actualPath); + return StringUtil.StringsEqual(path1, path2, caseInsensitive) || IsSubPath(path1, path2, caseInsensitive); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("Path under or matching"); + writer.WriteExpectedValue(expectedPath); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SomeItemsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SomeItemsConstraint.cs new file mode 100644 index 00000000000..38bba1285b2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SomeItemsConstraint.cs @@ -0,0 +1,75 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Constraints +{ + /// + /// SomeItemsConstraint applies another constraint to each + /// item in a collection, succeeding if any of them succeeds. + /// + public class SomeItemsConstraint : PrefixConstraint + { + /// + /// Construct a SomeItemsConstraint on top of an existing constraint + /// + /// + public SomeItemsConstraint(Constraint itemConstraint) + : base(itemConstraint) + { + this.DisplayName = "some"; + } + + /// + /// Apply the item constraint to each item in the collection, + /// succeeding if any item succeeds. + /// + /// + /// + public override bool Matches(object actual) + { + this.actual = actual; + + if (!(actual is IEnumerable)) + throw new ArgumentException("The actual value must be an IEnumerable", "actual"); + + foreach (object item in (IEnumerable)actual) + if (baseConstraint.Matches(item)) + return true; + + return false; + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("some item"); + baseConstraint.WriteDescriptionTo(writer); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/StartsWithConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/StartsWithConstraint.cs new file mode 100644 index 00000000000..2116d17ee28 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/StartsWithConstraint.cs @@ -0,0 +1,65 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// StartsWithConstraint can test whether a string starts + /// with an expected substring. + /// + public class StartsWithConstraint : StringConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The expected string + public StartsWithConstraint(string expected) : base(expected) { } + + /// + /// Test whether the constraint is matched by the actual value. + /// This is a template method, which calls the IsMatch method + /// of the derived class. + /// + /// + /// + protected override bool Matches(string actual) + { + if (this.caseInsensitive) + return actual.ToLower().StartsWith(expected.ToLower()); + else + return actual.StartsWith(expected); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("String starting with"); + writer.WriteExpectedValue(MsgUtils.ClipString(expected, writer.MaxLineLength - 40, 0)); + if (this.caseInsensitive) + writer.WriteModifier("ignoring case"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/StringConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/StringConstraint.cs new file mode 100644 index 00000000000..ea0e3e99ac9 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/StringConstraint.cs @@ -0,0 +1,81 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// StringConstraint is the abstract base for constraints + /// that operate on strings. It supports the IgnoreCase + /// modifier for string operations. + /// + public abstract class StringConstraint : Constraint + { + /// + /// The expected value + /// + protected readonly string expected; + + /// + /// Indicates whether tests should be case-insensitive + /// + protected bool caseInsensitive; + + /// + /// Constructs a StringConstraint given an expected value + /// + /// The expected value + protected StringConstraint(string expected) + : base(expected) + { + this.expected = expected; + } + + /// + /// Modify the constraint to ignore case in matching. + /// + public StringConstraint IgnoreCase + { + get { caseInsensitive = true; return this; } + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + string actualAsString = actual as string; + return actualAsString != null && Matches(actualAsString); + } + + /// + /// Test whether the constraint is satisfied by a given string + /// + /// The string to be tested + /// True for success, false for failure + protected abstract bool Matches(string actual); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SubPathConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SubPathConstraint.cs new file mode 100644 index 00000000000..7f8dd5b6da5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SubPathConstraint.cs @@ -0,0 +1,60 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// SubPathConstraint tests that the actual path is under the expected path + /// + public class SubPathConstraint : PathConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The expected path + public SubPathConstraint(string expected) : base(expected) { } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The expected path + /// The actual path + /// True for success, false for failure + protected override bool IsMatch(string expectedPath, string actualPath) + { + return IsSubPath(Canonicalize(expectedPath), Canonicalize(actualPath), caseInsensitive); + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("Path under"); + writer.WriteExpectedValue(expectedPath); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SubstringConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SubstringConstraint.cs new file mode 100644 index 00000000000..f60b5bbfb2d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/SubstringConstraint.cs @@ -0,0 +1,63 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// SubstringConstraint can test whether a string contains + /// the expected substring. + /// + public class SubstringConstraint : StringConstraint + { + /// + /// Initializes a new instance of the class. + /// + /// The expected. + public SubstringConstraint(string expected) : base(expected) { } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + protected override bool Matches(string actual) + { + if (this.caseInsensitive) + return actual.ToLower().IndexOf(expected.ToLower()) >= 0; + else + return actual.IndexOf(expected) >= 0; + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WritePredicate("String containing"); + writer.WriteExpectedValue(expected); + if (this.caseInsensitive) + writer.WriteModifier("ignoring case"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ThrowsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ThrowsConstraint.cs new file mode 100644 index 00000000000..f361123864d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ThrowsConstraint.cs @@ -0,0 +1,267 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework.Constraints +{ + /// + /// ThrowsConstraint is used to test the exception thrown by + /// a delegate by applying a constraint to it. + /// + public class ThrowsConstraint : PrefixConstraint + { + private Exception caughtException; + + /// + /// Initializes a new instance of the class, + /// using a constraint to be applied to the exception. + /// + /// A constraint to apply to the caught exception. + public ThrowsConstraint(Constraint baseConstraint) + : base(baseConstraint) { } + + /// + /// Get the actual exception thrown - used by Assert.Throws. + /// + public Exception ActualException + { + get { return caughtException; } + } + + #region Constraint Overrides + + /// + /// Executes the code of the delegate and captures any exception. + /// If a non-null base constraint was provided, it applies that + /// constraint to the exception. + /// + /// A delegate representing the code to be tested + /// True if an exception is thrown and the constraint succeeds, otherwise false + public override bool Matches(object actual) + { + caughtException = ExceptionInterceptor.Intercept(actual); + + if (caughtException == null) + return false; + + return baseConstraint == null || baseConstraint.Matches(caughtException); + } + + /// + /// Converts an ActualValueDelegate to a TestDelegate + /// before calling the primary overload. + /// +#if CLR_2_0 || CLR_4_0 + public override bool Matches(ActualValueDelegate del) + { + return Matches(new GenericInvocationDescriptor(del)); + } +#else + public override bool Matches(ActualValueDelegate del) + { + return Matches(new ObjectInvocationDescriptor(del)); + } +#endif + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + if (baseConstraint == null) + writer.WritePredicate("an exception"); + else + baseConstraint.WriteDescriptionTo(writer); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + if (caughtException == null) + writer.Write("no exception thrown"); + else if (baseConstraint != null) + baseConstraint.WriteActualValueTo(writer); + else + writer.WriteActualValue(caughtException); + } + #endregion + + /// + /// Returns the string representation of this constraint + /// + protected override string GetStringRepresentation() + { + if (baseConstraint == null) + return ""; + + return base.GetStringRepresentation(); + } + } + + #region ExceptionInterceptor + + internal class ExceptionInterceptor + { + private ExceptionInterceptor() { } + + internal static Exception Intercept(object invocation) + { + IInvocationDescriptor invocationDescriptor = GetInvocationDescriptor(invocation); + +#if NET_4_5 + if (AsyncInvocationRegion.IsAsyncOperation(invocationDescriptor.Delegate)) + { + using (AsyncInvocationRegion region = AsyncInvocationRegion.Create(invocationDescriptor.Delegate)) + { + object result = invocationDescriptor.Invoke(); + + try + { + region.WaitForPendingOperationsToComplete(result); + return null; + } + catch (Exception ex) + { + return ex; + } + } + } + else +#endif + { + try + { + invocationDescriptor.Invoke(); + return null; + } + catch (Exception ex) + { + return ex; + } + } + } + + private static IInvocationDescriptor GetInvocationDescriptor(object actual) + { + IInvocationDescriptor invocationDescriptor = actual as IInvocationDescriptor; + + if (invocationDescriptor == null) + { + TestDelegate testDelegate = actual as TestDelegate; + + if (testDelegate == null) + throw new ArgumentException( + String.Format("The actual value must be a TestDelegate or ActualValueDelegate but was {0}", actual.GetType().Name), + "actual"); + + invocationDescriptor = new VoidInvocationDescriptor(testDelegate); + } + + return invocationDescriptor; + } + } + + #endregion + + #region InvocationDescriptor + + internal class VoidInvocationDescriptor : IInvocationDescriptor + { + private readonly TestDelegate _del; + + public VoidInvocationDescriptor(TestDelegate del) + { + _del = del; + } + + public object Invoke() + { + _del(); + return null; + } + + public Delegate Delegate + { + get { return _del; } + } + } + +#if CLR_2_0 || CLR_4_0 + internal class GenericInvocationDescriptor : IInvocationDescriptor + { + private readonly ActualValueDelegate _del; + + public GenericInvocationDescriptor(ActualValueDelegate del) + { + _del = del; + } + + public object Invoke() + { + return _del(); + } + + public Delegate Delegate + { + get { return _del; } + } + } +#else + internal class ObjectInvocationDescriptor : IInvocationDescriptor + { + private readonly ActualValueDelegate _del; + + public ObjectInvocationDescriptor(ActualValueDelegate del) + { + _del = del; + } + + public object Invoke() + { + return _del(); + } + + public Delegate Delegate + { + get { return _del; } + } + } +#endif + + internal interface IInvocationDescriptor + { + object Invoke(); + Delegate Delegate { get; } + } + + #endregion +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ThrowsNothingConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ThrowsNothingConstraint.cs new file mode 100644 index 00000000000..42b5b3f2f29 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ThrowsNothingConstraint.cs @@ -0,0 +1,81 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// ThrowsNothingConstraint tests that a delegate does not + /// throw an exception. + /// + public class ThrowsNothingConstraint : Constraint + { + private Exception caughtException; + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True if no exception is thrown, otherwise false + public override bool Matches(object actual) + { + caughtException = ExceptionInterceptor.Intercept(actual); + + return caughtException == null; + } + +#if CLR_2_0 || CLR_4_0 + public override bool Matches(ActualValueDelegate del) + { + return Matches(new GenericInvocationDescriptor(del)); + } +#else + public override bool Matches(ActualValueDelegate del) + { + return Matches(new ObjectInvocationDescriptor(del)); + } +#endif + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write(string.Format("No Exception to be thrown")); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. Overridden in ThrowsNothingConstraint to write + /// information about the exception that was actually caught. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteLine(" ({0})", caughtException.Message); + writer.Write(caughtException.StackTrace); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Tolerance.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Tolerance.cs new file mode 100644 index 00000000000..2903d050e23 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/Tolerance.cs @@ -0,0 +1,220 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// The Tolerance class generalizes the notion of a tolerance + /// within which an equality test succeeds. Normally, it is + /// used with numeric types, but it can be used with any + /// type that supports taking a difference between two + /// objects and comparing that difference to a value. + /// + public class Tolerance + { + private readonly ToleranceMode mode; + private readonly object amount; + + private const string ModeMustFollowTolerance = "Tolerance amount must be specified before setting mode"; + private const string MultipleToleranceModes = "Tried to use multiple tolerance modes at the same time"; + private const string NumericToleranceRequired = "A numeric tolerance is required"; + + /// + /// Returns an empty Tolerance object, equivalent to + /// specifying no tolerance. In most cases, it results + /// in an exact match but for floats and doubles a + /// default tolerance may be used. + /// + public static Tolerance Empty + { + get { return new Tolerance(0, ToleranceMode.None); } + } + + /// + /// Returns a zero Tolerance object, equivalent to + /// specifying an exact match. + /// + public static Tolerance Zero + { + get { return new Tolerance(0, ToleranceMode.Linear); } + } + + /// + /// Constructs a linear tolerance of a specdified amount + /// + public Tolerance(object amount) : this(amount, ToleranceMode.Linear) { } + + /// + /// Constructs a tolerance given an amount and ToleranceMode + /// + private Tolerance(object amount, ToleranceMode mode) + { + this.amount = amount; + this.mode = mode; + } + + /// + /// Gets the ToleranceMode for the current Tolerance + /// + public ToleranceMode Mode + { + get { return this.mode; } + } + + + /// + /// Tests that the current Tolerance is linear with a + /// numeric value, throwing an exception if it is not. + /// + private void CheckLinearAndNumeric() + { + if (mode != ToleranceMode.Linear) + throw new InvalidOperationException(mode == ToleranceMode.None + ? ModeMustFollowTolerance + : MultipleToleranceModes); + + if (!Numerics.IsNumericType(amount)) + throw new InvalidOperationException(NumericToleranceRequired); + } + + /// + /// Gets the value of the current Tolerance instance. + /// + public object Value + { + get { return this.amount; } + } + + /// + /// Returns a new tolerance, using the current amount as a percentage. + /// + public Tolerance Percent + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(this.amount, ToleranceMode.Percent); + } + } + + /// + /// Returns a new tolerance, using the current amount in Ulps. + /// + public Tolerance Ulps + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(this.amount, ToleranceMode.Ulps); + } + } + + /// + /// Returns a new tolerance with a TimeSpan as the amount, using + /// the current amount as a number of days. + /// + public Tolerance Days + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(TimeSpan.FromDays(Convert.ToDouble(amount))); + } + } + + /// + /// Returns a new tolerance with a TimeSpan as the amount, using + /// the current amount as a number of hours. + /// + public Tolerance Hours + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(TimeSpan.FromHours(Convert.ToDouble(amount))); + } + } + + /// + /// Returns a new tolerance with a TimeSpan as the amount, using + /// the current amount as a number of minutes. + /// + public Tolerance Minutes + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(TimeSpan.FromMinutes(Convert.ToDouble(amount))); + } + } + + /// + /// Returns a new tolerance with a TimeSpan as the amount, using + /// the current amount as a number of seconds. + /// + public Tolerance Seconds + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(TimeSpan.FromSeconds(Convert.ToDouble(amount))); + } + } + + /// + /// Returns a new tolerance with a TimeSpan as the amount, using + /// the current amount as a number of milliseconds. + /// + public Tolerance Milliseconds + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(TimeSpan.FromMilliseconds(Convert.ToDouble(amount))); + } + } + + /// + /// Returns a new tolerance with a TimeSpan as the amount, using + /// the current amount as a number of clock ticks. + /// + public Tolerance Ticks + { + get + { + CheckLinearAndNumeric(); + return new Tolerance(TimeSpan.FromTicks(Convert.ToInt64(amount))); + } + } + + /// + /// Returns true if the current tolerance is empty. + /// + public bool IsEmpty + { + get { return mode == ToleranceMode.None; } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ToleranceMode.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ToleranceMode.cs new file mode 100644 index 00000000000..01a3eac5c93 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/ToleranceMode.cs @@ -0,0 +1,54 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// Modes in which the tolerance value for a comparison can be interpreted. + /// + public enum ToleranceMode + { + /// + /// The tolerance was created with a value, without specifying + /// how the value would be used. This is used to prevent setting + /// the mode more than once and is generally changed to Linear + /// upon execution of the test. + /// + None, + /// + /// The tolerance is used as a numeric range within which + /// two compared values are considered to be equal. + /// + Linear, + /// + /// Interprets the tolerance as the percentage by which + /// the two compared values my deviate from each other. + /// + Percent, + /// + /// Compares two values based in their distance in + /// representable numbers. + /// + Ulps + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/TrueConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/TrueConstraint.cs new file mode 100644 index 00000000000..0c37c70513d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/TrueConstraint.cs @@ -0,0 +1,36 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Constraints +{ + /// + /// TrueConstraint tests that the actual value is true + /// + public class TrueConstraint : BasicConstraint + { + /// + /// Initializes a new instance of the class. + /// + public TrueConstraint() : base(true, "True") { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/TypeConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/TypeConstraint.cs new file mode 100644 index 00000000000..ad3148d9353 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/TypeConstraint.cs @@ -0,0 +1,59 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Constraints +{ + /// + /// TypeConstraint is the abstract base for constraints + /// that take a Type as their expected value. + /// + public abstract class TypeConstraint : Constraint + { + /// + /// The expected Type used by the constraint + /// + protected readonly Type expectedType; + + /// + /// Construct a TypeConstraint for a given Type + /// + /// + protected TypeConstraint(Type type) : base(type) + { + this.expectedType = type; + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. TypeConstraints override this method to write + /// the name of the type. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(actual == null ? null : actual.GetType()); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/UniqueItemsConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/UniqueItemsConstraint.cs new file mode 100644 index 00000000000..e82ab3c663c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/UniqueItemsConstraint.cs @@ -0,0 +1,63 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; + +namespace NUnit.Framework.Constraints +{ + /// + /// UniqueItemsConstraint tests whether all the items in a + /// collection are unique. + /// + public class UniqueItemsConstraint : CollectionItemsEqualConstraint + { + /// + /// Check that all items are unique. + /// + /// + /// + protected override bool doMatch(IEnumerable actual) + { + ObjectList list = new ObjectList(); + + foreach (object o1 in actual) + { + foreach (object o2 in list) + if (ItemsEqual(o1, o2)) + return false; + list.Add(o1); + } + + return true; + } + + /// + /// Write a description of this constraint to a MessageWriter + /// + /// + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write("all items unique"); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/XmlSerializableConstraint.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/XmlSerializableConstraint.cs new file mode 100644 index 00000000000..90acc2e9398 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Constraints/XmlSerializableConstraint.cs @@ -0,0 +1,105 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +#if !SILVERLIGHT +using System; +using System.IO; +using System.Xml.Serialization; + +namespace NUnit.Framework.Constraints +{ + /// + /// XmlSerializableConstraint tests whether + /// an object is serializable in XML format. + /// + public class XmlSerializableConstraint : Constraint + { + private XmlSerializer serializer; + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// True for success, false for failure + public override bool Matches(object actual) + { + this.actual = actual; + + if(actual == null) + throw new ArgumentException(); + + MemoryStream stream = new MemoryStream(); + + try + { + serializer = new XmlSerializer(actual.GetType()); + + serializer.Serialize(stream, actual); + + stream.Seek(0, SeekOrigin.Begin); + + object value = serializer.Deserialize(stream); + + return value != null; + } + catch (NotSupportedException) + { + return false; + } + catch (InvalidOperationException) + { + return false; + } + } + + /// + /// Write the constraint description to a MessageWriter + /// + /// The writer on which the description is displayed + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.Write("xml serializable"); + } + + /// + /// Write the actual value for a failing constraint test to a + /// MessageWriter. The default implementation simply writes + /// the raw value of actual, leaving it to the writer to + /// perform any formatting. + /// + /// The writer on which the actual value is displayed + public override void WriteActualValueTo(MessageWriter writer) + { + writer.Write("<{0}>", actual.GetType().Name); + } + + /// + /// Returns the string representation of this constraint + /// + protected override string GetStringRepresentation() + { + return ""; + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Contains.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Contains.cs new file mode 100644 index 00000000000..66797f5fc4e --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Contains.cs @@ -0,0 +1,62 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework +{ + /// + /// Helper class with properties and methods that supply + /// a number of constraints used in Asserts. + /// + public class Contains + { + #region Item + + /// + /// Returns a new CollectionContainsConstraint checking for the + /// presence of a particular object in the collection. + /// + public static CollectionContainsConstraint Item(object expected) + { + return new CollectionContainsConstraint(expected); + } + + #endregion + + #region Substring + + /// + /// Returns a constraint that succeeds if the actual + /// value contains the substring supplied as an argument. + /// + public static SubstringConstraint Substring(string expected) + { + return new SubstringConstraint(expected);; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Env.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Env.cs new file mode 100644 index 00000000000..0d9a547f5d8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Env.cs @@ -0,0 +1,56 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Text; + +namespace NUnit +{ + /// + /// Env is a static class that provides some of the features of + /// System.Environment that are not available under all runtimes + /// + public class Env + { + // Define NewLine to be used for this system + // NOTE: Since this is done at compile time for .NET CF, + // these binaries are not yet currently portable. + /// + /// The newline sequence in the current environmemt. + /// +#if PocketPC || WindowsCE || NETCF + public static readonly string NewLine = "\r\n"; +#else + public static readonly string NewLine = Environment.NewLine; +#endif + + /// + /// Path to the 'My Documents' folder + /// +#if SILVERLIGHT || PocketPC || WindowsCE || NETCF + public static string DocumentFolder = @"\My Documents"; +#else + public static string DocumentFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/AssertionException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/AssertionException.cs new file mode 100644 index 00000000000..66431d61b97 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/AssertionException.cs @@ -0,0 +1,56 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Thrown when an assertion failed. + /// + [Serializable] + public class AssertionException : System.Exception + { + /// The error message that explains + /// the reason for the exception + public AssertionException (string message) : base(message) + {} + + /// The error message that explains + /// the reason for the exception + /// The exception that caused the + /// current exception + public AssertionException(string message, Exception inner) : + base(message, inner) + {} + +#if !NETCF && !SILVERLIGHT + /// + /// Serialization Constructor + /// + protected AssertionException(System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info,context) + {} +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/IgnoreException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/IgnoreException.cs new file mode 100644 index 00000000000..3e563ae3ddf --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/IgnoreException.cs @@ -0,0 +1,55 @@ +// *********************************************************************** +// Copyright (c) 2004 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Thrown when an assertion failed. + /// + [Serializable] + public class IgnoreException : System.Exception + { + /// + public IgnoreException (string message) : base(message) + {} + + /// The error message that explains + /// the reason for the exception + /// The exception that caused the + /// current exception + public IgnoreException(string message, Exception inner) : + base(message, inner) + {} + +#if !NETCF && !SILVERLIGHT + /// + /// Serialization Constructor + /// + protected IgnoreException(System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info,context) + {} +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/InconclusiveException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/InconclusiveException.cs new file mode 100644 index 00000000000..eab245d60c1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/InconclusiveException.cs @@ -0,0 +1,58 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Thrown when a test executes inconclusively. + /// + [Serializable] + public class InconclusiveException : System.Exception + { + /// The error message that explains + /// the reason for the exception + public InconclusiveException(string message) + : base(message) + { } + + /// The error message that explains + /// the reason for the exception + /// The exception that caused the + /// current exception + public InconclusiveException(string message, Exception inner) + : + base(message, inner) + { } + +#if !NETCF && !SILVERLIGHT + /// + /// Serialization Constructor + /// + protected InconclusiveException(System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) + { } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/SuccessException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/SuccessException.cs new file mode 100644 index 00000000000..b94a339922a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Exceptions/SuccessException.cs @@ -0,0 +1,57 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + using System; + + /// + /// Thrown when an assertion failed. + /// + [Serializable] + public class SuccessException : System.Exception + { + /// + public SuccessException(string message) + : base(message) + { } + + /// The error message that explains + /// the reason for the exception + /// The exception that caused the + /// current exception + public SuccessException(string message, Exception inner) + : + base(message, inner) + { } + +#if !NETCF && !SILVERLIGHT + /// + /// Serialization Constructor + /// + protected SuccessException(System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) + { } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/IParameterDataProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/IParameterDataProvider.cs new file mode 100644 index 00000000000..e254a8e82a9 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/IParameterDataProvider.cs @@ -0,0 +1,52 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Collections; +using System.Reflection; + +namespace NUnit.Framework.Extensibility +{ + /// + /// The IDataPointProvider interface is used by extensions + /// that provide data for a single test parameter. + /// + public interface IParameterDataProvider + { + /// + /// Determine whether any data is available for a parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// True if any data is available, otherwise false. + bool HasDataFor(ParameterInfo parameter); + + /// + /// Return an IEnumerable providing data for use with the + /// supplied parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// An IEnumerable providing the required data + IEnumerable GetDataFor(ParameterInfo parameter); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ISuiteBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ISuiteBuilder.cs new file mode 100644 index 00000000000..e307e8c4af0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ISuiteBuilder.cs @@ -0,0 +1,55 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Internal; + +namespace NUnit.Framework.Extensibility +{ + /// + /// The ISuiteBuilder interface is exposed by a class that knows how to + /// build a suite from one or more Types. + /// + public interface ISuiteBuilder + { + /// + /// Examine the type and determine if it is suitable for + /// this builder to use in building a TestSuite. + /// + /// Note that returning false will cause the type to be ignored + /// in loading the tests. If it is desired to load the suite + /// but label it as non-runnable, ignored, etc., then this + /// method must return true. + /// + /// The type of the fixture to be used + /// True if the type can be used to build a TestSuite + bool CanBuildFrom( Type type ); + + /// + /// Build a TestSuite from type provided. + /// + /// The type of the fixture to be used + /// A TestSuite + Test BuildFrom( Type type ); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ITestCaseBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ITestCaseBuilder.cs new file mode 100644 index 00000000000..3324f99cefb --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ITestCaseBuilder.cs @@ -0,0 +1,88 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Extensibility +{ + /// + /// The ITestCaseBuilder interface is exposed by a class that knows how to + /// build a test case from certain methods. + /// + public interface ITestCaseBuilder + { + /// + /// Examine the method and determine if it is suitable for + /// this builder to use in building a TestCase. + /// + /// Note that returning false will cause the method to be ignored + /// in loading the tests. If it is desired to load the method + /// but label it as non-runnable, ignored, etc., then this + /// method must return true. + /// + /// The test method to examine + /// True is the builder can use this method + bool CanBuildFrom(MethodInfo method); + + /// + /// Build a TestCase from the provided MethodInfo. + /// + /// The method to be used as a test case + /// A TestCase or null + Test BuildFrom(MethodInfo method); + } + + /// + /// ITestCaseBuilder2 extends ITestCaseBuilder with methods + /// that include the suite for which the test case is being + /// built. Test case builders not needing the suite can + /// continue to implement ITestCaseBuilder. + /// + public interface ITestCaseBuilder2 : ITestCaseBuilder + { + /// + /// Examine the method and determine if it is suitable for + /// this builder to use in building a TestCase to be + /// included in the suite being populated. + /// + /// Note that returning false will cause the method to be ignored + /// in loading the tests. If it is desired to load the method + /// but label it as non-runnable, ignored, etc., then this + /// method must return true. + /// + /// The test method to examine + /// The suite being populated + /// True is the builder can use this method + bool CanBuildFrom(MethodInfo method, Test suite); + + /// + /// Build a TestCase from the provided MethodInfo for + /// inclusion in the suite being constructed. + /// + /// The method to be used as a test case + /// The test suite being populated, or null + /// A TestCase or null + Test BuildFrom(MethodInfo method, Test suite); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ITestCaseProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ITestCaseProvider.cs new file mode 100644 index 00000000000..6450955f46c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Extensibility/ITestCaseProvider.cs @@ -0,0 +1,55 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Extensibility +{ + /// + /// The ITestCaseProvider interface is used by extensions + /// that provide data for parameterized tests, along with + /// certain flags and other indicators used in the test. + /// + public interface ITestCaseProvider + { + /// + /// Determine whether any test cases are available for a parameterized method. + /// + /// A MethodInfo representing a parameterized test + /// True if any cases are available, otherwise false. + bool HasTestCasesFor(MethodInfo method); + + /// + /// Return an IEnumerable providing test cases for use in + /// running a paramterized test. + /// + /// + /// +#if CLR_2_0 || CLR_4_0 + System.Collections.Generic.IEnumerable GetTestCasesFor(MethodInfo method); +#else + System.Collections.IEnumerable GetTestCasesFor(MethodInfo method); +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/GlobalSettings.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/GlobalSettings.cs new file mode 100644 index 00000000000..b6bebbe960a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/GlobalSettings.cs @@ -0,0 +1,39 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// GlobalSettings is a place for setting default values used + /// by the framework in performing asserts. + /// + public class GlobalSettings + { + /// + /// Default tolerance for floating point equality + /// + public static double DefaultFloatingPointTolerance = 0.0d; + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Guard.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Guard.cs new file mode 100644 index 00000000000..25285838b24 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Guard.cs @@ -0,0 +1,35 @@ +using System; + +namespace NUnit.Framework +{ + /// + /// Class used to guard against unexpected argument values + /// by throwing an appropriate exception. + /// + public class Guard + { + /// + /// Throws an exception if an argument is null + /// + /// The value to be tested + /// The name of the argument + public static void ArgumentNotNull(object value, string name) + { + if (value == null) + throw new ArgumentNullException("Argument " + name + " must not be null", name); + } + + /// + /// Throws an exception if a string argument is null or empty + /// + /// The value to be tested + /// The name of the argument + public static void ArgumentNotNullOrEmpty(string value, string name) + { + ArgumentNotNull(value, name); + + if (value == string.Empty) + throw new ArgumentException("Argument " + name +" must not be the empty string", name); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Has.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Has.cs new file mode 100644 index 00000000000..4880bd480f0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Has.cs @@ -0,0 +1,209 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework +{ + /// + /// Helper class with properties and methods that supply + /// a number of constraints used in Asserts. + /// + public class Has + { + #region No + + /// + /// Returns a ConstraintExpression that negates any + /// following constraint. + /// + public static ConstraintExpression No + { + get { return new ConstraintExpression().Not; } + } + + #endregion + + #region All + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them succeed. + /// + public static ConstraintExpression All + { + get { return new ConstraintExpression().All; } + } + + #endregion + + #region Some + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if at least one of them succeeds. + /// + public static ConstraintExpression Some + { + get { return new ConstraintExpression().Some; } + } + + #endregion + + #region None + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them fail. + /// + public static ConstraintExpression None + { + get { return new ConstraintExpression().None; } + } + + #endregion + + #region Exactly(n) + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding only if a specified number of them succeed. + /// + public static ConstraintExpression Exactly(int expectedCount) + { + return new ConstraintExpression().Exactly(expectedCount); + } + + #endregion + + #region Property + + /// + /// Returns a new PropertyConstraintExpression, which will either + /// test for the existence of the named property on the object + /// being tested or apply any following constraint to that property. + /// + public static ResolvableConstraintExpression Property(string name) + { + return new ConstraintExpression().Property(name); + } + + #endregion + + #region Length + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Length property of the object being tested. + /// + public static ResolvableConstraintExpression Length + { + get { return Property("Length"); } + } + + #endregion + + #region Count + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Count property of the object being tested. + /// + public static ResolvableConstraintExpression Count + { + get { return Property("Count"); } + } + + #endregion + + #region Message + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the Message property of the object being tested. + /// + public static ResolvableConstraintExpression Message + { + get { return Property("Message"); } + } + + #endregion + + #region InnerException + + /// + /// Returns a new ConstraintExpression, which will apply the following + /// constraint to the InnerException property of the object being tested. + /// + public static ResolvableConstraintExpression InnerException + { + get { return Property("InnerException"); } + } + + #endregion + + #region Attribute + + /// + /// Returns a new AttributeConstraint checking for the + /// presence of a particular attribute on an object. + /// + public static ResolvableConstraintExpression Attribute(Type expectedType) + { + return new ConstraintExpression().Attribute(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a new AttributeConstraint checking for the + /// presence of a particular attribute on an object. + /// + public static ResolvableConstraintExpression Attribute() + { + return Attribute(typeof(T)); + } +#endif + + #endregion + + #region Member + + /// + /// Returns a new CollectionContainsConstraint checking for the + /// presence of a particular object in the collection. + /// + public static CollectionContainsConstraint Member(object expected) + { + return new CollectionContainsConstraint(expected); + } + + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/IExpectException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/IExpectException.cs new file mode 100644 index 00000000000..804af3ecaaa --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/IExpectException.cs @@ -0,0 +1,42 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// Interface implemented by a user fixture in order to + /// validate any expected exceptions. It is only called + /// for test methods marked with the ExpectedException + /// attribute. + /// + public interface IExpectException + { + /// + /// Method to handle an expected exception + /// + /// The exception to be handled + void HandleException(Exception ex); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AssemblyHelper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AssemblyHelper.cs new file mode 100644 index 00000000000..3cce0e83f93 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AssemblyHelper.cs @@ -0,0 +1,135 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; + +namespace NUnit.Framework.Internal +{ + /// + /// AssemblyHelper provides static methods for working + /// with assemblies. + /// + public class AssemblyHelper + { + #region GetAssemblyPath + +#if !NETCF + /// + /// Gets the path from which the assembly defining a type was loaded. + /// + /// The Type. + /// The path. + public static string GetAssemblyPath(Type type) + { + return GetAssemblyPath(type.Assembly); + } + + /// + /// Gets the path from which an assembly was loaded. + /// + /// The assembly. + /// The path. + public static string GetAssemblyPath(Assembly assembly) + { + string codeBase = assembly.CodeBase; + + if (IsFileUri(codeBase)) + return GetAssemblyPathFromCodeBase(codeBase); + + return assembly.Location; + } +#endif + + #endregion + + #region GetDirectoryName + +#if !NETCF + /// + /// Gets the path to the directory from which an assembly was loaded. + /// + /// The assembly. + /// The path. + public static string GetDirectoryName( Assembly assembly ) + { + return System.IO.Path.GetDirectoryName(GetAssemblyPath(assembly)); + } +#endif + + #endregion + + #region GetAssemblyName + + /// + /// Gets the AssemblyName of an assembly. + /// + /// The assembly + /// An AssemblyName + public static AssemblyName GetAssemblyName(Assembly assembly) + { +#if SILVERLIGHT + return new AssemblyName(assembly.FullName); +#else + return assembly.GetName(); +#endif + } + + #endregion + + #region Helper Methods + +#if !NETCF + private static bool IsFileUri(string uri) + { + return uri.ToLower().StartsWith(Uri.UriSchemeFile); + } + + // Public for testing purposes + public static string GetAssemblyPathFromCodeBase(string codeBase) + { + // Skip over the file:// part + int start = Uri.UriSchemeFile.Length + Uri.SchemeDelimiter.Length; + + bool isWindows = System.IO.Path.DirectorySeparatorChar == '\\'; + + if (codeBase[start] == '/') // third slash means a local path + { + // Handle Windows Drive specifications + if (isWindows && codeBase[start + 2] == ':') + ++start; + // else leave the last slash so path is absolute + } + else // It's either a Windows Drive spec or a share + { + if (!isWindows || codeBase[start + 1] != ':') + start -= 2; // Back up to include two slashes + } + + return codeBase.Substring(start); + } +#endif + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AsyncInvocationRegion.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AsyncInvocationRegion.cs new file mode 100644 index 00000000000..fd896dc6f1f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AsyncInvocationRegion.cs @@ -0,0 +1,137 @@ +#if NET_4_5 +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; + +namespace NUnit.Framework.Internal +{ + internal abstract class AsyncInvocationRegion : IDisposable + { + private static readonly Type AsyncStateMachineAttribute = Type.GetType("System.Runtime.CompilerServices.AsyncStateMachineAttribute"); +#if __MOBILE__ + static void PreserveStackTrace (Exception e) + { + } +#else + private static readonly MethodInfo PreserveStackTraceMethod = typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly Action PreserveStackTrace; + + static AsyncInvocationRegion() + { + PreserveStackTrace = (Action)Delegate.CreateDelegate(typeof(Action), PreserveStackTraceMethod); + } +#endif + + private AsyncInvocationRegion() + { + } + + public static AsyncInvocationRegion Create(Delegate @delegate) + { + return Create(@delegate.Method); + } + + public static AsyncInvocationRegion Create(MethodInfo method) + { + if (!IsAsyncOperation(method)) + throw new InvalidOperationException(@"Either asynchronous support is not available or an attempt +at wrapping a non-async method invocation in an async region was done"); + + if (method.ReturnType == typeof(void)) + return new AsyncVoidInvocationRegion(); + + return new AsyncTaskInvocationRegion(); + } + + public static bool IsAsyncOperation(MethodInfo method) + { + return AsyncStateMachineAttribute != null && method.IsDefined(AsyncStateMachineAttribute, false); + } + + public static bool IsAsyncOperation(Delegate @delegate) + { + return IsAsyncOperation(@delegate.Method); + } + + /// + /// Waits for pending asynchronous operations to complete, if appropriate, + /// and returns a proper result of the invocation by unwrapping task results + /// + /// The raw result of the method invocation + /// The unwrapped result, if necessary + public abstract object WaitForPendingOperationsToComplete(object invocationResult); + + public virtual void Dispose() + { } + + private class AsyncVoidInvocationRegion : AsyncInvocationRegion + { + private readonly SynchronizationContext _previousContext; + private readonly AsyncSynchronizationContext _currentContext; + + public AsyncVoidInvocationRegion() + { + _previousContext = SynchronizationContext.Current; + _currentContext = new AsyncSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(_currentContext); + } + + public override void Dispose() + { + SynchronizationContext.SetSynchronizationContext(_previousContext); + } + + public override object WaitForPendingOperationsToComplete(object invocationResult) + { + try + { + _currentContext.WaitForPendingOperationsToComplete(); + return invocationResult; + } + catch (Exception e) + { + PreserveStackTrace(e); + throw; + } + } + } + + private class AsyncTaskInvocationRegion : AsyncInvocationRegion + { + private const string TaskWaitMethod = "Wait"; + private const string TaskResultProperty = "Result"; + private const string SystemAggregateException = "System.AggregateException"; + private const string InnerExceptionsProperty = "InnerExceptions"; + private const BindingFlags TaskResultPropertyBindingFlags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public; + + public override object WaitForPendingOperationsToComplete(object invocationResult) + { + try + { + invocationResult.GetType().GetMethod(TaskWaitMethod, new Type[0]).Invoke(invocationResult, null); + } + catch (TargetInvocationException e) + { + IList innerExceptions = GetAllExceptions(e.InnerException); + + PreserveStackTrace(innerExceptions[0]); + throw innerExceptions[0]; + } + + PropertyInfo taskResultProperty = invocationResult.GetType().GetProperty(TaskResultProperty, TaskResultPropertyBindingFlags); + + return taskResultProperty != null ? taskResultProperty.GetValue(invocationResult, null) : invocationResult; + } + + private static IList GetAllExceptions(Exception exception) + { + if (SystemAggregateException.Equals(exception.GetType().FullName)) + return (IList)exception.GetType().GetProperty(InnerExceptionsProperty).GetValue(exception, null); + + return new Exception[] { exception }; + } + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AsyncSynchronizationContext.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AsyncSynchronizationContext.cs new file mode 100644 index 00000000000..17db7ce8bf5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/AsyncSynchronizationContext.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections; +using System.Threading; + +namespace NUnit.Framework.Internal +{ + internal class AsyncSynchronizationContext : SynchronizationContext + { + private int _operationCount; + private readonly AsyncOperationQueue _operations = new AsyncOperationQueue(); + + public override void Send(SendOrPostCallback d, object state) + { + throw new InvalidOperationException("Sending to this synchronization context is not supported"); + } + + public override void Post(SendOrPostCallback d, object state) + { + _operations.Enqueue(new AsyncOperation(d, state)); + } + + public override void OperationStarted() + { + Interlocked.Increment(ref _operationCount); + base.OperationStarted(); + } + + public override void OperationCompleted() + { + if (Interlocked.Decrement(ref _operationCount) == 0) + _operations.MarkAsComplete(); + + base.OperationCompleted(); + } + + public void WaitForPendingOperationsToComplete() + { + _operations.InvokeAll(); + } + + private class AsyncOperationQueue + { + private bool _run = true; + private readonly Queue _operations = Queue.Synchronized(new Queue()); + private readonly AutoResetEvent _operationsAvailable = new AutoResetEvent(false); + + public void Enqueue(AsyncOperation asyncOperation) + { + _operations.Enqueue(asyncOperation); + _operationsAvailable.Set(); + } + + public void MarkAsComplete() + { + _run = false; + _operationsAvailable.Set(); + } + + public void InvokeAll() + { + while (_run) + { + InvokePendingOperations(); + _operationsAvailable.WaitOne(); + } + + InvokePendingOperations(); + } + + private void InvokePendingOperations() + { + while (_operations.Count > 0) + { + AsyncOperation operation = (AsyncOperation)_operations.Dequeue(); + operation.Invoke(); + } + } + } + + private class AsyncOperation + { + private readonly SendOrPostCallback _action; + private readonly object _state; + + public AsyncOperation(SendOrPostCallback action, object state) + { + _action = action; + _state = state; + } + + public void Invoke() + { + _action(_state); + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombinatorialStrategy.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombinatorialStrategy.cs new file mode 100644 index 00000000000..ccfe7bb3ceb --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombinatorialStrategy.cs @@ -0,0 +1,92 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// CombinatorialStrategy creates test cases by using all possible + /// combinations of the parameter data. + /// + public class CombinatorialStrategy : CombiningStrategy + { + /// + /// Initializes a new instance of the class. + /// + /// The sources. + public CombinatorialStrategy(IEnumerable[] sources) : base(sources) { } + + /// + /// Gets the test cases generated by the CombiningStrategy. + /// + /// The test cases. +#if CLR_2_0 || CLR_4_0 + public override IEnumerable GetTestCases() + { + List testCases = new List(); +#else + public override IEnumerable GetTestCases() + { + ArrayList testCases = new ArrayList(); +#endif + IEnumerator[] enumerators = new IEnumerator[Sources.Length]; + int index = -1; + + for (; ; ) + { + while (++index < Sources.Length) + { + enumerators[index] = Sources[index].GetEnumerator(); + if (!enumerators[index].MoveNext()) + return testCases; + } + + object[] testdata = new object[Sources.Length]; + + for (int i = 0; i < Sources.Length; i++) + testdata[i] = enumerators[i].Current; + + ParameterSet parms = new ParameterSet(); + parms.Arguments = testdata; + testCases.Add(parms); + + index = Sources.Length; + + while (--index >= 0 && !enumerators[index].MoveNext()) ; + + if (index < 0) break; + } + + return testCases; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombinatorialTestCaseProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombinatorialTestCaseProvider.cs new file mode 100644 index 00000000000..330e3500b58 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombinatorialTestCaseProvider.cs @@ -0,0 +1,108 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using System.Collections; +using NUnit.Framework.Api; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// CombinatorialTestCaseProvider creates test cases from individual + /// parameter data values, combining them using the CombiningStrategy + /// indicated by an Attribute used on the test method. + /// + public class CombinatorialTestCaseProvider : ITestCaseProvider + { + #region Static Members + static IParameterDataProvider dataPointProvider = new ParameterDataProviders(); + + #endregion + + #region ITestCaseProvider Members + + /// + /// Determine whether any test cases are available for a parameterized method. + /// + /// A MethodInfo representing a parameterized test + /// + /// True if any cases are available, otherwise false. + /// + public bool HasTestCasesFor(System.Reflection.MethodInfo method) + { + if (method.GetParameters().Length == 0) + return false; + + foreach (ParameterInfo parameter in method.GetParameters()) + if (!dataPointProvider.HasDataFor(parameter)) + return false; + + return true; + } + + /// + /// Return an IEnumerable providing test cases for use in + /// running a paramterized test. + /// + /// + /// +#if CLR_2_0 || CLR_4_0 + public System.Collections.Generic.IEnumerable GetTestCasesFor(MethodInfo method) +#else + public IEnumerable GetTestCasesFor(MethodInfo method) +#endif + { + return GetStrategy(method).GetTestCases(); + } + #endregion + + #region GetStrategy + + /// + /// Gets the strategy to be used in building test cases for this test. + /// + /// The method for which test cases are being built. + /// + private CombiningStrategy GetStrategy(MethodInfo method) + { + ParameterInfo[] parameters = method.GetParameters(); + IEnumerable[] sources = new IEnumerable[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + sources[i] = dataPointProvider.GetDataFor(parameters[i]); + + if (method.IsDefined(typeof(NUnit.Framework.SequentialAttribute), false)) + return new SequentialStrategy(sources); + + if (method.IsDefined(typeof(NUnit.Framework.PairwiseAttribute), false) && + method.GetParameters().Length > 2) + return new PairwiseStrategy(sources); + + return new CombinatorialStrategy(sources); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombiningStrategy.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombiningStrategy.cs new file mode 100644 index 00000000000..e41e797e891 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/CombiningStrategy.cs @@ -0,0 +1,91 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; +using NUnit.Framework.Internal; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Builders +{ + /// + /// CombiningStrategy is the abstract base for classes that + /// know how to combine values provided for individual test + /// parameters to create a set of test cases. + /// + public abstract class CombiningStrategy + { + private IEnumerable[] sources; + private IEnumerator[] enumerators; + + /// + /// Initializes a new instance of the + /// class using a set of parameter sources. + /// + /// The sources. + public CombiningStrategy(IEnumerable[] sources) + { + this.sources = sources; + } + + /// + /// Gets the sources used by this strategy. + /// + /// The sources. + public IEnumerable[] Sources + { + get { return sources; } + } + + /// + /// Gets the enumerators for the sources. + /// + /// The enumerators. + public IEnumerator[] Enumerators + { + get + { + if (enumerators == null) + { + enumerators = new IEnumerator[Sources.Length]; + for (int i = 0; i < Sources.Length; i++) + enumerators[i] = Sources[i].GetEnumerator(); + } + + return enumerators; + } + } + + /// + /// Gets the test cases generated by the CombiningStrategy. + /// + /// The test cases. +#if CLR_2_0 || CLR_4_0 + public abstract System.Collections.Generic.IEnumerable GetTestCases(); +#else + public abstract System.Collections.IEnumerable GetTestCases(); +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/DataAttributeTestCaseProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/DataAttributeTestCaseProvider.cs new file mode 100644 index 00000000000..f8372313521 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/DataAttributeTestCaseProvider.cs @@ -0,0 +1,90 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// DataAttributeTestCaseProvider provides data for methods + /// annotated with any DataAttribute. For correct operation, + /// any new or custom Attributes must implement one of the + /// following interfaces: + /// ITestCaseData + /// ITestCaseSource + /// + public class DataAttributeTestCaseProvider : ITestCaseProvider + { + #region ITestCaseProvider Members + + /// + /// Determine whether any test cases are available for a parameterized method. + /// + /// A MethodInfo representing a parameterized test + /// True if any cases are available, otherwise false. + public bool HasTestCasesFor(MethodInfo method) + { + return method.IsDefined(typeof(DataAttribute), false); + } + + /// + /// Return an IEnumerable providing test cases for use in + /// running a parameterized test. + /// + /// + /// +#if CLR_2_0 || CLR_4_0 + public IEnumerable GetTestCasesFor(MethodInfo method) + { + List testCases = new List(); +#else + public IEnumerable GetTestCasesFor(MethodInfo method) + { + ArrayList testCases = new ArrayList(); +#endif + + foreach (DataAttribute attr in method.GetCustomAttributes(typeof(DataAttribute), false)) + { + ITestCaseSource source = attr as ITestCaseSource; + if (source != null) + { + // TODO: Create a class to handle exceptions for NUnitLite + foreach (ITestCaseData testCase in ((ITestCaseSource)attr).GetTestCasesFor(method)) + testCases.Add(testCase); + continue; + } + } + + return testCases; + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/DatapointProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/DatapointProvider.cs new file mode 100644 index 00000000000..7a08e740d77 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/DatapointProvider.cs @@ -0,0 +1,186 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using System.Collections; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// Provides data from fields marked with the DatapointAttribute or the + /// DatapointsAttribute. + /// + public class DatapointProvider : IParameterDataProvider + { + #region IDataPointProvider Members + + /// + /// Determine whether any data is available for a parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// + /// True if any data is available, otherwise false. + /// + public bool HasDataFor(System.Reflection.ParameterInfo parameter) + { + Type parameterType = parameter.ParameterType; + MemberInfo method = parameter.Member; + Type fixtureType = method.ReflectedType; + + if (!method.IsDefined(typeof(TheoryAttribute), true)) + return false; + + if (parameterType == typeof(bool) || parameterType.IsEnum) + return true; + + foreach (MemberInfo member in fixtureType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) + { + if (member.IsDefined(typeof(DatapointAttribute), true) && + GetTypeFromMemberInfo(member) == parameterType) + return true; + else if (member.IsDefined(typeof(DatapointSourceAttribute), true) && + GetElementTypeFromMemberInfo(member) == parameterType) + return true; + } + + return false; + } + + /// + /// Return an IEnumerable providing data for use with the + /// supplied parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// + /// An IEnumerable providing the required data + /// + public System.Collections.IEnumerable GetDataFor(System.Reflection.ParameterInfo parameter) + { + ObjectList datapoints = new ObjectList(); + + Type parameterType = parameter.ParameterType; + Type fixtureType = parameter.Member.ReflectedType; + + foreach (MemberInfo member in fixtureType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) + { + if (member.IsDefined(typeof(DatapointAttribute), true)) + { + if (GetTypeFromMemberInfo(member) == parameterType && + member.MemberType == MemberTypes.Field) + { + FieldInfo field = member as FieldInfo; + if (field.IsStatic) + datapoints.Add(field.GetValue(null)); + else + datapoints.Add(field.GetValue(ProviderCache.GetInstanceOf(fixtureType))); + } + } + else if (member.IsDefined(typeof(DatapointSourceAttribute), true)) + { + if (GetElementTypeFromMemberInfo(member) == parameterType) + { + object instance; + + switch(member.MemberType) + { + case MemberTypes.Field: + FieldInfo field = member as FieldInfo; + instance = field.IsStatic ? null : ProviderCache.GetInstanceOf(fixtureType); + foreach (object data in (IEnumerable)field.GetValue(instance)) + datapoints.Add(data); + break; + case MemberTypes.Property: + PropertyInfo property = member as PropertyInfo; + MethodInfo getMethod = property.GetGetMethod(true); + instance = getMethod.IsStatic ? null : ProviderCache.GetInstanceOf(fixtureType); + foreach (object data in (IEnumerable)property.GetValue(instance,null)) + datapoints.Add(data); + break; + case MemberTypes.Method: + MethodInfo method = member as MethodInfo; + instance = method.IsStatic ? null : ProviderCache.GetInstanceOf(fixtureType); + foreach (object data in (IEnumerable)method.Invoke(instance, new Type[0])) + datapoints.Add(data); + break; + } + } + } + } + + if (datapoints.Count == 0) + { + if (parameterType == typeof(bool)) + { + datapoints.Add(true); + datapoints.Add(false); + } + else if (parameterType.IsEnum) + { + datapoints.AddRange(TypeHelper.GetEnumValues(parameterType)); + } + } + + return datapoints; + } + + private Type GetTypeFromMemberInfo(MemberInfo member) + { + switch (member.MemberType) + { + case MemberTypes.Field: + return ((FieldInfo)member).FieldType; + case MemberTypes.Property: + return ((PropertyInfo)member).PropertyType; + case MemberTypes.Method: + return ((MethodInfo)member).ReturnType; + default: + return null; + } + } + + private Type GetElementTypeFromMemberInfo(MemberInfo member) + { + Type type = GetTypeFromMemberInfo(member); + + if (type == null) + return null; + + if (type.IsArray) + return type.GetElementType(); + +#if CLR_2_0 || CLR_4_0 + if (type.IsGenericType && type.Name == "IEnumerable`1") + return type.GetGenericArguments()[0]; +#endif + + return null; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/NUnitTestCaseBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/NUnitTestCaseBuilder.cs new file mode 100644 index 00000000000..2ad8d2ff544 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/NUnitTestCaseBuilder.cs @@ -0,0 +1,408 @@ +// *********************************************************************** +// Copyright (c) 2008-2012 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal.Commands; + +#if NET_4_5 +using System.Threading.Tasks; +#endif + +namespace NUnit.Framework.Builders +{ + /// + /// Class to build ether a parameterized or a normal NUnitTestMethod. + /// There are four cases that the builder must deal with: + /// 1. The method needs no params and none are provided + /// 2. The method needs params and they are provided + /// 3. The method needs no params but they are provided in error + /// 4. The method needs params but they are not provided + /// This could have been done using two different builders, but it + /// turned out to be simpler to have just one. The BuildFrom method + /// takes a different branch depending on whether any parameters are + /// provided, but all four cases are dealt with in lower-level methods + /// + public class NUnitTestCaseBuilder : ITestCaseBuilder2 + { + private Randomizer randomizer; + + private ITestCaseProvider testCaseProvider = new TestCaseProviders(); + + /// + /// Default no argument constructor for NUnitTestCaseBuilder + /// + public NUnitTestCaseBuilder() + { + randomizer = Randomizer.CreateRandomizer(); + } + + #region ITestCaseBuilder Methods + /// + /// Determines if the method can be used to build an NUnit test + /// test method of some kind. The method must normally be marked + /// with an identifying attriute for this to be true. + /// + /// Note that this method does not check that the signature + /// of the method for validity. If we did that here, any + /// test methods with invalid signatures would be passed + /// over in silence in the test run. Since we want such + /// methods to be reported, the check for validity is made + /// in BuildFrom rather than here. + /// + /// A MethodInfo for the method being used as a test method + /// True if the builder can create a test case from this method + public bool CanBuildFrom(MethodInfo method) + { + return method.IsDefined(typeof(TestAttribute), false) + || method.IsDefined(typeof(ITestCaseSource), false) + || method.IsDefined(typeof(TheoryAttribute), false); + } + + /// + /// Build a Test from the provided MethodInfo. Depending on + /// whether the method takes arguments and on the availability + /// of test case data, this method may return a single test + /// or a group of tests contained in a ParameterizedMethodSuite. + /// + /// The MethodInfo for which a test is to be built + /// A Test representing one or more method invocations + public Test BuildFrom(MethodInfo method) + { + return BuildFrom(method, null); + } + + #endregion + + #region ITestCaseBuilder2 Members + + /// + /// Determines if the method can be used to build an NUnit test + /// test method of some kind. The method must normally be marked + /// with an identifying attriute for this to be true. + /// + /// Note that this method does not check that the signature + /// of the method for validity. If we did that here, any + /// test methods with invalid signatures would be passed + /// over in silence in the test run. Since we want such + /// methods to be reported, the check for validity is made + /// in BuildFrom rather than here. + /// + /// A MethodInfo for the method being used as a test method + /// The test suite being built, to which the new test would be added + /// True if the builder can create a test case from this method + public bool CanBuildFrom(MethodInfo method, Test parentSuite) + { + return CanBuildFrom(method); + } + + /// + /// Build a Test from the provided MethodInfo. Depending on + /// whether the method takes arguments and on the availability + /// of test case data, this method may return a single test + /// or a group of tests contained in a ParameterizedMethodSuite. + /// + /// The MethodInfo for which a test is to be built + /// The test fixture being populated, or null + /// A Test representing one or more method invocations + public Test BuildFrom(MethodInfo method, Test parentSuite) + { + return testCaseProvider.HasTestCasesFor(method) + ? BuildParameterizedMethodSuite(method, parentSuite) + : BuildSingleTestMethod(method, parentSuite, null); + } + + #endregion + + #region Implementation + + /// + /// Builds a ParameterizedMetodSuite containing individual + /// test cases for each set of parameters provided for + /// this method. + /// + /// The MethodInfo for which a test is to be built + /// The test suite for which the method is being built + /// A ParameterizedMethodSuite populated with test cases + public Test BuildParameterizedMethodSuite(MethodInfo method, Test parentSuite) + { + ParameterizedMethodSuite methodSuite = new ParameterizedMethodSuite(method); + methodSuite.ApplyAttributesToTest(method); + + foreach (ITestCaseData testcase in testCaseProvider.GetTestCasesFor(method)) + { + ParameterSet parms = testcase as ParameterSet; + if (parms == null) + parms = new ParameterSet(testcase); + + TestMethod test = BuildSingleTestMethod(method, parentSuite, parms); + + methodSuite.Add(test); + } + + return methodSuite; + } + + /// + /// Builds a single NUnitTestMethod, either as a child of the fixture + /// or as one of a set of test cases under a ParameterizedTestMethodSuite. + /// + /// The MethodInfo from which to construct the TestMethod + /// The suite or fixture to which the new test will be added + /// The ParameterSet to be used, or null + /// + private TestMethod BuildSingleTestMethod(MethodInfo method, Test parentSuite, ParameterSet parms) + { + TestMethod testMethod = new TestMethod(method, parentSuite); + + testMethod.Seed = randomizer.Next(); + + string prefix = method.ReflectedType.FullName; + + // Needed to give proper fullname to test in a parameterized fixture. + // Without this, the arguments to the fixture are not included. + if (parentSuite != null) + { + prefix = parentSuite.FullName; + //testMethod.FullName = prefix + "." + testMethod.Name; + } + + if (CheckTestMethodSignature(testMethod, parms)) + { + if (parms == null) + testMethod.ApplyAttributesToTest(method); + + foreach (ICommandDecorator decorator in method.GetCustomAttributes(typeof(ICommandDecorator), true)) + testMethod.CustomDecorators.Add(decorator); + + ExpectedExceptionAttribute[] attributes = + (ExpectedExceptionAttribute[])method.GetCustomAttributes(typeof(ExpectedExceptionAttribute), false); + + if (attributes.Length > 0) + { + ExpectedExceptionAttribute attr = attributes[0]; + string handlerName = attr.Handler; + if (handlerName != null && GetExceptionHandler(testMethod.FixtureType, handlerName) == null) + MarkAsNotRunnable( + testMethod, + string.Format("The specified exception handler {0} was not found", handlerName)); + + testMethod.CustomDecorators.Add(new ExpectedExceptionDecorator(attr.ExceptionData)); + } + } + + if (parms != null) + { + // NOTE: After the call to CheckTestMethodSignature, the Method + // property of testMethod may no longer be the same as the + // original MethodInfo, so we reassign it here. + method = testMethod.Method; + + if (parms.TestName != null) + { + testMethod.Name = parms.TestName; + testMethod.FullName = prefix + "." + parms.TestName; + } + else if (parms.OriginalArguments != null) + { + string name = MethodHelper.GetDisplayName(method, parms.OriginalArguments); + testMethod.Name = name; + testMethod.FullName = prefix + "." + name; + } + + parms.ApplyToTest(testMethod); + } + + return testMethod; + } + + #endregion + + #region Helper Methods + + /// + /// Helper method that checks the signature of a TestMethod and + /// any supplied parameters to determine if the test is valid. + /// + /// Currently, NUnitTestMethods are required to be public, + /// non-abstract methods, either static or instance, + /// returning void. They may take arguments but the values must + /// be provided or the TestMethod is not considered runnable. + /// + /// Methods not meeting these criteria will be marked as + /// non-runnable and the method will return false in that case. + /// + /// The TestMethod to be checked. If it + /// is found to be non-runnable, it will be modified. + /// Parameters to be used for this test, or null + /// True if the method signature is valid, false if not + private static bool CheckTestMethodSignature(TestMethod testMethod, ParameterSet parms) + { + if (testMethod.Method.IsAbstract) + { + return MarkAsNotRunnable(testMethod, "Method is abstract"); + } + + if (!testMethod.Method.IsPublic) + { + return MarkAsNotRunnable(testMethod, "Method is not public"); + } + +#if NETCF + // TODO: Get this to work + if (testMethod.Method.IsGenericMethodDefinition) + { + return MarkAsNotRunnable(testMethod, "Generic test methods are not yet supported under .NET CF"); + } +#endif + + ParameterInfo[] parameters = testMethod.Method.GetParameters(); + int argsNeeded = parameters.Length; + + object[] arglist = null; + int argsProvided = 0; + + if (parms != null) + { + testMethod.parms = parms; + testMethod.RunState = parms.RunState; + + arglist = parms.Arguments; + + if (arglist != null) + argsProvided = arglist.Length; + + if (testMethod.RunState != RunState.Runnable) + return false; + } + + Type returnType = testMethod.Method.ReturnType; + if (returnType.Equals(typeof(void))) + { + if (parms != null && parms.HasExpectedResult) + return MarkAsNotRunnable(testMethod, "Method returning void cannot have an expected result"); + } + else + { +#if NET_4_5 + if (MethodHelper.IsAsyncMethod(testMethod.Method)) + { + bool returnsGenericTask = returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>); + if (returnsGenericTask && (parms == null|| !parms.HasExpectedResult && !parms.ExceptionExpected)) + return MarkAsNotRunnable(testMethod, "Async test method must have Task or void return type when no result is expected"); + else if (!returnsGenericTask && parms != null && parms.HasExpectedResult) + return MarkAsNotRunnable(testMethod, "Async test method must have Task return type when a result is expected"); + } + else +#endif + if (parms == null || !parms.HasExpectedResult && !parms.ExceptionExpected) + return MarkAsNotRunnable(testMethod, "Method has non-void return value, but no result is expected"); + } + + if (argsProvided > 0 && argsNeeded == 0) + { + return MarkAsNotRunnable(testMethod, "Arguments provided for method not taking any"); + } + + if (argsProvided == 0 && argsNeeded > 0) + { + return MarkAsNotRunnable(testMethod, "No arguments were provided"); + } + + if (argsProvided != argsNeeded) + { + return MarkAsNotRunnable(testMethod, "Wrong number of arguments provided"); + } + +#if CLR_2_0 || CLR_4_0 +#if !NETCF + if (testMethod.Method.IsGenericMethodDefinition) + { + Type[] typeArguments = GetTypeArgumentsForMethod(testMethod.Method, arglist); + foreach (object o in typeArguments) + if (o == null) + { + return MarkAsNotRunnable(testMethod, "Unable to determine type arguments for method"); + } + + testMethod.method = testMethod.Method.MakeGenericMethod(typeArguments); + parameters = testMethod.Method.GetParameters(); + } +#endif +#endif + + if (arglist != null && parameters != null) + TypeHelper.ConvertArgumentList(arglist, parameters); + + return true; + } + +#if CLR_2_0 || CLR_4_0 +#if !NETCF + private static Type[] GetTypeArgumentsForMethod(MethodInfo method, object[] arglist) + { + Type[] typeParameters = method.GetGenericArguments(); + Type[] typeArguments = new Type[typeParameters.Length]; + ParameterInfo[] parameters = method.GetParameters(); + + for (int typeIndex = 0; typeIndex < typeArguments.Length; typeIndex++) + { + Type typeParameter = typeParameters[typeIndex]; + + for (int argIndex = 0; argIndex < parameters.Length; argIndex++) + { + if (parameters[argIndex].ParameterType.Equals(typeParameter)) + typeArguments[typeIndex] = TypeHelper.BestCommonType( + typeArguments[typeIndex], + arglist[argIndex].GetType()); + } + } + + return typeArguments; + } +#endif +#endif + + private static MethodInfo GetExceptionHandler(Type fixtureType, string name) + { + return fixtureType.GetMethod( + name, + BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + null, + new Type[] { typeof(System.Exception) }, + null); + } + + private static bool MarkAsNotRunnable(TestMethod testMethod, string reason) + { + testMethod.RunState = RunState.NotRunnable; + testMethod.Properties.Set(PropertyNames.SkipReason, reason); + return false; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/NUnitTestFixtureBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/NUnitTestFixtureBuilder.cs new file mode 100644 index 00000000000..46c09be47c9 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/NUnitTestFixtureBuilder.cs @@ -0,0 +1,349 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Text; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +using NUnit.Framework.Extensibility; + +namespace NUnit.Framework.Builders +{ + /// + /// Built-in SuiteBuilder for NUnit TestFixture + /// + public class NUnitTestFixtureBuilder : ISuiteBuilder + { + #region Static Fields + + static readonly string NO_TYPE_ARGS_MSG = + "Fixture type contains generic parameters. You must either provide " + + "Type arguments or specify constructor arguments that allow NUnit " + + "to deduce the Type arguments."; + + #endregion + + #region Instance Fields + /// + /// The NUnitTestFixture being constructed; + /// + private TestFixture fixture; + + private Extensibility.ITestCaseBuilder2 testBuilder; + + #endregion + + #region Constructor + + public NUnitTestFixtureBuilder() + { + testBuilder = new NUnitTestCaseBuilder(); + } + + #endregion + + #region ISuiteBuilder Methods + /// + /// Checks to see if the fixture type has the TestFixtureAttribute + /// + /// The fixture type to check + /// True if the fixture can be built, false if not + public bool CanBuildFrom(Type type) + { + if ( type.IsAbstract && !type.IsSealed ) + return false; + + if (type.IsDefined(typeof(TestFixtureAttribute), true)) + return true; + +#if CLR_2_0 || CLR_4_0 + // Generics must have a TestFixtureAttribute + if (type.IsGenericTypeDefinition) + return false; +#endif + + return Reflect.HasMethodWithAttribute(type, typeof(NUnit.Framework.TestAttribute)) || + Reflect.HasMethodWithAttribute(type, typeof(NUnit.Framework.TestCaseAttribute)) || + Reflect.HasMethodWithAttribute(type, typeof(NUnit.Framework.TestCaseSourceAttribute)) || + Reflect.HasMethodWithAttribute(type, typeof(NUnit.Framework.TheoryAttribute)); + } + + /// + /// Build a TestSuite from type provided. + /// + /// + /// + public Test BuildFrom(Type type) + { + TestFixtureAttribute[] attrs = GetTestFixtureAttributes(type); + +#if CLR_2_0 || CLR_4_0 + if (type.IsGenericType) + return BuildMultipleFixtures(type, attrs); +#endif + + switch (attrs.Length) + { + case 0: + return BuildSingleFixture(type, null); + case 1: + object[] args = (object[])attrs[0].Arguments; + return args == null || args.Length == 0 + ? BuildSingleFixture(type, attrs[0]) + : BuildMultipleFixtures(type, attrs); + default: + return BuildMultipleFixtures(type, attrs); + } + } + #endregion + + #region Helper Methods + + private Test BuildMultipleFixtures(Type type, TestFixtureAttribute[] attrs) + { + TestSuite suite = new ParameterizedFixtureSuite(type); + + if (attrs.Length > 0) + { + foreach (TestFixtureAttribute attr in attrs) + suite.Add(BuildSingleFixture(type, attr)); + } + else + { + suite.RunState = RunState.NotRunnable; + suite.Properties.Set(PropertyNames.SkipReason, NO_TYPE_ARGS_MSG); + } + + return suite; + } + + private Test BuildSingleFixture(Type type, TestFixtureAttribute attr) + { + object[] arguments = null; + + if (attr != null) + { + arguments = (object[])attr.Arguments; + +#if CLR_2_0 || CLR_4_0 + if (type.ContainsGenericParameters) + { + Type[] typeArgs = (Type[])attr.TypeArgs; + if( typeArgs.Length > 0 || + TypeHelper.CanDeduceTypeArgsFromArgs(type, arguments, ref typeArgs)) + { + type = TypeHelper.MakeGenericType(type, typeArgs); + } + } +#endif + } + + this.fixture = new TestFixture(type, arguments); + CheckTestFixtureIsValid(fixture); + + fixture.ApplyAttributesToTest(type); + + if (fixture.RunState == RunState.Runnable && attr != null) + { + if (attr.Ignore) + { + fixture.RunState = RunState.Ignored; + fixture.Properties.Set(PropertyNames.SkipReason, attr.IgnoreReason); + } + } + + AddTestCases(type); + + return this.fixture; + } + + /// + /// Method to add test cases to the newly constructed fixture. + /// + /// + private void AddTestCases( Type fixtureType ) + { + IList methods = fixtureType.GetMethods( + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static ); + + foreach(MethodInfo method in methods) + { + Test test = BuildTestCase(method, this.fixture); + + if(test != null) + { + this.fixture.Add( test ); + } + } + } + + /// + /// Method to create a test case from a MethodInfo and add + /// it to the fixture being built. It first checks to see if + /// any global TestCaseBuilder addin wants to build the + /// test case. If not, it uses the internal builder + /// collection maintained by this fixture builder. After + /// building the test case, it applies any decorators + /// that have been installed. + /// + /// The default implementation has no test case builders. + /// Derived classes should add builders to the collection + /// in their constructor. + /// + /// The MethodInfo for which a test is to be created + /// The test suite being built. + /// A newly constructed Test + private Test BuildTestCase( MethodInfo method, TestSuite suite ) + { + return testBuilder.CanBuildFrom(method, suite) + ? testBuilder.BuildFrom(method, suite) + : null; + } + + private void CheckTestFixtureIsValid(TestFixture fixture) + { + Type fixtureType = fixture.FixtureType; + +#if CLR_2_0 || CLR_4_0 + if (fixtureType.ContainsGenericParameters) + { + SetNotRunnable(fixture, NO_TYPE_ARGS_MSG); + return; + } +#endif + if( !IsStaticClass(fixtureType) && !HasValidConstructor(fixtureType, fixture.arguments) ) + { + SetNotRunnable(fixture, "No suitable constructor was found"); + return; + } + + if (!CheckSetUpTearDownMethods(fixture, fixture.SetUpMethods)) + return; + if (!CheckSetUpTearDownMethods(fixture, fixture.TearDownMethods)) + return; + if (!CheckSetUpTearDownMethods(fixture, Reflect.GetMethodsWithAttribute(fixture.FixtureType, typeof(TestFixtureSetUpAttribute), true))) + return; + CheckSetUpTearDownMethods(fixture, Reflect.GetMethodsWithAttribute(fixture.FixtureType, typeof(TestFixtureTearDownAttribute), true)); + } + + private static bool HasValidConstructor(Type fixtureType, object[] args) + { + Type[] argTypes; + + // Note: This could be done more simply using + // Type.EmptyTypes and Type.GetTypeArray() but + // they don't exist in all runtimes we support. + if (args == null) + argTypes = new Type[0]; + else + { + argTypes = new Type[args.Length]; + + int index = 0; + foreach (object arg in args) + argTypes[index++] = arg.GetType(); + } + + return fixtureType.GetConstructor(argTypes) != null; + } + + private void SetNotRunnable(TestFixture fixture, string reason) + { + fixture.RunState = RunState.NotRunnable; + fixture.Properties.Set(PropertyNames.SkipReason, reason); + } + + private static bool IsStaticClass(Type type) + { + return type.IsAbstract && type.IsSealed; + } + + private bool CheckSetUpTearDownMethods(TestFixture fixture, MethodInfo[] methods) + { + foreach (MethodInfo method in methods) + if (method.IsAbstract || + !method.IsPublic && !method.IsFamily || + method.GetParameters().Length > 0 || + !method.ReturnType.Equals(typeof(void))) + { + SetNotRunnable(fixture, string.Format("Invalid signature for Setup or TearDown method: {0}", method.Name)); + return false; + } + + return true; + } + + /// + /// Get TestFixtureAttributes following a somewhat obscure + /// set of rules to eliminate spurious duplication of fixtures. + /// 1. If there are any attributes with args, they are the only + /// ones returned and those without args are ignored. + /// 2. No more than one attribute without args is ever returned. + /// + private TestFixtureAttribute[] GetTestFixtureAttributes(Type type) + { + TestFixtureAttribute[] attrs = + (TestFixtureAttribute[])type.GetCustomAttributes(typeof(TestFixtureAttribute), true); + + // Just return - no possibility of duplication + if (attrs.Length <= 1) + return attrs; + + int withArgs = 0; + bool[] hasArgs = new bool[attrs.Length]; + + // Count and record those attrs with arguments + for (int i = 0; i < attrs.Length; i++) + { + TestFixtureAttribute attr = attrs[i]; + + if (attr.Arguments.Length > 0 || attr.TypeArgs.Length > 0) + { + withArgs++; + hasArgs[i] = true; + } + } + + // If all attributes have args, just return them + if (withArgs == attrs.Length) + return attrs; + + // If all attributes are without args, just return the first found + if (withArgs == 0) + return new TestFixtureAttribute[] { attrs[0] }; + + // Some of each type, so extract those with args + int count = 0; + TestFixtureAttribute[] result = new TestFixtureAttribute[withArgs]; + for (int i = 0; i < attrs.Length; i++) + if (hasArgs[i]) + result[count++] = attrs[i]; + + return result; + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/PairwiseStrategy.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/PairwiseStrategy.cs new file mode 100644 index 00000000000..597d447db12 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/PairwiseStrategy.cs @@ -0,0 +1,754 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using System.Text; +using NUnit.Framework.Api; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// PairwiseStrategy creates test cases by combining the parameter + /// data so that all possible pairs of data items are used. + /// + public class PairwiseStrategy : CombiningStrategy + { + internal class FleaRand + { + private const int FleaRandSize = 256; + + private uint b; + private uint c; + private uint d; + private uint z; + + private uint[] m = new uint[FleaRandSize]; + private uint[] r = new uint[FleaRandSize]; + + private uint q; + + /// + /// Initializes a new instance of the class. + /// + /// The seed. + public FleaRand(uint seed) + { + this.b = seed; + this.c = seed; + this.d = seed; + this.z = seed; + + for (int i = 0; i < this.m.Length; i++) + { + this.m[i] = seed; + } + + for (int i = 0; i < 10; i++) + { + this.Batch(); + } + + this.q = 0; + } + + public uint Next() + { + if (this.q == 0) + { + this.Batch(); + this.q = (uint)this.r.Length - 1; + } + else + { + this.q--; + } + + return this.r[this.q]; + } + + private void Batch() + { + uint a; + uint b = this.b; + uint c = this.c + (++this.z); + uint d = this.d; + + for (int i = 0; i < this.r.Length; i++) + { + a = this.m[b % this.m.Length]; + this.m[b % this.m.Length] = d; + d = (c << 19) + (c >> 13) + b; + c = b ^ this.m[i]; + b = a + d; + this.r[i] = c; + } + + this.b = b; + this.c = c; + this.d = d; + } + } + + internal class FeatureInfo + { + public const string Names = "abcdefghijklmnopqrstuvwxyz"; + + public readonly int Dimension; + public readonly int Feature; + + public FeatureInfo(int dimension, int feature) + { + this.Dimension = dimension; + this.Feature = feature; + } + +#if DEBUG + public override string ToString() + { + return (this.Dimension + 1).ToString() + FeatureInfo.Names[this.Feature]; + } +#endif + } + + internal class Tuple + { +#if CLR_2_0 || CLR_4_0 + private readonly List features = new List(); +#else + private readonly ArrayList features = new ArrayList(); +#endif + + public int Count + { + get + { + return this.features.Count; + } + } + + public FeatureInfo this[int index] + { + get + { + return (FeatureInfo)this.features[index]; + } + } + + public void Add(FeatureInfo feature) + { + this.features.Add(feature); + } + +#if DEBUG + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.Append('('); + + for (int i = 0; i < this.features.Count; i++) + { + if (i > 0) + { + sb.Append(' '); + } + + sb.Append(this.features[i].ToString()); + } + + sb.Append(')'); + + return sb.ToString(); + } +#endif + } + + internal class TupleCollection + { +#if CLR_2_0 || CLR_4_0 + private readonly List tuples = new List(); +#else + private readonly ArrayList tuples = new ArrayList(); +#endif + + public int Count + { + get + { + return this.tuples.Count; + } + } + + public Tuple this[int index] + { + get + { + return (Tuple)this.tuples[index]; + } + } + + public void Add(Tuple tuple) + { + this.tuples.Add(tuple); + } + + public void RemoveAt(int index) + { + this.tuples.RemoveAt(index); + } + } + + internal class TestCase + { + public readonly int[] Features; + + public TestCase(int numberOfDimensions) + { + this.Features = new int[numberOfDimensions]; + } + + public bool IsTupleCovered(Tuple tuple) + { + for (int i = 0; i < tuple.Count; i++) + { + if (this.Features[tuple[i].Dimension] != tuple[i].Feature) + { + return false; + } + } + + return true; + } + +#if DEBUG + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < this.Features.Length; i++) + { + if (i > 0) + { + sb.Append(' '); + } + + sb.Append(i + 1); + sb.Append(FeatureInfo.Names[this.Features[i]]); + } + + return sb.ToString(); + } +#endif + } + + internal class TestCaseCollection : IEnumerable + { +#if CLR_2_0 || CLR_4_0 + private readonly List testCases = new List(); +#else + private readonly ArrayList testCases = new ArrayList(); +#endif + + public void Add(TestCase testCase) + { + this.testCases.Add(testCase); + } + + public IEnumerator GetEnumerator() + { + return this.testCases.GetEnumerator(); + } + + public bool IsTupleCovered(Tuple tuple) + { + foreach (TestCase testCase in this.testCases) + { + if (testCase.IsTupleCovered(tuple)) + { + return true; + } + } + + return false; + } + } + + internal class PairwiseTestCaseGenerator + { + private const int MaxTupleLength = 2; + + private readonly FleaRand random = new FleaRand(0); + + private readonly int[] dimensions; + + private readonly TupleCollection[][] uncoveredTuples; + + private readonly int[][] currentTupleLength; + + private readonly TestCaseCollection testCases = new TestCaseCollection(); + + public PairwiseTestCaseGenerator(int[] dimensions) + { + this.dimensions = dimensions; + + this.uncoveredTuples = new TupleCollection[this.dimensions.Length][]; + + for (int d = 0; d < this.uncoveredTuples.Length; d++) + { + this.uncoveredTuples[d] = new TupleCollection[this.dimensions[d]]; + + for (int f = 0; f < this.dimensions[d]; f++) + { + this.uncoveredTuples[d][f] = new TupleCollection(); + } + } + + this.currentTupleLength = new int[this.dimensions.Length][]; + + for (int d = 0; d < this.dimensions.Length; d++) + { + this.currentTupleLength[d] = new int[this.dimensions[d]]; + } + } + + public IEnumerable GetTestCases() + { + this.CreateTestCases(); + + this.SelfTest(); + + return this.testCases; + } + + private void CreateTestCases() + { + while (true) + { + this.ExtendTupleSet(); + + Tuple tuple = this.FindTupleToCover(); + + if (tuple == null) + { + return; + } + + TestCase testCase = this.FindGoodTestCase(tuple); + + this.RemoveTuplesCoveredBy(testCase); + + this.testCases.Add(testCase); + } + } + + private void ExtendTupleSet() + { + for (int d = 0; d < this.dimensions.Length; d++) + { + for (int f = 0; f < this.dimensions[d]; f++) + { + this.ExtendTupleSet(d, f); + } + } + } + + private void ExtendTupleSet(int dimension, int feature) + { + // If tuples for [dimension][feature] already exists, it's no needs to add more tuples. + if (this.uncoveredTuples[dimension][feature].Count > 0) + { + return; + } + + // If maximum tuple length for [dimension][feature] is reached, it's no needs to add more tuples. + if (this.currentTupleLength[dimension][feature] == MaxTupleLength) + { + return; + } + + this.currentTupleLength[dimension][feature]++; + + int tupleLength = this.currentTupleLength[dimension][feature]; + + if (tupleLength == 1) + { + Tuple tuple = new Tuple(); + + tuple.Add(new FeatureInfo(dimension, feature)); + + if (this.testCases.IsTupleCovered(tuple)) + { + return; + } + + this.uncoveredTuples[dimension][feature].Add(tuple); + } + else + { + for (int d = 0; d < this.dimensions.Length; d++) + { + for (int f = 0; f < this.dimensions[d]; f++) + { + Tuple tuple = new Tuple(); + tuple.Add(new FeatureInfo(d, f)); + + if (tuple[0].Dimension == dimension) + { + continue; + } + + tuple.Add(new FeatureInfo(dimension, feature)); + + if (this.testCases.IsTupleCovered(tuple)) + { + continue; + } + + this.uncoveredTuples[dimension][feature].Add(tuple); + } + } + } + } + + private Tuple FindTupleToCover() + { + int tupleLength = MaxTupleLength; + int tupleCount = 0; + Tuple tuple = null; + + for (int d = 0; d < this.dimensions.Length; d++) + { + for (int f = 0; f < this.dimensions[d]; f++) + { + if (this.currentTupleLength[d][f] < tupleLength) + { + tupleLength = this.currentTupleLength[d][f]; + tupleCount = this.uncoveredTuples[d][f].Count; + tuple = this.uncoveredTuples[d][f][0]; + } + else + { + if (this.currentTupleLength[d][f] == tupleLength && this.uncoveredTuples[d][f].Count > tupleCount) + { + tupleCount = this.uncoveredTuples[d][f].Count; + tuple = this.uncoveredTuples[d][f][0]; + } + } + } + } + + return tuple; + } + + private TestCase FindGoodTestCase(Tuple tuple) + { + TestCase bestTest = null; + int bestCoverage = -1; + + for (int i = 0; i < 5; i++) + { + TestCase test = new TestCase(this.dimensions.Length); + + int coverage = this.CreateTestCase(tuple, test); + + if (coverage > bestCoverage) + { + bestTest = test; + bestCoverage = coverage; + } + } + + return bestTest; + } + + private int CreateTestCase(Tuple tuple, TestCase test) + { + // Create a random test case... + for (int i = 0; i < test.Features.Length; i++) + { + test.Features[i] = (int)(this.random.Next() % this.dimensions[i]); + } + + // ...and inject the tuple into it! + for (int i = 0; i < tuple.Count; i++) + { + test.Features[tuple[i].Dimension] = tuple[i].Feature; + } + + return this.MaximizeCoverage(test, tuple); + } + + private int MaximizeCoverage(TestCase test, Tuple tuple) + { + int[] dimensionOrder = this.GetMutableDimensions(tuple); + + while (true) + { + bool progress = false; + int totalCoverage = 1; + + // Scramble dimensions. + for (int i = dimensionOrder.Length; i > 1; i--) + { + int j = (int)(this.random.Next() % i); + int t = dimensionOrder[i - 1]; + dimensionOrder[i - 1] = dimensionOrder[j]; + dimensionOrder[j] = t; + } + + // For each dimension that can be modified... + for (int i = 0; i < dimensionOrder.Length; i++) + { + int d = dimensionOrder[i]; + +#if CLR_2_0 || CLR_4_0 + List bestFeatures = new List(); +#else + ArrayList bestFeatures = new ArrayList(); +#endif + + int bestCoverage = this.CountTuplesCovered(test, d, test.Features[d]); + + int bestTupleLength = this.currentTupleLength[d][test.Features[d]]; + + // For each feature that can be modified, check if it can extend coverage. + for (int f = 0; f < this.dimensions[d]; f++) + { + test.Features[d] = f; + + int coverage = this.CountTuplesCovered(test, d, f); + + if (this.currentTupleLength[d][f] < bestTupleLength) + { + progress = true; + bestTupleLength = this.currentTupleLength[d][f]; + bestCoverage = coverage; + bestFeatures.Clear(); + bestFeatures.Add(f); + } + else + { + if (this.currentTupleLength[d][f] == bestTupleLength && coverage >= bestCoverage) + { + if (coverage > bestCoverage) + { + progress = true; + bestCoverage = coverage; + bestFeatures.Clear(); + } + + bestFeatures.Add(f); + } + } + } + + if (bestFeatures.Count == 1) + { + test.Features[d] = (int)bestFeatures[0]; + } + else + { + test.Features[d] = (int)bestFeatures[(int)(this.random.Next() % bestFeatures.Count)]; + } + + totalCoverage += bestCoverage; + } + + if (!progress) + { + return totalCoverage; + } + } + } + + private int[] GetMutableDimensions(Tuple tuple) + { + bool[] immutableDimensions = new bool[this.dimensions.Length]; + + for (int i = 0; i < tuple.Count; i++) + { + immutableDimensions[tuple[i].Dimension] = true; + } + +#if CLR_2_0 || CLR_4_0 + List mutableDimensions = new List(); +#else + ArrayList mutableDimensions = new ArrayList(); +#endif + + for (int i = 0; i < this.dimensions.Length; i++) + { + if (!immutableDimensions[i]) + { + mutableDimensions.Add(i); + } + } + +#if CLR_2_0 || CLR_4_0 + return mutableDimensions.ToArray(); +#else + return (int[])mutableDimensions.ToArray(typeof(int)); +#endif + } + + private int CountTuplesCovered(TestCase test, int dimension, int feature) + { + int tuplesCovered = 0; + + TupleCollection tuples = this.uncoveredTuples[dimension][feature]; + + for (int i = 0; i < tuples.Count; i++) + { + if (test.IsTupleCovered(tuples[i])) + { + tuplesCovered++; + } + } + + return tuplesCovered; + } + + private void RemoveTuplesCoveredBy(TestCase testCase) + { + for (int d = 0; d < this.uncoveredTuples.Length; d++) + { + for (int f = 0; f < this.uncoveredTuples[d].Length; f++) + { + TupleCollection tuples = this.uncoveredTuples[d][f]; + + for (int i = tuples.Count - 1; i >= 0; i--) + { + if (testCase.IsTupleCovered(tuples[i])) + { + tuples.RemoveAt(i); + } + } + } + } + } + + private void SelfTest() + { + for (int d1 = 0; d1 < this.dimensions.Length - 1; d1++) + { + for (int d2 = d1 + 1; d2 < this.dimensions.Length; d2++) + { + for (int f1 = 0; f1 < this.dimensions[d1]; f1++) + { + for (int f2 = 0; f2 < this.dimensions[d2]; f2++) + { + Tuple tuple = new Tuple(); + tuple.Add(new FeatureInfo(d1, f1)); + tuple.Add(new FeatureInfo(d2, f2)); + + if (!this.testCases.IsTupleCovered(tuple)) + { + throw new Exception("PairwiseStrategy self-test failed : Not all pairs are covered!"); + } + } + } + } + } + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The sources. + public PairwiseStrategy(IEnumerable[] sources) : base(sources) { } + + /// + /// Gets the test cases generated by this strategy instance. + /// + /// The test cases. +#if CLR_2_0 || CLR_4_0 + public override IEnumerable GetTestCases() + { + List testCases = new List(); +#else + public override IEnumerable GetTestCases() + { + ArrayList testCases = new ArrayList(); +#endif + ObjectList[] valueSet = CreateValueSet(); + int[] dimensions = CreateDimensions(valueSet); + + IEnumerable pairwiseTestCases = new PairwiseTestCaseGenerator(dimensions).GetTestCases(); + + foreach (TestCase pairwiseTestCase in pairwiseTestCases) + { + object[] testData = new object[pairwiseTestCase.Features.Length]; + + for (int i = 0; i < pairwiseTestCase.Features.Length; i++) + { + testData[i] = valueSet[i][pairwiseTestCase.Features[i]]; + } + + ParameterSet parms = new ParameterSet(); + parms.Arguments = testData; + testCases.Add(parms); + } + + return testCases; + } + + private ObjectList[] CreateValueSet() + { + ObjectList[] valueSet = new ObjectList[Sources.Length]; + + for (int i = 0; i < valueSet.Length; i++) + { + ObjectList values = new ObjectList(); + + foreach (object value in Sources[i]) + { + values.Add(value); + } + + valueSet[i] = values; + } + + return valueSet; + } + + private int[] CreateDimensions(ObjectList[] valueSet) + { + int[] dimensions = new int[valueSet.Length]; + + for (int i = 0; i < valueSet.Length; i++) + { + dimensions[i] = valueSet[i].Count; + } + + return dimensions; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/ParameterDataProvider.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/ParameterDataProvider.cs new file mode 100644 index 00000000000..6eacc4740e8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/ParameterDataProvider.cs @@ -0,0 +1,79 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using System.Collections; +using NUnit.Framework.Api; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// ParameterDataProvider supplies individual argument values for + /// single parameters using attributes derived from DataAttribute. + /// + public class ParameterDataProvider : IParameterDataProvider + { + #region IDataPointProvider Members + + /// + /// Determine whether any data is available for a parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// + /// True if any data is available, otherwise false. + /// + public bool HasDataFor(ParameterInfo parameter) + { + return parameter.IsDefined(typeof(DataAttribute), false); + } + + /// + /// Return an IEnumerable providing data for use with the + /// supplied parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// + /// An IEnumerable providing the required data + /// + public IEnumerable GetDataFor(ParameterInfo parameter) + { + ObjectList data = new ObjectList(); + + foreach (Attribute attr in parameter.GetCustomAttributes(typeof(DataAttribute), false)) + { + IParameterDataSource source = attr as IParameterDataSource; + if (source != null) + foreach (object item in source.GetData(parameter)) + data.Add(item); + } + + return data; + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/ProviderCache.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/ProviderCache.cs new file mode 100644 index 00000000000..1486593d397 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/ProviderCache.cs @@ -0,0 +1,102 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Text; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + class ProviderCache + { +#if CLR_2_0 || CLR_4_0 + private static Dictionary instances = new Dictionary(); +#else + private static IDictionary instances = new Hashtable(); +#endif + + public static object GetInstanceOf(Type providerType) + { + return GetInstanceOf(providerType, null); + } + + public static object GetInstanceOf(Type providerType, object[] providerArgs) + { + CacheEntry entry = new CacheEntry(providerType, providerArgs); + +#if CLR_2_0 || CLR_4_0 + object instance = instances.ContainsKey(entry) +#else + object instance = instances.Contains(entry) +#endif + ?instances[entry] + : null; + + if (instance == null) + instances[entry] = instance = Reflect.Construct(providerType, providerArgs); + + return instance; + } + + public static void Clear() + { + foreach (CacheEntry key in instances.Keys) + { + IDisposable provider = instances[key] as IDisposable; + if (provider != null) + provider.Dispose(); + } + + instances.Clear(); + } + + class CacheEntry + { + private Type providerType; + private object[] providerArgs; + + public CacheEntry(Type providerType, object[] providerArgs) + { + this.providerType = providerType; + this.providerArgs = providerArgs; + } + + public override bool Equals(object obj) + { + CacheEntry other = obj as CacheEntry; + if (other == null) return false; + + return this.providerType == other.providerType; + } + + public override int GetHashCode() + { + return providerType.GetHashCode(); + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/SequentialStrategy.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/SequentialStrategy.cs new file mode 100644 index 00000000000..b4f8e1b38d7 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Builders/SequentialStrategy.cs @@ -0,0 +1,88 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Extensibility; +using NUnit.Framework.Internal; + +namespace NUnit.Framework.Builders +{ + /// + /// SequentialStrategy creates test cases by using all of the + /// parameter data sources in parallel, substituting null + /// when any of them run out of data. + /// + public class SequentialStrategy : CombiningStrategy + { + /// + /// Initializes a new instance of the class. + /// + /// The sources. + public SequentialStrategy(IEnumerable[] sources) : base(sources) { } + + /// + /// Gets the test cases generated by the CombiningStrategy. + /// + /// The test cases. +#if CLR_2_0 || CLR_4_0 + public override IEnumerable GetTestCases() + { + List testCases = new List(); +#else + public override IEnumerable GetTestCases() + { + ArrayList testCases = new ArrayList(); +#endif + + for (; ; ) + { + bool gotData = false; + object[] testdata = new object[Sources.Length]; + + for (int i = 0; i < Sources.Length; i++) + if (Enumerators[i].MoveNext()) + { + testdata[i] = Enumerators[i].Current; + gotData = true; + } + else + testdata[i] = null; + + if (!gotData) + break; + + ParameterSet parms = new ParameterSet(); + parms.Arguments = testdata; + testCases.Add(parms); + } + + return testCases; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ApplyChangesToContextCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ApplyChangesToContextCommand.cs new file mode 100644 index 00000000000..58b9435f5c5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ApplyChangesToContextCommand.cs @@ -0,0 +1,65 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Threading; +namespace NUnit.Framework.Internal.Commands +{ + /// + /// ContextSettingsCommand applies specified changes to the + /// TestExecutionContext prior to running a test. No special + /// action is needed after the test runs, since the prior + /// context will be restored automatically. + /// + class ApplyChangesToContextCommand : DelegatingTestCommand + { + private IApplyToContext[] _changes; + + public ApplyChangesToContextCommand(TestCommand innerCommand, IApplyToContext[] changes) + : base(innerCommand) + { + _changes = changes; + } + + public override TestResult Execute(TestExecutionContext context) + { + try + { + foreach (IApplyToContext change in _changes) + change.ApplyToContext(context); + + context.CurrentResult = innerCommand.Execute(context); + } + catch (Exception ex) + { +#if !NETCF && !SILVERLIGHT + if (ex is ThreadAbortException) + Thread.ResetAbort(); +#endif + context.CurrentResult.RecordException(ex); + } + + return context.CurrentResult; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/CommandDecoratorList.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/CommandDecoratorList.cs new file mode 100644 index 00000000000..5b77b850e39 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/CommandDecoratorList.cs @@ -0,0 +1,48 @@ +using System; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// CommandDecoratorList maintains a list of ICommandDecorators + /// and is able to sort them by level so that they are applied + /// in the proper order. + /// +#if CLR_2_0 || CLR_4_0 + public class CommandDecoratorList : System.Collections.Generic.List +#else + public class CommandDecoratorList : System.Collections.ArrayList +#endif + { + /// + /// Order command decorators by the stage at which they apply. + /// + public void OrderByStage() + { + Sort(CommandDecoratorComparison); + } + +#if CLR_2_0 || CLR_4_0 + private int CommandDecoratorComparison(ICommandDecorator x, ICommandDecorator y) + { + return x.Stage.CompareTo(y.Stage); + } +#else + private CommandDecoratorComparer CommandDecoratorComparison = new CommandDecoratorComparer(); + + private class CommandDecoratorComparer : System.Collections.IComparer + { + public int Compare(object x, object y) + { + ICommandDecorator xDecorator = x as ICommandDecorator; + ICommandDecorator yDecorator = y as ICommandDecorator; + + if (xDecorator == null || yDecorator == null) + return 0; + + return xDecorator.Stage.CompareTo(yDecorator.Stage); + } + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/CommandStage.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/CommandStage.cs new file mode 100644 index 00000000000..7740d5cb8e0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/CommandStage.cs @@ -0,0 +1,81 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// The CommandStage enumeration represents the defined stages + /// of execution for a series of TestCommands. The int values + /// of the enum are used to apply decorators in the proper + /// order. Lower values are applied first and are therefore + /// "closer" to the actual test execution. + /// + /// + /// No CommandStage is defined for actual invocation of the test or + /// for creation of the context. Execution may be imagined as + /// proceeding from the bottom of the list upwards, with cleanup + /// after the test running in the opposite order. + /// + public enum CommandStage + { + /// + /// Use an application-defined default value. + /// + Default, + + // NOTE: The test is actually invoked here. + + /// + /// Make adjustments needed before and after running + /// the raw test - that is, after any SetUp has run + /// and before TearDown. + /// + BelowSetUpTearDown, + + /// + /// Run SetUp and TearDown for the test. This stage is used + /// internally by NUnit and should not normally appear + /// in user-defined decorators. + /// + SetUpTearDown, + + /// + /// Make adjustments needed before and after running + /// the entire test - including SetUp and TearDown. + /// + AboveSetUpTearDown + + // Note: The context is created here and destroyed + // after the test has run. + + // Command Stages + // Create/Destroy Context + // Modify/Restore Context + // Create/Destroy fixture object + // Repeat test + // Create/Destroy thread + // Modify overall result + // SetUp/TearDown + // Modify raw result + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/DelegatingTestCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/DelegatingTestCommand.cs new file mode 100644 index 00000000000..91e3acaa73c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/DelegatingTestCommand.cs @@ -0,0 +1,46 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TODO: Documentation needed for class + /// + public abstract class DelegatingTestCommand : TestCommand + { + /// TODO: Documentation needed for field + protected TestCommand innerCommand; + + /// + /// TODO: Documentation needed for constructor + /// + /// + protected DelegatingTestCommand(TestCommand innerCommand) + : base(innerCommand.Test) + { + this.innerCommand = innerCommand; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ExpectedExceptionCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ExpectedExceptionCommand.cs new file mode 100644 index 00000000000..5d545730c1b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ExpectedExceptionCommand.cs @@ -0,0 +1,220 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TODO: Documentation needed for class + /// + public class ExpectedExceptionCommand : DelegatingTestCommand + { + private ExpectedExceptionData exceptionData; + + /// + /// Initializes a new instance of the class. + /// + /// The inner command. + /// The exception data. + public ExpectedExceptionCommand(TestCommand innerCommand, ExpectedExceptionData exceptionData) + : base(innerCommand) + { + this.exceptionData = exceptionData; + } + + + /// + /// Runs the test, saving a TestResult in the supplied TestExecutionContext + /// + /// The context in which the test is to be run. + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + try + { + context.CurrentResult = innerCommand.Execute(context); + + if (context.CurrentResult.ResultState == ResultState.Success) + ProcessNoException(context); + } + catch (Exception ex) + { +#if !NETCF && !SILVERLIGHT + if (ex is ThreadAbortException) + Thread.ResetAbort(); +#endif + ProcessException(ex, context); + } + + return context.CurrentResult; + } + + /// + /// Handles processing when no exception was thrown. + /// + /// The execution context. + public void ProcessNoException(TestExecutionContext context) + { + context.CurrentResult.SetResult(ResultState.Failure, NoExceptionMessage()); + } + + /// + /// Handles processing when an exception was thrown. + /// + /// The exception. + /// The execution context. + public void ProcessException(Exception exception, TestExecutionContext context) + { + if (exception is NUnitException) + exception = exception.InnerException; + + if (IsExpectedExceptionType(exception)) + { + if (IsExpectedMessageMatch(exception)) + { + if (context.TestObject != null) + { + MethodInfo exceptionMethod = exceptionData.GetExceptionHandler(context.TestObject.GetType()); + if (exceptionMethod != null) + { + Reflect.InvokeMethod(exceptionMethod, context.TestObject, exception); + } + else + { + IExpectException handler = context.TestObject as IExpectException; + if (handler != null) + handler.HandleException(exception); + } + } + + context.CurrentResult.SetResult(ResultState.Success); + } + else + { + context.CurrentResult.SetResult(ResultState.Failure, WrongTextMessage(exception), GetStackTrace(exception)); + } + } + else + { + context.CurrentResult.RecordException(exception); + + // If it shows as an error, change it to a failure due to the wrong type + if (context.CurrentResult.ResultState == ResultState.Error) + context.CurrentResult.SetResult(ResultState.Failure, WrongTypeMessage(exception), GetStackTrace(exception)); + } + } + + #region Helper Methods + + private bool IsExpectedExceptionType(Exception exception) + { + return exceptionData.ExpectedExceptionName == null || + exceptionData.ExpectedExceptionName.Equals(exception.GetType().FullName); + } + + private bool IsExpectedMessageMatch(Exception exception) + { + if (exceptionData.ExpectedMessage == null) + return true; + + switch (exceptionData.MatchType) + { + case MessageMatch.Exact: + default: + return exceptionData.ExpectedMessage.Equals(exception.Message); + case MessageMatch.Contains: + return exception.Message.IndexOf(exceptionData.ExpectedMessage) >= 0; + case MessageMatch.Regex: + return Regex.IsMatch(exception.Message, exceptionData.ExpectedMessage); + case MessageMatch.StartsWith: + return exception.Message.StartsWith(exceptionData.ExpectedMessage); + } + } + + private string NoExceptionMessage() + { + string expectedType = exceptionData.ExpectedExceptionName == null ? "An Exception" : exceptionData.ExpectedExceptionName; + return CombineWithUserMessage(expectedType + " was expected"); + } + + private string WrongTypeMessage(Exception exception) + { + return CombineWithUserMessage( + "An unexpected exception type was thrown" + Env.NewLine + + "Expected: " + exceptionData.ExpectedExceptionName + Env.NewLine + + " but was: " + exception.GetType().FullName + " : " + exception.Message); + } + + private string WrongTextMessage(Exception exception) + { + string expectedText; + switch (exceptionData.MatchType) + { + default: + case MessageMatch.Exact: + expectedText = "Expected: "; + break; + case MessageMatch.Contains: + expectedText = "Expected message containing: "; + break; + case MessageMatch.Regex: + expectedText = "Expected message matching: "; + break; + case MessageMatch.StartsWith: + expectedText = "Expected message starting: "; + break; + } + + return CombineWithUserMessage( + "The exception message text was incorrect" + Env.NewLine + + expectedText + exceptionData.ExpectedMessage + Env.NewLine + + " but was: " + exception.Message); + } + + private string CombineWithUserMessage(string message) + { + if (exceptionData.UserMessage == null) + return message; + return exceptionData.UserMessage + Env.NewLine + message; + } + + private string GetStackTrace(Exception exception) + { + try + { + return exception.StackTrace; + } + catch (Exception) + { + return "No stack trace available"; + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ICommandDecorator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ICommandDecorator.cs new file mode 100644 index 00000000000..a40fdce6577 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/ICommandDecorator.cs @@ -0,0 +1,54 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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 NUnit.Framework.Internal.Commands +{ + /// + /// ICommandDecorator is implemented by attributes and other + /// objects able to decorate a TestCommand, usually by wrapping + /// it with an outer command. + /// + public interface ICommandDecorator + { + /// + /// The stage of command execution to which this decorator applies. + /// + CommandStage Stage { get; } + + /// + /// The priority of this decorator as compared to other decorators + /// in the same Stage. Lower values are applied first. + /// + int Priority { get; } + + /// + /// Decorate a command, usually by wrapping it with another + /// command, and return the decorated command. + /// + /// The command to be decorated + /// The decorated command + TestCommand Decorate(TestCommand command); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/MaxTimeCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/MaxTimeCommand.cs new file mode 100644 index 00000000000..f9a7b0ff0b5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/MaxTimeCommand.cs @@ -0,0 +1,88 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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.Diagnostics; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TODO: Documentation needed for class + /// + public class MaxTimeCommand : DelegatingTestCommand + { + private int maxTime; + + /// + /// Initializes a new instance of the class. + /// TODO: Add a comment about where the max time is retrieved. + /// + /// The inner command. + public MaxTimeCommand(TestCommand innerCommand) + : base(innerCommand) + { + this.maxTime = Test.Properties.GetSetting(PropertyNames.MaxTime, 0); + } + + /// + /// Runs the test, saving a TestResult in the supplied TestExecutionContext + /// + /// The context in which the test should run. + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + // TODO: This command duplicates the calculation of the + // duration of the test because that calculation is + // normally performed at a higher level. Most likely, + // we should move the maxtime calculation to the + // higher level eventually. +#if (CLR_2_0 || CLR_4_0) && !SILVERLIGHT && !NETCF_2_0 + long startTicks = Stopwatch.GetTimestamp(); +#endif + + TestResult testResult = innerCommand.Execute(context); + +#if (CLR_2_0 || CLR_4_0) && !SILVERLIGHT && !NETCF_2_0 + long tickCount = Stopwatch.GetTimestamp() - startTicks; + double seconds = (double)tickCount / Stopwatch.Frequency; + testResult.Duration = TimeSpan.FromSeconds(seconds); +#else + testResult.Duration = DateTime.Now - context.StartTime; +#endif + + if (testResult.ResultState == ResultState.Success) + { + //int elapsedTime = (int)Math.Round(testResult.Time * 1000.0); + double elapsedTime = testResult.Duration.TotalMilliseconds; + + if (elapsedTime > maxTime) + testResult.SetResult(ResultState.Failure, + string.Format("Elapsed time of {0}ms exceeds maximum of {1}ms", + elapsedTime, maxTime)); + } + + return testResult; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/OneTimeSetUpCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/OneTimeSetUpCommand.cs new file mode 100644 index 00000000000..67534215127 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/OneTimeSetUpCommand.cs @@ -0,0 +1,74 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Reflection; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// OneTimeSetUpCommand runs any one-time setup methods for a suite, + /// constructing the user test object if necessary. + /// + public class OneTimeSetUpCommand : TestCommand + { + private readonly TestSuite suite; + private readonly Type fixtureType; + private readonly object[] arguments; + + /// + /// Constructs a OneTimeSetUpComand for a suite + /// + /// The suite to which the command applies + public OneTimeSetUpCommand(TestSuite suite) : base(suite) + { + this.suite = suite; + this.fixtureType = suite.FixtureType; + this.arguments = suite.arguments; + } + + /// + /// Overridden to run the one-time setup for a suite. + /// + /// The TestExecutionContext to be used. + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + if (fixtureType != null) + { + if (context.TestObject == null && !IsStaticClass(fixtureType)) + context.TestObject = Reflect.Construct(fixtureType, arguments); + + foreach (MethodInfo method in Reflect.GetMethodsWithAttribute(fixtureType, typeof(TestFixtureSetUpAttribute), true)) + Reflect.InvokeMethod(method, method.IsStatic ? null : context.TestObject); + } + + return context.CurrentResult; + } + + private static bool IsStaticClass(Type type) + { + return type.IsAbstract && type.IsSealed; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/OneTimeTearDownCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/OneTimeTearDownCommand.cs new file mode 100644 index 00000000000..e5dad4f69e4 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/OneTimeTearDownCommand.cs @@ -0,0 +1,106 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// OneTimeTearDownCommand performs any teardown actions + /// specified for a suite and calls Dispose on the user + /// test object, if any. + /// + public class OneTimeTearDownCommand : TestCommand + { + private readonly TestSuite suite; + private readonly Type fixtureType; + + /// + /// Construct a OneTimeTearDownCommand + /// + /// The test suite to which the command applies + public OneTimeTearDownCommand(TestSuite suite) + : base(suite) + { + this.suite = suite; + this.fixtureType = suite.FixtureType; + } + + /// + /// Overridden to run the teardown methods specified on the test. + /// + /// The TestExecutionContext to be used. + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + TestResult suiteResult = context.CurrentResult; + + if (fixtureType != null) + { + MethodInfo[] teardownMethods = + Reflect.GetMethodsWithAttribute(fixtureType, typeof(TestFixtureTearDownAttribute), true); + + try + { + int index = teardownMethods.Length; + while (--index >= 0) + { + MethodInfo fixtureTearDown = teardownMethods[index]; + if (!fixtureTearDown.IsStatic && context.TestObject == null) + Console.WriteLine("TestObject should not be null!!!"); + Reflect.InvokeMethod(fixtureTearDown, fixtureTearDown.IsStatic ? null : context.TestObject); + } + + IDisposable disposable = context.TestObject as IDisposable; + if (disposable != null) + disposable.Dispose(); + } + catch (Exception ex) + { + // Error in TestFixtureTearDown or Dispose causes the + // suite to be marked as a error, even if + // all the contained tests passed. + NUnitException nex = ex as NUnitException; + if (nex != null) + ex = nex.InnerException; + + // TODO: Can we move this logic into TestResult itself? + string message = "TearDown : " + ExceptionHelper.BuildMessage(ex); + if (suiteResult.Message != null) + message = suiteResult.Message + NUnit.Env.NewLine + message; + + string stackTrace = "--TearDown" + NUnit.Env.NewLine + ExceptionHelper.BuildStackTrace(ex); + if (suiteResult.StackTrace != null) + stackTrace = suiteResult.StackTrace + NUnit.Env.NewLine + stackTrace; + + // TODO: What about ignore exceptions in teardown? + suiteResult.SetResult(ResultState.Error, message, stackTrace); + } + } + + return suiteResult; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/RepeatedTestCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/RepeatedTestCommand.cs new file mode 100644 index 00000000000..5ff005b1584 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/RepeatedTestCommand.cs @@ -0,0 +1,72 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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. +// *********************************************************************** +#if false +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TODO: Documentation needed for class + /// + public class RepeatedTestCommand : DelegatingTestCommand + { + private int repeatCount; + + /// + /// Initializes a new instance of the class. + /// TODO: Add a comment about where the repeat count is retrieved. + /// + /// The inner command. + public RepeatedTestCommand(TestCommand innerCommand) + : base(innerCommand) + { + this.repeatCount = Test.Properties.GetSetting(PropertyNames.RepeatCount, 1); + } + + /// + /// Runs the test, saving a TestResult in the supplied TestExecutionContext. + /// + /// The context in which the test should run. + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + int count = repeatCount; + + while (count-- > 0) + { + context.CurrentResult = innerCommand.Execute(context); + + // TODO: We may want to change this so that all iterations are run + if (context.CurrentResult.ResultState == ResultState.Failure || + context.CurrentResult.ResultState == ResultState.Error || + context.CurrentResult.ResultState == ResultState.Cancelled) + { + break; + } + } + + return context.CurrentResult; + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/SetUpTearDownCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/SetUpTearDownCommand.cs new file mode 100644 index 00000000000..e281e694755 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/SetUpTearDownCommand.cs @@ -0,0 +1,143 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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.Reflection; +using System.Threading; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// SetUpTearDownDecorator decorates a test command by running + /// a setup method before the original command and a teardown + /// method after it has executed. + /// + public class SetUpTearDownDecorator : ICommandDecorator + { + CommandStage ICommandDecorator.Stage + { + get { return CommandStage.SetUpTearDown; } + } + + int ICommandDecorator.Priority + { + get { return 0; } + } + + TestCommand ICommandDecorator.Decorate(TestCommand command) + { + return new SetUpTearDownCommand(command); + } + } + + /// + /// TODO: Documentation needed for class + /// + public class SetUpTearDownCommand : DelegatingTestCommand + { + private readonly MethodInfo[] setUpMethods; + private readonly MethodInfo[] tearDownMethods; + + /// + /// Initializes a new instance of the class. + /// + /// The inner command. + public SetUpTearDownCommand(TestCommand innerCommand) + : base(innerCommand) + { + this.setUpMethods = Test.SetUpMethods; + this.tearDownMethods = Test.TearDownMethods; + } + + /// + /// Runs the test, saving a TestResult in the supplied TestExecutionContext. + /// + /// The context in which the test should run. + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + try + { + RunSetUpMethods(context); + + context.CurrentResult = innerCommand.Execute(context); + } + catch (Exception ex) + { +#if !NETCF && !SILVERLIGHT + if (ex is ThreadAbortException) + Thread.ResetAbort(); +#endif + context.CurrentResult.RecordException(ex); + } + finally + { + RunTearDownMethods(context); + } + + return context.CurrentResult; + } + + private void RunSetUpMethods(TestExecutionContext context) + { + if (setUpMethods != null) + foreach (MethodInfo setUpMethod in setUpMethods) + Reflect.InvokeMethod(setUpMethod, setUpMethod.IsStatic ? null : context.TestObject); + } + + private void RunTearDownMethods(TestExecutionContext context) + { + try + { + if (tearDownMethods != null) + { + int index = tearDownMethods.Length; + while (--index >= 0) + Reflect.InvokeMethod(tearDownMethods[index], tearDownMethods[index].IsStatic ? null : context.TestObject); + } + } + catch (Exception ex) + { + if (ex is NUnitException) + ex = ex.InnerException; + + // TODO: What about ignore exceptions in teardown? + ResultState resultState = context.CurrentResult.ResultState == ResultState.Cancelled + ? ResultState.Cancelled + : ResultState.Error; + + // TODO: Can we move this logic into TestResult itself? + string message = "TearDown : " + ExceptionHelper.BuildMessage(ex); + if (context.CurrentResult.Message != null) + message = context.CurrentResult.Message + NUnit.Env.NewLine + message; + + string stackTrace = "--TearDown" + NUnit.Env.NewLine + ExceptionHelper.BuildStackTrace(ex); + if (context.CurrentResult.StackTrace != null) + stackTrace = context.CurrentResult.StackTrace + NUnit.Env.NewLine + stackTrace; + + context.CurrentResult.SetResult(resultState, message, stackTrace); + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/SkipCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/SkipCommand.cs new file mode 100644 index 00000000000..8dbe25d8414 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/SkipCommand.cs @@ -0,0 +1,80 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TODO: Documentation needed for class + /// + public class SkipCommand : TestCommand + { + /// + /// Initializes a new instance of the class. + /// + /// The test being skipped. + public SkipCommand(Test test) : base(test) + { + } + + /// + /// Overridden to simply set the CurrentResult to the + /// appropriate Skipped state. + /// + /// The execution context for the test + /// A TestResult + public override TestResult Execute(TestExecutionContext context) + { + //TestResult testResult = this.Test.MakeTestResult(); + TestResult testResult = context.CurrentResult; + + switch (Test.RunState) + { + default: + case RunState.Skipped: + testResult.SetResult(ResultState.Skipped, GetSkipReason()); + break; + case RunState.Ignored: + testResult.SetResult(ResultState.Ignored, GetSkipReason()); + break; + case RunState.NotRunnable: + testResult.SetResult(ResultState.NotRunnable, GetSkipReason(), GetProviderStackTrace()); + break; + } + + return testResult; + } + + private string GetSkipReason() + { + return (string)Test.Properties.Get(PropertyNames.SkipReason); + } + + private string GetProviderStackTrace() + { + return (string)Test.Properties.Get(PropertyNames.ProviderStackTrace); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TestCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TestCommand.cs new file mode 100644 index 00000000000..02db2ea495b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TestCommand.cs @@ -0,0 +1,71 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TestCommand is the abstract base class for all test commands + /// in the framework. A TestCommand represents a single stage in + /// the execution of a test, e.g.: SetUp/TearDown, checking for + /// Timeout, verifying the returned result from a method, etc. + /// + /// TestCommands may decorate other test commands so that the + /// execution of a lower-level command is nested within that + /// of a higher level command. All nested commands are executed + /// synchronously, as a single unit. Scheduling test execution + /// on separate threads is handled at a higher level, using the + /// task dispatcher. + /// + public abstract class TestCommand + { + private Test test; + + /// + /// Construct a TestCommand for a test. + /// + /// The test to be executed + public TestCommand(Test test) + { + this.test = test; + } + + #region ITestCommandMembers + + /// + /// Gets the test associated with this command. + /// + public Test Test + { + get { return test; } + } + + /// + /// Runs the test in a specified context, returning a TestResult. + /// + /// The TestExecutionContext to be used for running the test. + /// A TestResult + public abstract TestResult Execute(TestExecutionContext context); + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TestMethodCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TestMethodCommand.cs new file mode 100644 index 00000000000..8e7f75e71d2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TestMethodCommand.cs @@ -0,0 +1,168 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TestMethodCommand is the lowest level concrete command + /// used to run actual test cases. + /// + public class TestMethodCommand : TestCommand + { + private const string TaskWaitMethod = "Wait"; + private const string TaskResultProperty = "Result"; + private const string SystemAggregateException = "System.AggregateException"; + private const string InnerExceptionsProperty = "InnerExceptions"; + private const BindingFlags TaskResultPropertyBindingFlags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public; + private readonly TestMethod testMethod; + private readonly object[] arguments; + + /// + /// Initializes a new instance of the class. + /// + /// The test. + public TestMethodCommand(TestMethod testMethod) : base(testMethod) + { + this.testMethod = testMethod; + this.arguments = testMethod.Arguments; + } + + /// + /// Runs the test, saving a TestResult in the execution context, as + /// well as returning it. If the test has an expected result, it + /// is asserts on that value. Since failed tests and errors throw + /// an exception, this command must be wrapped in an outer command, + /// will handle that exception and records the failure. This role + /// is usually played by the SetUpTearDown command. + /// + /// The execution context + public override TestResult Execute(TestExecutionContext context) + { + // TODO: Decide if we should handle exceptions here + object result = RunTestMethod(context); + + if (testMethod.HasExpectedResult) + NUnit.Framework.Assert.AreEqual(testMethod.ExpectedResult, result); + + context.CurrentResult.SetResult(ResultState.Success); + // TODO: Set assert count here? + //context.CurrentResult.AssertCount = context.AssertCount; + return context.CurrentResult; + } + + private object RunTestMethod(TestExecutionContext context) + { +#if NET_4_5 + if (MethodHelper.IsAsyncMethod(testMethod.Method)) + return RunAsyncTestMethod(context); + //{ + // if (testMethod.Method.ReturnType == typeof(void)) + // return RunAsyncVoidTestMethod(context); + // else + // return RunAsyncTaskTestMethod(context); + //} + else +#endif + return RunNonAsyncTestMethod(context); + } + +#if NET_4_5 + private object RunAsyncTestMethod(TestExecutionContext context) + { + using (AsyncInvocationRegion region = AsyncInvocationRegion.Create(testMethod.Method)) + { + object result = Reflect.InvokeMethod(testMethod.Method, context.TestObject, arguments); + + try + { + return region.WaitForPendingOperationsToComplete(result); + } + catch (Exception e) + { + throw new NUnitException("Rethrown", e); + } + } + } +#endif + + private object RunNonAsyncTestMethod(TestExecutionContext context) + { + return Reflect.InvokeMethod(testMethod.Method, context.TestObject, arguments); + } + +#if NET_4_5x + private object RunAsyncVoidTestMethod(TestExecutionContext context) + { + var previousContext = SynchronizationContext.Current; + var currentContext = new AsyncSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(currentContext); + + try + { + object result = Reflect.InvokeMethod(testMethod.Method, context.TestObject, arguments); + + currentContext.WaitForOperationCompleted(); + + if (currentContext.Exceptions.Count > 0) + throw new NUnitException("Rethrown", currentContext.Exceptions[0]); + + return result; + } + finally + { + SynchronizationContext.SetSynchronizationContext(previousContext); + } + } + + private object RunAsyncTaskTestMethod(TestExecutionContext context) + { + try + { + object task = Reflect.InvokeMethod(testMethod.Method, context.TestObject, arguments); + + Reflect.InvokeMethod(testMethod.Method.ReturnType.GetMethod(TaskWaitMethod, new Type[0]), task); + PropertyInfo resultProperty = testMethod.Method.ReturnType.GetProperty(TaskResultProperty, TaskResultPropertyBindingFlags); + + return resultProperty != null ? resultProperty.GetValue(task, null) : null; + } + catch (NUnitException e) + { + if (e.InnerException != null && + e.InnerException.GetType().FullName.Equals(SystemAggregateException)) + { + IList inner = (IList)e.InnerException.GetType() + .GetProperty(InnerExceptionsProperty).GetValue(e.InnerException, null); + + throw new NUnitException("Rethrown", inner[0]); + } + + throw; + } + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TheoryResultCommand.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TheoryResultCommand.cs new file mode 100644 index 00000000000..efb062a9eeb --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Commands/TheoryResultCommand.cs @@ -0,0 +1,72 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Commands +{ + /// + /// TheoryResultCommand adjusts the result of a Theory so that + /// it fails if all the results were inconclusive. + /// + public class TheoryResultCommand : DelegatingTestCommand + { + /// + /// Constructs a TheoryResultCommand + /// + /// The command to be wrapped by this one + public TheoryResultCommand(TestCommand command) : base(command) { } + + /// + /// Overridden to call the inner command and adjust the result + /// in case all chlid results were inconclusive. + /// + /// + /// + public override TestResult Execute(TestExecutionContext context) + { + TestResult theoryResult = innerCommand.Execute(context); + + if (theoryResult.ResultState == ResultState.Success) + { + if (!theoryResult.HasChildren) + theoryResult.SetResult(ResultState.Failure, "No test cases were provided", null); + else + { + bool wasInconclusive = true; + foreach (TestResult childResult in theoryResult.Children) + if (childResult.ResultState == ResultState.Success) + { + wasInconclusive = false; + break; + } + + if (wasInconclusive) + theoryResult.SetResult(ResultState.Failure, "All test cases were inconclusive", null); + } + } + + return theoryResult; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/CultureDetector.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/CultureDetector.cs new file mode 100644 index 00000000000..5d26eb43bde --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/CultureDetector.cs @@ -0,0 +1,142 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Reflection; +using System.Globalization; + +namespace NUnit.Framework.Internal +{ + /// + /// CultureDetector is a helper class used by NUnit to determine + /// whether a test should be run based on the current culture. + /// + public class CultureDetector + { + private CultureInfo currentCulture; + + // Set whenever we fail to support a list of platforms + private string reason = string.Empty; + + /// + /// Default constructor uses the current culutre. + /// + public CultureDetector() + { + this.currentCulture = CultureInfo.CurrentCulture; + } + + /// + /// Contruct a CultureDetector for a particular culture for testing. + /// + /// The culture to be used + public CultureDetector( string culture ) + { + this.currentCulture = new CultureInfo( culture ); + } + + /// + /// Test to determine if one of a collection of culturess + /// is being used currently. + /// + /// + /// + public bool IsCultureSupported( string[] cultures ) + { + foreach( string culture in cultures ) + if ( IsCultureSupported( culture ) ) + return true; + + return false; + } + + /// + /// Tests to determine if the current culture is supported + /// based on a culture attribute. + /// + /// The attribute to examine + /// + public bool IsCultureSupported( CultureAttribute cultureAttribute ) + { + string include = cultureAttribute.Include; + string exclude = cultureAttribute.Exclude; + + //try + //{ + if (include != null && !IsCultureSupported(include)) + { + reason = string.Format("Only supported under culture {0}", include); + return false; + } + + if (exclude != null && IsCultureSupported(exclude)) + { + reason = string.Format("Not supported under culture {0}", exclude); + return false; + } + //} + //catch( ArgumentException ex ) + //{ + // reason = string.Format( "Invalid culture: {0}", ex.ParamName ); + // return false; + //} + + return true; + } + + /// + /// Test to determine if the a particular culture or comma- + /// delimited set of cultures is in use. + /// + /// Name of the culture or comma-separated list of culture names + /// True if the culture is in use on the system + public bool IsCultureSupported( string culture ) + { + culture = culture.Trim(); + + if ( culture.IndexOf( ',' ) >= 0 ) + { + if ( IsCultureSupported( culture.Split( new char[] { ',' } ) ) ) + return true; + } + else + { + if( this.currentCulture.Name == culture || this.currentCulture.TwoLetterISOLanguageName == culture) + return true; + } + + this.reason = "Only supported under culture " + culture; + return false; + } + + /// + /// Return the last failure reason. Results are not + /// defined if called before IsSupported( Attribute ) + /// is called. + /// + public string Reason + { + get { return reason; } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ExceptionHelper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ExceptionHelper.cs new file mode 100644 index 00000000000..5a5d003fbfe --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ExceptionHelper.cs @@ -0,0 +1,95 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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.Globalization; +using System.Text; + +namespace NUnit.Framework.Internal +{ + /// + /// ExceptionHelper provides static methods for working with exceptions + /// + public class ExceptionHelper + { + // TODO: Move to a utility class + /// + /// Builds up a message, using the Message field of the specified exception + /// as well as any InnerExceptions. + /// + /// The exception. + /// A combined message string. + public static string BuildMessage(Exception exception) + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat(CultureInfo.CurrentCulture, "{0} : {1}", exception.GetType().ToString(), exception.Message); + + Exception inner = exception.InnerException; + while (inner != null) + { + sb.Append(NUnit.Env.NewLine); + sb.AppendFormat(CultureInfo.CurrentCulture, " ----> {0} : {1}", inner.GetType().ToString(), inner.Message); + inner = inner.InnerException; + } + + return sb.ToString(); + } + + /// + /// Builds up a message, using the Message field of the specified exception + /// as well as any InnerExceptions. + /// + /// The exception. + /// A combined stack trace. + public static string BuildStackTrace(Exception exception) + { + StringBuilder sb = new StringBuilder(GetStackTrace(exception)); + + Exception inner = exception.InnerException; + while (inner != null) + { + sb.Append(NUnit.Env.NewLine); + sb.Append("--"); + sb.Append(inner.GetType().Name); + sb.Append(NUnit.Env.NewLine); + sb.Append(GetStackTrace(inner)); + + inner = inner.InnerException; + } + + return sb.ToString(); + } + + private static string GetStackTrace(Exception exception) + { + try + { + return exception.StackTrace; + } + catch (Exception) + { + return "No stack trace available"; + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Extensibility/ParameterDataProviders.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Extensibility/ParameterDataProviders.cs new file mode 100644 index 00000000000..5c521c2fa45 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Extensibility/ParameterDataProviders.cs @@ -0,0 +1,85 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using System.Collections; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using NUnit.Framework.Builders; + +namespace NUnit.Framework.Extensibility +{ + class ParameterDataProviders : IParameterDataProvider + { +#if CLR_2_0 || CLR_4_0 + private List Extensions = new List(); +#else + private ArrayList Extensions = new ArrayList(); +#endif + + public ParameterDataProviders() + { + Extensions.Add(new ParameterDataProvider()); + Extensions.Add(new DatapointProvider()); + } + + #region IDataPointProvider Members + + /// + /// Determine whether any data is available for a parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// True if any data is available, otherwise false. + public bool HasDataFor(ParameterInfo parameter) + { + foreach (IParameterDataProvider provider in Extensions) + if (provider.HasDataFor(parameter)) + return true; + + return false; + } + + /// + /// Return an IEnumerable providing data for use with the + /// supplied parameter. + /// + /// A ParameterInfo representing one + /// argument to a parameterized test + /// An IEnumerable providing the required data + public IEnumerable GetDataFor(ParameterInfo parameter) + { + ObjectList list = new ObjectList(); + + foreach (IParameterDataProvider provider in Extensions) + if (provider.HasDataFor(parameter)) + foreach (object o in provider.GetDataFor(parameter)) + list.Add(o); + + return list; + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Extensibility/TestCaseProviders.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Extensibility/TestCaseProviders.cs new file mode 100644 index 00000000000..f46f17297f2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Extensibility/TestCaseProviders.cs @@ -0,0 +1,101 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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. +// *********************************************************************** + +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +using NUnit.Framework.Builders; + +namespace NUnit.Framework.Extensibility +{ + class TestCaseProviders : ITestCaseProvider + { +#if CLR_2_0 || CLR_4_0 + private List Extensions = new List(); +#else + private System.Collections.ArrayList Extensions = new System.Collections.ArrayList(); +#endif + + public TestCaseProviders() + { + this.Extensions.Add(new DataAttributeTestCaseProvider()); + this.Extensions.Add(new CombinatorialTestCaseProvider()); + } + + #region ITestCaseProvider Members + + /// + /// Determine whether any test cases are available for a parameterized method. + /// + /// A MethodInfo representing a parameterized test + /// True if any cases are available, otherwise false. + public bool HasTestCasesFor(MethodInfo method) + { + foreach (ITestCaseProvider provider in Extensions) + if (provider.HasTestCasesFor(method)) + return true; + + return false; + } + + /// + /// Return an enumeration providing test cases for use in + /// running a parameterized test. + /// + /// + /// +#if CLR_2_0 || CLR_4_0 + public System.Collections.Generic.IEnumerable GetTestCasesFor(MethodInfo method) + { + List testcases = new List(); +#else + public System.Collections.IEnumerable GetTestCasesFor(MethodInfo method) + { + System.Collections.ArrayList testcases = new System.Collections.ArrayList(); +#endif + + foreach (ITestCaseProvider provider in Extensions) + try + { + if (provider.HasTestCasesFor(method)) + foreach (ITestCaseData testcase in provider.GetTestCasesFor(method)) + testcases.Add(testcase); + } + catch (System.Reflection.TargetInvocationException ex) + { + testcases.Add(new ParameterSet(ex.InnerException)); + } + catch (System.Exception ex) + { + testcases.Add(new ParameterSet(ex)); + } + + return testcases; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/AndFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/AndFilter.cs new file mode 100644 index 00000000000..d265d451d0b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/AndFilter.cs @@ -0,0 +1,96 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Filters +{ + /// + /// Combines multiple filters so that a test must pass all + /// of them in order to pass this filter. + /// + [Serializable] + public class AndFilter : TestFilter + { +#if CLR_2_0 || CLR_4_0 + private List filters = new List(); +#else + private System.Collections.ArrayList filters = new System.Collections.ArrayList(); +#endif + + /// + /// Constructs an empty AndFilter + /// + public AndFilter() { } + + /// + /// Constructs an AndFilter from an array of filters + /// + /// + public AndFilter( params ITestFilter[] filters ) + { + this.filters.AddRange( filters ); + } + + /// + /// Adds a filter to the list of filters + /// + /// The filter to be added + public void Add( ITestFilter filter ) + { + this.filters.Add( filter ); + } + + /// + /// Checks whether the AndFilter is matched by a test + /// + /// The test to be matched + /// True if all the component filters pass, otherwise false + public override bool Pass( ITest test ) + { + foreach( ITestFilter filter in filters ) + if ( !filter.Pass( test ) ) + return false; + + return true; + } + + /// + /// Checks whether the AndFilter is matched by a test + /// + /// The test to be matched + /// True if all the component filters match, otherwise false + public override bool Match( ITest test ) + { + foreach( TestFilter filter in filters ) + if ( !filter.Match( test ) ) + return false; + + return true; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/CategoryExpression.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/CategoryExpression.cs new file mode 100644 index 00000000000..215ada3c858 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/CategoryExpression.cs @@ -0,0 +1,180 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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; + +namespace NUnit.Framework.Internal.Filters +{ + /// + /// CategoryExpression parses strings representing boolean + /// combinations of categories according to the following + /// grammar: + /// CategoryName ::= string not containing any of ',', '&', '+', '-' + /// CategoryFilter ::= CategoryName | CategoryFilter ',' CategoryName + /// CategoryPrimitive ::= CategoryFilter | '-' CategoryPrimitive + /// CategoryTerm ::= CategoryPrimitive | CategoryTerm '&' CategoryPrimitive + /// + public class CategoryExpression + { + static readonly char[] ops = new char[] { ',', ';', '-', '|', '+', '(', ')' }; + + private string text; + private int next; + private string token; + + private TestFilter filter; + + /// + /// Construct expression from a text string + /// + /// The text of the expression + public CategoryExpression(string text) + { + this.text = text; + this.next = 0; + } + + /// + /// Gets the TestFilter represented by the expression + /// + public TestFilter Filter + { + get + { + if( filter == null ) + { + filter = GetToken() == null + ? TestFilter.Empty + : GetExpression(); + } + + return filter; + } + } + + private TestFilter GetExpression() + { + TestFilter term = GetTerm(); + if ( token != "|" ) + return term; + + OrFilter filter = new OrFilter( term ); + + while ( token == "|" ) + { + GetToken(); + filter.Add( GetTerm() ); + } + + return filter; + } + + private TestFilter GetTerm() + { + TestFilter prim = GetPrimitive(); + if ( token != "+" && token != "-" ) + return prim; + + AndFilter filter = new AndFilter( prim ); + + while ( token == "+"|| token == "-" ) + { + string tok = token; + GetToken(); + prim = GetPrimitive(); + filter.Add( tok == "-" ? new NotFilter( prim ) : prim ); + } + + return filter; + } + + private TestFilter GetPrimitive() + { + if( token == "-" ) + { + GetToken(); + return new NotFilter( GetPrimitive() ); + } + else if( token == "(" ) + { + GetToken(); + TestFilter expr = GetExpression(); + GetToken(); // Skip ')' + return expr; + } + + return GetCategoryFilter(); + } + + private CategoryFilter GetCategoryFilter() + { + CategoryFilter filter = new CategoryFilter( token ); + + while( GetToken() == "," || token == ";" ) + filter.AddCategory( GetToken() ); + + return filter; + } + + private string GetToken() + { + SkipWhiteSpace(); + + if ( EndOfText() ) + token = null; + else if ( NextIsOperator() ) + token = text.Substring(next++, 1); + else + { + int index2 = text.IndexOfAny( ops, next ); + if ( index2 < 0 ) index2 = text.Length; + + token = text.Substring( next, index2 - next ).TrimEnd(); + next = index2; + } + + return token; + } + + private void SkipWhiteSpace() + { + while( next < text.Length && Char.IsWhiteSpace( text[next] ) ) + ++next; + } + + private bool EndOfText() + { + return next >= text.Length; + } + + private bool NextIsOperator() + { + foreach( char op in ops ) + if( op == text[next] ) + return true; + + return false; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/CategoryFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/CategoryFilter.cs new file mode 100644 index 00000000000..08b6ec16bbd --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/CategoryFilter.cs @@ -0,0 +1,118 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Text; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Filters +{ + /// + /// CategoryFilter is able to select or exclude tests + /// based on their categories. + /// + /// + [Serializable] + public class CategoryFilter : TestFilter + { +#if CLR_2_0 || CLR_4_0 + List categories = new List(); +#else + ArrayList categories = new ArrayList(); +#endif + + /// + /// Construct an empty CategoryFilter + /// + public CategoryFilter() + { + } + + /// + /// Construct a CategoryFilter using a single category name + /// + /// A category name + public CategoryFilter( string name ) + { + if ( name != null && name != string.Empty ) + categories.Add( name ); + } + + /// + /// Construct a CategoryFilter using an array of category names + /// + /// An array of category names + public CategoryFilter( string[] names ) + { + if ( names != null ) + categories.AddRange( names ); + } + + /// + /// Add a category name to the filter + /// + /// A category name + public void AddCategory(string name) + { + categories.Add( name ); + } + + /// + /// Check whether the filter matches a test + /// + /// The test to be matched + /// + public override bool Match(ITest test) + { + IList testCategories = test.Properties[PropertyNames.Category] as IList; + + if ( testCategories == null || testCategories.Count == 0) + return false; + + foreach( string cat in this.categories ) + if ( testCategories.Contains( cat ) ) + return true; + + return false; + } + + /// + /// Return the string representation of a category filter + /// + /// + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + for( int i = 0; i < categories.Count; i++ ) + { + if ( i > 0 ) sb.Append( ',' ); + sb.Append( categories[i] ); + } + return sb.ToString(); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/NotFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/NotFilter.cs new file mode 100644 index 00000000000..c62f79664c3 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/NotFilter.cs @@ -0,0 +1,97 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Filters +{ + /// + /// NotFilter negates the operation of another filter + /// + [Serializable] + public class NotFilter : TestFilter + { + ITestFilter baseFilter; + bool topLevel = false; + + /// + /// Construct a not filter on another filter + /// + /// The filter to be negated + public NotFilter( ITestFilter baseFilter) + { + this.baseFilter = baseFilter; + } + + /// + /// Indicates whether this is a top-level NotFilter, + /// requiring special handling of Explicit + /// + public bool TopLevel + { + get { return topLevel; } + set { topLevel = value; } + } + + /// + /// Gets the base filter + /// + public ITestFilter BaseFilter + { + get { return baseFilter; } + } + + /// + /// Check whether the filter matches a test + /// + /// The test to be matched + /// True if it matches, otherwise false + public override bool Match( ITest test ) + { + if (topLevel && test.RunState == RunState.Explicit) + return false; + + return !baseFilter.Pass( test ); + } + + /// + /// Determine whether any descendant of the test matches the filter criteria. + /// + /// The test to be matched + /// True if at least one descendant matches the filter criteria + protected override bool MatchDescendant(ITest test) + { + if (!test.HasChildren || test.Tests == null || topLevel && test.RunState == RunState.Explicit) + return false; + + foreach (ITest child in test.Tests) + { + if (Match(child) || MatchDescendant(child)) + return true; + } + + return false; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/OrFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/OrFilter.cs new file mode 100644 index 00000000000..418f8776197 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/OrFilter.cs @@ -0,0 +1,111 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Filters +{ + /// + /// Combines multiple filters so that a test must pass one + /// of them in order to pass this filter. + /// + [Serializable] + public class OrFilter : TestFilter + { +#if CLR_2_0 || CLR_4_0 + private List filters = new List(); +#else + private System.Collections.ArrayList filters = new System.Collections.ArrayList(); +#endif + + /// + /// Constructs an empty OrFilter + /// + public OrFilter() { } + + /// + /// Constructs an AndFilter from an array of filters + /// + /// + public OrFilter( params ITestFilter[] filters ) + { + this.filters.AddRange( filters ); + } + + /// + /// Adds a filter to the list of filters + /// + /// The filter to be added + public void Add( ITestFilter filter ) + { + this.filters.Add( filter ); + } + + /// + /// Return an array of the composing filters + /// + public ITestFilter[] Filters + { + get + { +#if CLR_2_0 || CLR_4_0 + return filters.ToArray(); +#else + return (ITestFilter[])filters.ToArray(typeof(ITestFilter)); +#endif + } + } + + /// + /// Checks whether the OrFilter is matched by a test + /// + /// The test to be matched + /// True if any of the component filters pass, otherwise false + public override bool Pass( ITest test ) + { + foreach( ITestFilter filter in filters ) + if ( filter.Pass( test ) ) + return true; + + return false; + } + + /// + /// Checks whether the OrFilter is matched by a test + /// + /// The test to be matched + /// True if any of the component filters match, otherwise false + public override bool Match( ITest test ) + { + foreach( TestFilter filter in filters ) + if ( filter.Match( test ) ) + return true; + + return false; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/SimpleCategoryExpression.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/SimpleCategoryExpression.cs new file mode 100644 index 00000000000..46c67185981 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/SimpleCategoryExpression.cs @@ -0,0 +1,43 @@ +namespace NUnit.Framework.Internal.Filters +{ + /// + /// SimpleCategoryFilter parses a basic string representing a + /// single category or a list of categories separated by commas + /// + public class SimpleCategoryExpression + { + private string text; + + private TestFilter filter; + + /// + /// Construct category filter from a text string + /// + /// A list of categories to parse + public SimpleCategoryExpression(string text) + { + this.text = text; + } + + /// + /// Gets the TestFilter represented by the expression + /// + public TestFilter Filter + { + get + { + if (filter == null) + { + filter = GetCategories(); + } + return filter; + } + } + + private TestFilter GetCategories() + { + string[] categories = text.Split(','); + return new CategoryFilter(categories); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/SimpleNameFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/SimpleNameFilter.cs new file mode 100644 index 00000000000..8e257e4bb0a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Filters/SimpleNameFilter.cs @@ -0,0 +1,93 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.Filters +{ + /// + /// SimpleName filter selects tests based on their name + /// + [Serializable] + public class SimpleNameFilter : TestFilter + { +#if CLR_2_0 || CLR_4_0 + private List names = new List(); +#else + private System.Collections.ArrayList names = new System.Collections.ArrayList(); +#endif + + /// + /// Construct an empty SimpleNameFilter + /// + public SimpleNameFilter() { } + + /// + /// Construct a SimpleNameFilter for a single name + /// + /// The name the filter will recognize. + public SimpleNameFilter(string nameToAdd) + { + Add(nameToAdd); + } + + /// + /// Construct a SimpleNameFilter for an array of names + /// + /// The names the filter will recognize. + public SimpleNameFilter(string[] namesToAdd) + { + foreach (string name in namesToAdd) + Add(name); + } + + /// + /// Add a name to a SimpleNameFilter + /// + /// The name to be added. + public void Add(string name) + { + Guard.ArgumentNotNullOrEmpty(name, "name"); + + names.Add(name); + } + + /// + /// Check whether the filter matches a test + /// + /// The test to be matched + /// True if it matches, otherwise false + public override bool Match( ITest test ) + { + foreach( string name in names ) + if ( test.FullName == name ) + return true; + + return false; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/IApplyToContext.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/IApplyToContext.cs new file mode 100644 index 00000000000..6f67c3fe8f6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/IApplyToContext.cs @@ -0,0 +1,39 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Internal +{ + /// + /// The IApplyToContext interface is implemented by attributes + /// that want to make changes to the execution context before + /// a test is run. + /// + public interface IApplyToContext + { + /// + /// Apply changes to the execution context + /// + /// The execution context + void ApplyToContext(TestExecutionContext context); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/IApplyToTest.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/IApplyToTest.cs new file mode 100644 index 00000000000..a0bdf7ed1af --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/IApplyToTest.cs @@ -0,0 +1,40 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// The IApplyToTest interface is implemented by self-applying + /// attributes that modify the state of a test in some way. + /// + public interface IApplyToTest + { + /// + /// Modifies a test as defined for the specific attribute. + /// + /// The test to modify + void ApplyToTest(Test test); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/InvalidTestFixtureException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/InvalidTestFixtureException.cs new file mode 100644 index 00000000000..8fce09bb91d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/InvalidTestFixtureException.cs @@ -0,0 +1,66 @@ +// *********************************************************************** +// Copyright (c) 2006 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Internal +{ + using System; +#if !NETCF + using System.Runtime.Serialization; +#endif + + /// + /// InvalidTestFixtureException is thrown when an appropriate test + /// fixture constructor using the provided arguments cannot be found. + /// + [Serializable] + public class InvalidTestFixtureException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public InvalidTestFixtureException() : base() {} + + /// + /// Initializes a new instance of the class. + /// + /// The message. + public InvalidTestFixtureException(string message) : base(message) + {} + + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// The inner. + public InvalidTestFixtureException(string message, Exception inner) : base(message, inner) + {} + +#if !NETCF && !SILVERLIGHT + /// + /// Serialization Constructor + /// + protected InvalidTestFixtureException(SerializationInfo info, + StreamingContext context) : base(info,context){} +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/MethodHelper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/MethodHelper.cs new file mode 100644 index 00000000000..43ba741a163 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/MethodHelper.cs @@ -0,0 +1,226 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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.Reflection; +using System.Text; + +namespace NUnit.Framework.Internal +{ + /// + /// MethodHelper provides static methods for working with methods. + /// + public class MethodHelper + { + /// + /// Gets the display name for a method as used by NUnit. + /// + /// The method for which a display name is needed. + /// The arguments provided. + /// The display name for the method + public static string GetDisplayName(MethodInfo method, object[] arglist) + { + StringBuilder sb = new StringBuilder(method.Name); + +#if CLR_2_0 || CLR_4_0 + if (method.IsGenericMethod) + { + sb.Append("<"); + int cnt = 0; + foreach (Type t in method.GetGenericArguments()) + { + if (cnt++ > 0) sb.Append(","); + sb.Append(t.Name); + } + sb.Append(">"); + } +#endif + + if (arglist != null) + { + sb.Append("("); + + for (int i = 0; i < arglist.Length; i++) + { + if (i > 0) sb.Append(","); + sb.Append(GetDisplayString(arglist[i])); + } + + sb.Append(")"); + } + + return sb.ToString(); + } + + private static string GetDisplayString(object arg) + { + string display = arg == null + ? "null" + : Convert.ToString(arg, System.Globalization.CultureInfo.InvariantCulture); + + if (arg is double) + { + double d = (double)arg; + + if (double.IsNaN(d)) + display = "double.NaN"; + else if (double.IsPositiveInfinity(d)) + display = "double.PositiveInfinity"; + else if (double.IsNegativeInfinity(d)) + display = "double.NegativeInfinity"; + else if (d == double.MaxValue) + display = "double.MaxValue"; + else if (d == double.MinValue) + display = "double.MinValue"; + else + { + if (display.IndexOf('.') == -1) + display += ".0"; + display += "d"; + } + } + else if (arg is float) + { + float f = (float)arg; + + if (float.IsNaN(f)) + display = "float.NaN"; + else if (float.IsPositiveInfinity(f)) + display = "float.PositiveInfinity"; + else if (float.IsNegativeInfinity(f)) + display = "float.NegativeInfinity"; + else if (f == float.MaxValue) + display = "float.MaxValue"; + else if (f == float.MinValue) + display = "float.MinValue"; + else + { + if (display.IndexOf('.') == -1) + display += ".0"; + display += "f"; + } + } + else if (arg is decimal) + { + decimal d = (decimal)arg; + if (d == decimal.MinValue) + display = "decimal.MinValue"; + else if (d == decimal.MaxValue) + display = "decimal.MaxValue"; + else + display += "m"; + } + else if (arg is long) + { + long l = (long)arg; + if (l == long.MinValue) + display = "long.MinValue"; + else if (l == long.MinValue) + display = "long.MaxValue"; + else + display += "L"; + } + else if (arg is ulong) + { + ulong ul = (ulong)arg; + if (ul == ulong.MinValue) + display = "ulong.MinValue"; + else if (ul == ulong.MinValue) + display = "ulong.MaxValue"; + else + display += "UL"; + } + else if (arg is string) + { + StringBuilder sb = new StringBuilder(); + sb.Append("\""); + foreach (char c in (string)arg) + sb.Append(EscapeControlChar(c)); + sb.Append("\""); + display = sb.ToString(); + } + else if (arg is char) + { + display = "\'" + EscapeControlChar((char)arg) + "\'"; + } + else if (arg is int) + { + int ival = (int)arg; + if (ival == int.MaxValue) + display = "int.MaxValue"; + else if (ival == int.MinValue) + display = "int.MinValue"; + } + + return display; + } + + private static string EscapeControlChar(char c) + { + switch (c) + { + case '\'': + return "\\\'"; + case '\"': + return "\\\""; + case '\\': + return "\\\\"; + case '\0': + return "\\0"; + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\f': + return "\\f"; + case '\n': + return "\\n"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + + case '\x0085': + case '\x2028': + case '\x2029': + return string.Format("\\x{0:X4}", (int)c); + + default: + return c.ToString(); + } + } + +#if NET_4_5 + /// + /// Returns true if the method specified by the argument + /// is an async method. + /// + public static bool IsAsyncMethod(MethodInfo method) + { + return method.IsDefined(typeof(System.Runtime.CompilerServices.AsyncStateMachineAttribute)); + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitException.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitException.cs new file mode 100644 index 00000000000..f201ce440d0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitException.cs @@ -0,0 +1,71 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Internal +{ + using System; +#if !NETCF + using System.Runtime.Serialization; +#endif + + /// + /// Thrown when an assertion failed. Here to preserve the inner + /// exception and hence its stack trace. + /// + [Serializable] + public class NUnitException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public NUnitException () : base() + {} + + /// + /// Initializes a new instance of the class. + /// + /// The error message that explains + /// the reason for the exception + public NUnitException(string message) : base (message) + {} + + /// + /// Initializes a new instance of the class. + /// + /// The error message that explains + /// the reason for the exception + /// The exception that caused the + /// current exception + public NUnitException(string message, Exception inner) : + base(message, inner) + {} + +#if !NETCF && !SILVERLIGHT + /// + /// Serialization Constructor + /// + protected NUnitException(SerializationInfo info, + StreamingContext context) : base(info,context){} +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitLiteTestAssemblyBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitLiteTestAssemblyBuilder.cs new file mode 100644 index 00000000000..4f3badd7106 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitLiteTestAssemblyBuilder.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections; +using System.IO; +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Builders; +using NUnit.Framework.Extensibility; + +namespace NUnit.Framework.Internal +{ + /// + /// DefaultTestAssemblyBuilder loads a single assembly and builds a TestSuite + /// containing test fixtures present in the assembly. + /// + public class NUnitLiteTestAssemblyBuilder : ITestAssemblyBuilder + { + #region Instance Fields + + /// + /// The loaded assembly + /// + Assembly assembly; + + #endregion + + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + public NUnitLiteTestAssemblyBuilder() + { + } + + #endregion + + #region Build Methods + /// + /// Build a suite of tests from a provided assembly + /// + /// The assembly from which tests are to be built + /// A dictionary of options to use in building the suite + /// + /// A TestSuite containing the tests found in the assembly + /// + public TestSuite Build(Assembly assembly, IDictionary options) + { + this.assembly = assembly; + + IList fixtureNames = options["LOAD"] as IList; + + IList fixtures = GetFixtures(assembly, fixtureNames); + + if (fixtures.Count > 0) + { +#if NETCF || SILVERLIGHT + AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(assembly); + return BuildTestAssembly(assemblyName.Name, fixtures); +#else + string assemblyPath = AssemblyHelper.GetAssemblyPath(assembly); + return BuildTestAssembly(assemblyPath, fixtures); +#endif + } + + return null; + } + + /// + /// Build a suite of tests given the filename of an assembly + /// + /// The filename of the assembly from which tests are to be built + /// A dictionary of options to use in building the suite + /// + /// A TestSuite containing the tests found in the assembly + /// + public TestSuite Build(string assemblyName, IDictionary options) + { + this.assembly = Load(assemblyName); + if (assembly == null) return null; + + IList fixtureNames = options["LOAD"] as IList; + + IList fixtures = GetFixtures(assembly, fixtureNames); + if (fixtures.Count > 0) + return BuildTestAssembly(assemblyName, fixtures); + + return null; + } + #endregion + + #region Helper Methods + + private Assembly Load(string path) + { +#if NETCF || SILVERLIGHT + return Assembly.Load(path); +#else + // Throws if this isn't a managed assembly or if it was built + // with a later version of the same assembly. + AssemblyName assemblyName = AssemblyName.GetAssemblyName(Path.GetFileName(path)); + + return Assembly.Load(assemblyName); +#endif + } + + private IList GetFixtures(Assembly assembly, IList names) + { + ObjectList fixtures = new ObjectList(); + + IList testTypes = GetCandidateFixtureTypes(assembly, names); + + foreach (Type testType in testTypes) + { + if (TestFixtureBuilder.CanBuildFrom(testType)) + fixtures.Add(TestFixtureBuilder.BuildFrom(testType)); + } + + return fixtures; + } + + private IList GetCandidateFixtureTypes(Assembly assembly, IList names) + { + IList types = assembly.GetTypes(); + + if (names == null || names.Count == 0) + return types; + + ObjectList result = new ObjectList(); + + foreach (string name in names) + { + Type fixtureType = assembly.GetType(name); + if (fixtureType != null) + result.Add(fixtureType); + else + { + string prefix = name + "."; + + foreach (Type type in types) + if (type.FullName.StartsWith(prefix)) + result.Add(type); + } + } + + return result; + } + + private TestSuite BuildFromFixtureType(string assemblyName, Type testType) + { + // TODO: This is the only situation in which we currently + // recognize and load legacy suites. We need to determine + // whether to allow them in more places. + //if (legacySuiteBuilder.CanBuildFrom(testType)) + // return (TestSuite)legacySuiteBuilder.BuildFrom(testType); + //else + if (TestFixtureBuilder.CanBuildFrom(testType)) + return BuildTestAssembly(assemblyName, + new Test[] { TestFixtureBuilder.BuildFrom(testType) }); + return null; + } + + private TestSuite BuildTestAssembly(string assemblyName, IList fixtures) + { + TestSuite testAssembly = new TestAssembly(this.assembly, assemblyName); + testAssembly.Seed = Randomizer.InitialSeed; + + //NamespaceTreeBuilder treeBuilder = + // new NamespaceTreeBuilder(testAssembly); + //treeBuilder.Add(fixtures); + //testAssembly = treeBuilder.RootSuite; + + foreach (Test fixture in fixtures) + testAssembly.Add(fixture); + + if (fixtures.Count == 0) + { + testAssembly.RunState = RunState.NotRunnable; + testAssembly.Properties.Set(PropertyNames.SkipReason, "Has no TestFixtures"); + } + + testAssembly.ApplyAttributesToTest(assembly); + +#if !SILVERLIGHT + testAssembly.Properties.Set(PropertyNames.ProcessID, System.Diagnostics.Process.GetCurrentProcess().Id); +#endif + testAssembly.Properties.Set(PropertyNames.AppDomain, AppDomain.CurrentDomain.FriendlyName); + + + // TODO: Make this an option? Add Option to sort assemblies as well? + testAssembly.Sort(); + + return testAssembly; + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitLiteTestAssemblyRunner.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitLiteTestAssemblyRunner.cs new file mode 100644 index 00000000000..5a42d39f6a1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/NUnitLiteTestAssemblyRunner.cs @@ -0,0 +1,143 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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; +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal.WorkItems; + +namespace NUnit.Framework.Internal +{ + /// + /// Default implementation of ITestAssemblyRunner + /// + public class NUnitLiteTestAssemblyRunner : ITestAssemblyRunner + { + private IDictionary settings; + private ITestAssemblyBuilder builder; + private TestSuite loadedTest; + //private Thread runThread; + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The builder. + public NUnitLiteTestAssemblyRunner(ITestAssemblyBuilder builder) + { + this.builder = builder; + } + + #endregion + + #region Properties + + /// + /// TODO: Documentation needed for property + /// + public ITest LoadedTest + { + get + { + return this.loadedTest; + } + } + + #endregion + + #region Methods + + /// + /// Loads the tests found in an Assembly + /// + /// File name of the assembly to load + /// Dictionary of option settings for loading the assembly + /// True if the load was successful + public bool Load(string assemblyName, IDictionary settings) + { + this.settings = settings; + this.loadedTest = this.builder.Build(assemblyName, settings); + if (loadedTest == null) return false; + + return true; + } + + /// + /// Loads the tests found in an Assembly + /// + /// The assembly to load + /// Dictionary of option settings for loading the assembly + /// True if the load was successful + public bool Load(Assembly assembly, IDictionary settings) + { + this.settings = settings; + this.loadedTest = this.builder.Build(assembly, settings); + if (loadedTest == null) return false; + + return true; + } + + ///// + ///// Count Test Cases using a filter + ///// + ///// The filter to apply + ///// The number of test cases found + //public int CountTestCases(TestFilter filter) + //{ + // return this.suite.CountTestCases(filter); + //} + + /// + /// Run selected tests and return a test result. The test is run synchronously, + /// and the listener interface is notified as it progresses. + /// + /// Interface to receive EventListener notifications. + /// A test filter used to select tests to be run + /// + public ITestResult Run(ITestListener listener, ITestFilter filter) + { + TestExecutionContext context = new TestExecutionContext(); + + if (this.settings.Contains("WorkDirectory")) + context.WorkDirectory = (string)this.settings["WorkDirectory"]; + else +#if NETCF || SILVERLIGHT + context.WorkDirectory = Env.DocumentFolder; +#else + context.WorkDirectory = Environment.CurrentDirectory; +#endif + context.Listener = listener; + + WorkItem workItem = loadedTest.CreateWorkItem(filter); + workItem.Execute(context); + + while (workItem.State != WorkItemState.Complete) + System.Threading.Thread.Sleep(5); + return workItem.Result; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/OSPlatform.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/OSPlatform.cs new file mode 100644 index 00000000000..7d86dc83ea3 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/OSPlatform.cs @@ -0,0 +1,386 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Internal +{ + /// + /// OSPlatform represents a particular operating system platform + /// + public class OSPlatform + { + PlatformID platform; + Version version; + ProductType product; + + #region Static Members + private static OSPlatform currentPlatform; + + + /// + /// Platform ID for Unix as defined by Microsoft .NET 2.0 and greater + /// + public static readonly PlatformID UnixPlatformID_Microsoft = (PlatformID)4; + + /// + /// Platform ID for Unix as defined by Mono + /// + public static readonly PlatformID UnixPlatformID_Mono = (PlatformID)128; + + /// + /// Get the OSPlatform under which we are currently running + /// + public static OSPlatform CurrentPlatform + { + get + { + if (currentPlatform == null) + { + OperatingSystem os = Environment.OSVersion; + +#if SILVERLIGHT + // TODO: Runtime silverlight detection? + currentPlatform = new OSPlatform(os.Platform, os.Version); +#else + if (os.Platform == PlatformID.Win32NT && os.Version.Major >= 5) + { + OSVERSIONINFOEX osvi = new OSVERSIONINFOEX(); + osvi.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osvi); + GetVersionEx(ref osvi); + currentPlatform = new OSPlatform(os.Platform, os.Version, (ProductType)osvi.ProductType); + } + else + currentPlatform = new OSPlatform(os.Platform, os.Version); +#endif + } + + return currentPlatform; + } + } + #endregion + + #region Members used for Win32NT platform only + /// + /// Product Type Enumeration used for Windows + /// + public enum ProductType + { + /// + /// Product type is unknown or unspecified + /// + Unknown, + + /// + /// Product type is Workstation + /// + WorkStation, + + /// + /// Product type is Domain Controller + /// + DomainController, + + /// + /// Product type is Server + /// + Server, + } + + [StructLayout(LayoutKind.Sequential)] + struct OSVERSIONINFOEX + { + public uint dwOSVersionInfoSize; + public uint dwMajorVersion; + public uint dwMinorVersion; + public uint dwBuildNumber; + public uint dwPlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string szCSDVersion; + public Int16 wServicePackMajor; + public Int16 wServicePackMinor; + public Int16 wSuiteMask; + public Byte ProductType; + public Byte Reserved; + } + + [DllImport("Kernel32.dll")] + private static extern bool GetVersionEx(ref OSVERSIONINFOEX osvi); + #endregion + + /// + /// Construct from a platform ID and version + /// + public OSPlatform(PlatformID platform, Version version) + { + this.platform = platform; + this.version = version; + } + + /// + /// Construct from a platform ID, version and product type + /// + public OSPlatform(PlatformID platform, Version version, ProductType product) + : this( platform, version ) + { + this.product = product; + } + + /// + /// Get the platform ID of this instance + /// + public PlatformID Platform + { + get { return platform; } + } + + /// + /// Get the Version of this instance + /// + public Version Version + { + get { return version; } + } + + /// + /// Get the Product Type of this instance + /// + public ProductType Product + { + get { return product; } + } + + /// + /// Return true if this is a windows platform + /// + public bool IsWindows + { + get + { + return platform == PlatformID.Win32NT + || platform == PlatformID.Win32Windows + || platform == PlatformID.Win32S + || platform == PlatformID.WinCE; + } + } + + /// + /// Return true if this is a Unix or Linux platform + /// + public bool IsUnix + { + get + { + return platform == UnixPlatformID_Microsoft + || platform == UnixPlatformID_Mono; + } + } + + /// + /// Return true if the platform is Win32S + /// + public bool IsWin32S + { + get { return platform == PlatformID.Win32S; } + } + + /// + /// Return true if the platform is Win32Windows + /// + public bool IsWin32Windows + { + get { return platform == PlatformID.Win32Windows; } + } + + /// + /// Return true if the platform is Win32NT + /// + public bool IsWin32NT + { + get { return platform == PlatformID.Win32NT; } + } + + /// + /// Return true if the platform is Windows CE + /// + public bool IsWinCE + { + get { return (int)platform == 3; } // PlatformID.WinCE not defined in .NET 1.0 + } + +#if (CLR_2_0 || CLR_4_0) && !NETCF + /// + /// Return true if the platform is Xbox + /// + public bool IsXbox + { + get { return platform == PlatformID.Xbox; } + } + + /// + /// Return true if the platform is MacOSX + /// + public bool IsMacOSX + { + get { return platform == PlatformID.MacOSX; } + } +#endif + + /// + /// Return true if the platform is Windows 95 + /// + public bool IsWin95 + { + get { return platform == PlatformID.Win32Windows && version.Major == 4 && version.Minor == 0; } + } + + /// + /// Return true if the platform is Windows 98 + /// + public bool IsWin98 + { + get { return platform == PlatformID.Win32Windows && version.Major == 4 && version.Minor == 10; } + } + + /// + /// Return true if the platform is Windows ME + /// + public bool IsWinME + { + get { return platform == PlatformID.Win32Windows && version.Major == 4 && version.Minor == 90; } + } + + /// + /// Return true if the platform is NT 3 + /// + public bool IsNT3 + { + get { return platform == PlatformID.Win32NT && version.Major == 3; } + } + + /// + /// Return true if the platform is NT 4 + /// + public bool IsNT4 + { + get { return platform == PlatformID.Win32NT && version.Major == 4; } + } + + /// + /// Return true if the platform is NT 5 + /// + public bool IsNT5 + { + get { return platform == PlatformID.Win32NT && version.Major == 5; } + } + + /// + /// Return true if the platform is Windows 2000 + /// + public bool IsWin2K + { + get { return IsNT5 && version.Minor == 0; } + } + + /// + /// Return true if the platform is Windows XP + /// + public bool IsWinXP + { + get { return IsNT5 && (version.Minor == 1 || version.Minor == 2 && Product == ProductType.WorkStation); } + } + + /// + /// Return true if the platform is Windows 2003 Server + /// + public bool IsWin2003Server + { + get { return IsNT5 && version.Minor == 2 && Product == ProductType.Server; } + } + + /// + /// Return true if the platform is NT 6 + /// + public bool IsNT6 + { + get { return platform == PlatformID.Win32NT && version.Major == 6; } + } + + /// + /// Return true if the platform is Vista + /// + public bool IsVista + { + get { return IsNT6 && version.Minor == 0 && Product == ProductType.WorkStation; } + } + + /// + /// Return true if the platform is Windows 2008 Server (original or R2) + /// + public bool IsWin2008Server + { + get { return IsNT6 && Product == ProductType.Server; } + } + + /// + /// Return true if the platform is Windows 2008 Server (original) + /// + public bool IsWin2008ServerR1 + { + get { return IsNT6 && version.Minor == 0 && Product == ProductType.Server; } + } + + /// + /// Return true if the platform is Windows 2008 Server R2 + /// + public bool IsWin2008ServerR2 + { + get { return IsNT6 && version.Minor == 1 && Product == ProductType.Server; } + } + + /// + /// Return true if the platform is Windows 2012 Server + /// + public bool IsWin2012Server + { + get { return IsNT6 && version.Minor == 2 && Product == ProductType.Server; } + } + + /// + /// Return true if the platform is Windows 7 + /// + public bool IsWindows7 + { + get { return IsNT6 && version.Minor == 1 && Product == ProductType.WorkStation; } + } + + /// + /// Return true if the platform is Windows 8 + /// + public bool IsWindows8 + { + get { return IsNT6 && version.Minor == 8 && Product == ProductType.WorkStation; } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ParameterSet.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ParameterSet.cs new file mode 100644 index 00000000000..2c90a389138 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ParameterSet.cs @@ -0,0 +1,219 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// ParameterSet encapsulates method arguments and + /// other selected parameters needed for constructing + /// a parameterized test case. + /// + public class ParameterSet : ITestCaseData, IApplyToTest + { + #region Instance Fields + + private object[] arguments; + private object[] originalArguments; + private object result; + private bool hasExpectedResult; + private ExpectedExceptionData exceptionData; + + /// + /// A dictionary of properties, used to add information + /// to tests without requiring the class to change. + /// + private IPropertyBag properties; + + #endregion + + #region Properties + + private RunState runState; + /// + /// The RunState for this set of parameters. + /// + public RunState RunState + { + get { return runState; } + set { runState = value; } + } + + /// + /// The arguments to be used in running the test, + /// which must match the method signature. + /// + public object[] Arguments + { + get { return arguments; } + set + { + arguments = value; + + if (originalArguments == null) + originalArguments = value; + } + } + + /// + /// The original arguments provided by the user, + /// used for display purposes. + /// + public object[] OriginalArguments + { + get { return originalArguments; } + } + + /// + /// Gets a flag indicating whether an exception is expected. + /// + public bool ExceptionExpected + { + get { return exceptionData.ExpectedExceptionName != null; } + } + + /// + /// Data about any expected exception + /// + public ExpectedExceptionData ExceptionData + { + get { return exceptionData; } + } + + /// + /// The expected result of the test, which + /// must match the method return type. + /// + public object ExpectedResult + { + get { return result; } + set + { + result = value; + hasExpectedResult = true; + } + } + + /// + /// Gets a value indicating whether an expected result was specified. + /// + public bool HasExpectedResult + { + get { return hasExpectedResult; } + } + + private string testName; + /// + /// A name to be used for this test case in lieu + /// of the standard generated name containing + /// the argument list. + /// + public string TestName + { + get { return testName; } + set { testName = value; } + } + + /// + /// Gets the property dictionary for this test + /// + public IPropertyBag Properties + { + get + { + if (properties == null) + properties = new PropertyBag(); + + return properties; + } + } + + #endregion + + #region Constructors + + /// + /// Construct a non-runnable ParameterSet, specifying + /// the provider exception that made it invalid. + /// + public ParameterSet(Exception exception) + { + this.RunState = RunState.NotRunnable; + this.Properties.Set(PropertyNames.SkipReason, ExceptionHelper.BuildMessage(exception)); + this.Properties.Set(PropertyNames.ProviderStackTrace, ExceptionHelper.BuildStackTrace(exception)); + } + + /// + /// Construct an empty parameter set, which + /// defaults to being Runnable. + /// + public ParameterSet() + { + this.RunState = RunState.Runnable; + } + + /// + /// Construct a ParameterSet from an object implementing ITestCaseData + /// + /// + public ParameterSet(ITestCaseData data) + { + this.TestName = data.TestName; + this.RunState = data.RunState; + this.Arguments = data.Arguments; + this.exceptionData = data.ExceptionData; + + if (data.HasExpectedResult) + this.ExpectedResult = data.ExpectedResult; + + foreach (string key in data.Properties.Keys) + this.Properties[key] = data.Properties[key]; + } + + #endregion + + #region IApplyToTest Members + + /// + /// Applies ParameterSet values to the test itself. + /// + /// A test. + public void ApplyToTest(Test test) + { + if (this.RunState != RunState.Runnable) + test.RunState = this.RunState; + + foreach (string key in Properties.Keys) + foreach (object value in Properties[key]) + test.Properties.Add(key, value); + + TestMethod testMethod = test as TestMethod; + if (testMethod != null && exceptionData.ExpectedExceptionName != null) + testMethod.CustomDecorators.Add(new ExpectedExceptionDecorator(this.ExceptionData)); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PlatformHelper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PlatformHelper.cs new file mode 100644 index 00000000000..9e614dd9236 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PlatformHelper.cs @@ -0,0 +1,298 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Internal +{ + /// + /// PlatformHelper class is used by the PlatformAttribute class to + /// determine whether a platform is supported. + /// + public class PlatformHelper + { + private OSPlatform os; + private RuntimeFramework rt; + + // Set whenever we fail to support a list of platforms + private string reason = string.Empty; + + /// + /// Comma-delimited list of all supported OS platform constants + /// + public static readonly string OSPlatforms = +#if (CLR_2_0 || CLR_4_0) && !NETCF + "Win,Win32,Win32S,Win32NT,Win32Windows,WinCE,Win95,Win98,WinMe,NT3,NT4,NT5,NT6,Win2K,WinXP,Win2003Server,Vista,Win2008Server,Win2008ServerR2,Win2012Server,Windows7,Windows8,Unix,Linux,Xbox,MacOSX"; +#else + "Win,Win32,Win32S,Win32NT,Win32Windows,WinCE,Win95,Win98,WinMe,NT3,NT4,NT5,NT6,Win2K,WinXP,Win2003Server,Vista,Win2008Server,Win2008ServerR2,Win2012Server,Windows7,Windows8,Unix,Linux"; +#endif + + /// + /// Comma-delimited list of all supported Runtime platform constants + /// + public static readonly string RuntimePlatforms = + "Net,NetCF,SSCLI,Rotor,Mono,MonoTouch"; + + /// + /// Default constructor uses the operating system and + /// common language runtime of the system. + /// + public PlatformHelper() + { + this.os = OSPlatform.CurrentPlatform; + this.rt = RuntimeFramework.CurrentFramework; + } + + /// + /// Contruct a PlatformHelper for a particular operating + /// system and common language runtime. Used in testing. + /// + /// OperatingSystem to be used + /// RuntimeFramework to be used + public PlatformHelper( OSPlatform os, RuntimeFramework rt ) + { + this.os = os; + this.rt = rt; + } + + /// + /// Test to determine if one of a collection of platforms + /// is being used currently. + /// + /// + /// + public bool IsPlatformSupported( string[] platforms ) + { + foreach( string platform in platforms ) + if ( IsPlatformSupported( platform ) ) + return true; + + return false; + } + + /// + /// Tests to determine if the current platform is supported + /// based on a platform attribute. + /// + /// The attribute to examine + /// + public bool IsPlatformSupported( PlatformAttribute platformAttribute ) + { + string include = platformAttribute.Include; + string exclude = platformAttribute.Exclude; + + try + { + if (include != null && !IsPlatformSupported(include)) + { + reason = string.Format("Only supported on {0}", include); + return false; + } + + if (exclude != null && IsPlatformSupported(exclude)) + { + reason = string.Format("Not supported on {0}", exclude); + return false; + } + } + catch (Exception ex) + { + reason = ex.Message; + return false; + } + + return true; + } + + /// + /// Test to determine if the a particular platform or comma- + /// delimited set of platforms is in use. + /// + /// Name of the platform or comma-separated list of platform names + /// True if the platform is in use on the system + public bool IsPlatformSupported( string platform ) + { + if ( platform.IndexOf( ',' ) >= 0 ) + return IsPlatformSupported( platform.Split( new char[] { ',' } ) ); + + string platformName = platform.Trim(); + bool isSupported = false; + +// string versionSpecification = null; +// +// string[] parts = platformName.Split( new char[] { '-' } ); +// if ( parts.Length == 2 ) +// { +// platformName = parts[0]; +// versionSpecification = parts[1]; +// } + + switch( platformName.ToUpper() ) + { + case "WIN": + case "WIN32": + isSupported = os.IsWindows; + break; + case "WIN32S": + isSupported = os.IsWin32S; + break; + case "WIN32WINDOWS": + isSupported = os.IsWin32Windows; + break; + case "WIN32NT": + isSupported = os.IsWin32NT; + break; + case "WINCE": + isSupported = os.IsWinCE; + break; + case "WIN95": + isSupported = os.IsWin95; + break; + case "WIN98": + isSupported = os.IsWin98; + break; + case "WINME": + isSupported = os.IsWinME; + break; + case "NT3": + isSupported = os.IsNT3; + break; + case "NT4": + isSupported = os.IsNT4; + break; + case "NT5": + isSupported = os.IsNT5; + break; + case "WIN2K": + isSupported = os.IsWin2K; + break; + case "WINXP": + isSupported = os.IsWinXP; + break; + case "WIN2003SERVER": + isSupported = os.IsWin2003Server; + break; + case "NT6": + isSupported = os.IsNT6; + break; + case "VISTA": + isSupported = os.IsVista; + break; + case "WIN2008SERVER": + isSupported = os.IsWin2008Server; + break; + case "WIN2008SERVERR2": + isSupported = os.IsWin2008ServerR2; + break; + case "WIN2012SERVER": + isSupported = os.IsWin2012Server; + break; + case "WINDOWS7": + isSupported = os.IsWindows7; + break; + case "WINDOWS8": + isSupported = os.IsWindows8; + break; + case "UNIX": + case "LINUX": + isSupported = os.IsUnix; + break; +#if (CLR_2_0 || CLR_4_0) && !NETCF + case "XBOX": + isSupported = os.IsXbox; + break; + case "MACOSX": + isSupported = os.IsMacOSX; + break; +#endif + + default: + isSupported = IsRuntimeSupported(platformName); + break; + } + + if (!isSupported) + this.reason = "Only supported on " + platform; + + return isSupported; + } + + /// + /// Return the last failure reason. Results are not + /// defined if called before IsSupported( Attribute ) + /// is called. + /// + public string Reason + { + get { return reason; } + } + + private bool IsRuntimeSupported(string platformName) + { + string versionSpecification = null; + string[] parts = platformName.Split(new char[] { '-' }); + if (parts.Length == 2) + { + platformName = parts[0]; + versionSpecification = parts[1]; + } + + switch (platformName.ToUpper()) + { + case "NET": + return IsRuntimeSupported(RuntimeType.Net, versionSpecification); + + case "NETCF": + return IsRuntimeSupported(RuntimeType.NetCF, versionSpecification); + + case "SSCLI": + case "ROTOR": + return IsRuntimeSupported(RuntimeType.SSCLI, versionSpecification); + + case "MONO": + return IsRuntimeSupported(RuntimeType.Mono, versionSpecification); + + case "SL": + case "SILVERLIGHT": + return IsRuntimeSupported(RuntimeType.Silverlight, versionSpecification); + + case "MONOTOUCH": + return IsRuntimeSupported(RuntimeType.MonoTouch, versionSpecification); + + default: + throw new ArgumentException("Invalid platform name", platformName); + } + } + + private bool IsRuntimeSupported(RuntimeType runtime, string versionSpecification) + { + Version version = versionSpecification == null + ? RuntimeFramework.DefaultVersion + : new Version(versionSpecification); + + RuntimeFramework target = new RuntimeFramework(runtime, version); + + return rt.Supports(target); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PropertyBag.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PropertyBag.cs new file mode 100644 index 00000000000..acf5e8fd08f --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PropertyBag.cs @@ -0,0 +1,462 @@ +using System; +using System.Collections; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// A PropertyBag represents a collection of name value pairs + /// that allows duplicate entries with the same key. Methods + /// are provided for adding a new pair as well as for setting + /// a key to a single value. All keys are strings but values + /// may be of any type. Null values are not permitted, since + /// a null entry represents the absence of the key. + /// + public class PropertyBag : IPropertyBag + { +#if CLR_2_0 || CLR_4_0 + private Dictionary inner = new Dictionary(); + + private bool TryGetValue(string key, out IList list) + { + return inner.TryGetValue(key, out list); + } +#else + private Hashtable inner = new Hashtable(); + + private bool TryGetValue(string key, out IList list) + { + list = inner.ContainsKey(key) + ? (IList)inner[key] + : null; + + return list != null; + } +#endif + + /// + /// Adds a key/value pair to the property set + /// + /// The key + /// The value + public void Add(string key, object value) + { + IList list; + if (!TryGetValue(key, out list)) + { + list = new ObjectList(); + inner.Add(key, list); + } + list.Add(value); + } + + /// + /// Sets the value for a key, removing any other + /// values that are already in the property set. + /// + /// + /// + public void Set(string key, object value) + { + IList list = new ObjectList(); + list.Add(value); + inner[key] = list; + } + + /// + /// Gets a single value for a key, using the first + /// one if multiple values are present and returning + /// null if the value is not found. + /// + /// + /// + public object Get(string key) + { + IList list; + return TryGetValue(key, out list) && list.Count > 0 + ? list[0] + : null; + } + + /// + /// Gets a single boolean value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + /// + /// + /// + public bool GetSetting(string key, bool defaultValue) + { + object value = Get(key); + return value == null + ? defaultValue + : (bool)value; + } + + /// + /// Gets a single string value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + /// + /// + /// + public string GetSetting(string key, string defaultValue) + { + object value = Get(key); + return value == null + ? defaultValue + : (string)value; + } + + /// + /// Gets a single int value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + /// + /// + /// + public int GetSetting(string key, int defaultValue) + { + object value = Get(key); + return value == null + ? defaultValue + : (int)value; + } + + /// + /// Gets a single Enum value for a key, using the first + /// one if multiple values are present and returning the + /// default value if no entry is found. + /// + /// + /// + /// + public Enum GetSetting(string key, Enum defaultValue) + { + object value = Get(key); + return value == null + ? defaultValue + : (Enum)value; + } + + /// + /// Clears this instance. + /// + public void Clear() + { + inner.Clear(); + } + + /// + /// Removes all entries for a key from the property set + /// + /// The key for which the entries are to be removed + public void Remove(string key) + { + inner.Remove(key); + } + + /// + /// Removes a single entry if present. If not found, + /// no error occurs. + /// + /// + /// + public void Remove(string key, object value) + { + IList list; + if (TryGetValue(key, out list)) + list.Remove(value); + } + + /// + /// Removes a specific PropertyEntry. If the entry is not + /// found, no errr occurs. + /// + /// The property entry to remove + public void Remove(PropertyEntry entry) + { + Remove(entry.Name, entry.Value); + } + + /// + /// Get the number of key/value pairs in the property set + /// + /// + public int Count + { + get + { + int count = 0; + + foreach (string key in inner.Keys) + count += ((IList)inner[key]).Count; + + return count; + } + } + + /// + /// Gets a flag indicating whether the specified key has + /// any entries in the property set. + /// + /// The key to be checked + /// + /// True if their are values present, otherwise false + /// + public bool ContainsKey(string key) + { + return inner.ContainsKey(key); + } + + /// + /// Gets a flag indicating whether the specified key and + /// value are present in the property set. + /// + /// The key to be checked + /// The value to be checked + /// + /// True if the key and value are present, otherwise false + /// + public bool Contains(string key, object value) + { + IList list; + return TryGetValue(key, out list) && list.Contains(value); + } + + /// + /// Gets a flag indicating whether the specified key and + /// value are present in the property set. + /// + /// The property entry to be checked + /// + /// True if the entry is present, otherwise false + /// + public bool Contains(PropertyEntry entry) + { + return Contains(entry.Name, entry.Value); + } + + /// + /// Gets a collection containing all the keys in the property set + /// + /// +#if CLR_2_0 || CLR_4_0 + public ICollection Keys +#else + public ICollection Keys +#endif + { + get { return inner.Keys; } + } + + /// + /// Gets an enumerator for all properties in the property bag + /// + /// + public IEnumerator GetEnumerator() + { + return new PropertyBagEnumerator(this); + } + + /// + /// Gets or sets the list of values for a particular key + /// + public IList this[string key] + { + get + { + IList list; + if (!TryGetValue(key, out list)) + { + list = new ObjectList(); + inner.Add(key, list); + } + return list; + } + set + { + inner[key] = value; + } + } + + #region IXmlNodeBuilder Members + + /// + /// Returns an XmlNode representating the current PropertyBag. + /// + /// Not used + /// An XmlNode representing the PropertyBag + public XmlNode ToXml(bool recursive) + { + //XmlResult topNode = XmlResult.CreateTopLevelElement("dummy"); + + XmlNode thisNode = AddToXml(new XmlNode("dummy"), recursive); + + return thisNode; + } + + /// + /// Returns an XmlNode representing the PropertyBag after + /// adding it as a child of the supplied parent node. + /// + /// The parent node. + /// Not used + /// + public XmlNode AddToXml(XmlNode parentNode, bool recursive) + { + XmlNode properties = parentNode.AddElement("properties"); + + foreach (string key in Keys) + { + foreach (object value in this[key]) + { + XmlNode prop = properties.AddElement("property"); + + // TODO: Format as string + prop.AddAttribute("name", key.ToString()); + prop.AddAttribute("value", value.ToString()); + } + } + + return properties; + } + + #endregion + + #region Nested PropertyBagEnumerator Class + + /// + /// TODO: Documentation needed for class + /// +#if CLR_2_0 || CLR_4_0 + public class PropertyBagEnumerator : IEnumerator + { + private IEnumerator> innerEnum; +#else + public class PropertyBagEnumerator : IEnumerator + { + private IEnumerator innerEnum; +#endif + private PropertyBag bag; + private IEnumerator valueEnum; + + /// + /// + /// + /// + public PropertyBagEnumerator(PropertyBag bag) + { + this.bag = bag; + + Initialize(); + } + + private void Initialize() + { + innerEnum = bag.inner.GetEnumerator(); + valueEnum = null; + + if (innerEnum.MoveNext()) + { +#if CLR_2_0 || CLR_4_0 + valueEnum = innerEnum.Current.Value.GetEnumerator(); +#else + DictionaryEntry entry = (DictionaryEntry)innerEnum.Current; + valueEnum = ((IList)entry.Value).GetEnumerator(); +#endif + } + } + + private PropertyEntry GetCurrentEntry() + { + if (valueEnum == null) + throw new InvalidOperationException(); + +#if CLR_2_0 || CLR_4_0 + string key = innerEnum.Current.Key; +#else + DictionaryEntry entry = (DictionaryEntry)innerEnum.Current; + string key = (string)entry.Key; +#endif + + object value = valueEnum.Current; + + return new PropertyEntry(key, value); + } + + #region IEnumerator Members + +#if CLR_2_0 || CLR_4_0 + PropertyEntry IEnumerator.Current + { + get + { + return GetCurrentEntry(); + } + } +#endif + + #endregion + + #region IDisposable Members + +#if CLR_2_0 || CLR_4_0 + void IDisposable.Dispose() + { + } +#endif + + #endregion + + #region IEnumerator Members + + object IEnumerator.Current + { + get + { + return GetCurrentEntry(); + } + } + + bool IEnumerator.MoveNext() + { + if (valueEnum == null) + return false; + + while (!valueEnum.MoveNext()) + { + if (!innerEnum.MoveNext()) + { + valueEnum = null; + return false; + } + +#if CLR_2_0 || CLR_4_0 + valueEnum = innerEnum.Current.Value.GetEnumerator(); +#else + DictionaryEntry entry = (DictionaryEntry)innerEnum.Current; + valueEnum = ((IList)entry.Value).GetEnumerator(); +#endif + } + + return true; + } + + void IEnumerator.Reset() + { + Initialize(); + } + + #endregion + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PropertyNames.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PropertyNames.cs new file mode 100644 index 00000000000..400713351ea --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/PropertyNames.cs @@ -0,0 +1,102 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Internal +{ + /// + /// The PropertyNames class provides static constants for the + /// standard property names that NUnit uses on tests. + /// + public class PropertyNames + { + /// + /// The Description of a test + /// + public static readonly string Description = "Description"; + + /// + /// The reason a test was not run + /// + public static readonly string SkipReason = "_SKIPREASON"; + + /// + /// The stack trace from any data provider that threw + /// an exception. + /// + public static readonly string ProviderStackTrace = "_PROVIDERSTACKTRACE"; + + /// + /// The culture to be set for a test + /// + public static readonly string SetCulture = "SetCulture"; + + /// + /// The UI culture to be set for a test + /// + public static readonly string SetUICulture = "SetUICulture"; + + /// + /// The categories applying to a test + /// + public static readonly string Category = "Category"; + +#if !NUNITLITE + /// + /// The ApartmentState required for running the test + /// + public static readonly string ApartmentState = "ApartmentState"; +#endif + + /// + /// The timeout value for the test + /// + public static readonly string Timeout = "Timeout"; + + /// + /// The number of times the test should be repeated + /// + public static readonly string RepeatCount = "Repeat"; + + /// + /// The maximum time in ms, above which the test is considered to have failed + /// + public static readonly string MaxTime = "MaxTime"; + + /// + /// The selected strategy for joining parameter data into test cases + /// + public static readonly string JoinType = "_JOINTYPE"; + + /// + /// The process ID of the executing assembly + /// + public static readonly string ProcessID = "_PID"; + + /// + /// The FriendlyName of the AppDomain in which the assembly is running + /// + public static readonly string AppDomain = "_APPDOMAIN"; + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/RandomGenerator.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/RandomGenerator.cs new file mode 100644 index 00000000000..c2711e9b4b0 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/RandomGenerator.cs @@ -0,0 +1,196 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework.Internal +{ + /// + /// RandomGenerator returns a set of random values in a repeatable + /// way, to allow re-running of tests if necessary. + /// + /// This class is internal to the framework but exposed externally to through the TestContext + /// the class is used to allow for obtaining repeatable random values during a tests execution. + /// this class should not be used inside the framework only with a TestMethod. + /// + public class RandomGenerator + { + #region Members & Constructor + /// + /// Seed for the wrapped Random + /// + public readonly int seed; + + private Random random; + + /// + /// Lazy-loaded Random built on the readonly Seed + /// + private Random Rand + { + get + { + random = random == null ? new Random(seed) : random; + return random; + } + } + + /// + /// Constructor requires Seed value in order to store it for use in Random creation + /// + /// + public RandomGenerator(int seed) + { + this.seed = seed; + } + #endregion + + #region Ints + /// + /// Get Next Integer from Random + /// + /// int + public int GetInt() + { + return Rand.Next(); + } + /// + /// Get Next Integer within the specified min & max from Random + /// + /// + /// + /// int + public int GetInt(int min, int max) + { + return Rand.Next(min, max); + } + #endregion + + #region Shorts + /// + /// Get Next Short from Random + /// + /// short + public short GetShort() + { + return (short)Rand.Next(short.MinValue, short.MaxValue); + } + /// + /// Get Next Short within the specified min & max from Random + /// + /// + /// + /// short + public short GetShort(short min, short max) + { + return (short)Rand.Next(min, max); + } + #endregion + + #region Bytes + /// + /// Get Next Byte from Random + /// + /// byte + public byte GetByte() + { + return (byte)Rand.Next(Byte.MinValue, Byte.MaxValue); + } + /// + /// Get Next Byte within the specified min & max from Random + /// + /// + /// + /// byte + public byte GetByte(byte min, byte max) + { + return (byte)Rand.Next(min, max); + } + #endregion + + #region Bools + /// + /// Get Random Boolean value + /// + /// bool + public bool GetBool() + { + return Rand.Next(0, 2) == 0; + } + /// + /// Get Random Boolean value based on the probability of that value being true + /// + /// + /// bool + public bool GetBool(double probability) + { + return Rand.NextDouble() < Math.Abs(probability % 1.0); + } + #endregion + + #region Double & Float + /// + /// Get Next Double from Random + /// + /// + public double GetDouble() + { + return Rand.NextDouble(); + } + /// + /// Get Next Float from Random + /// + /// + public float GetFloat() + { + return (float)Rand.NextDouble(); + } + #endregion + + #region Enums +#if CLR_2_0 || CLR_4_0 + /// + /// Return a random enum value representation of the specified Type + /// + /// + /// T + public T GetEnum() + { + Array enums = TypeHelper.GetEnumValues(typeof(T)); + return (T)enums.GetValue(Rand.Next(0, enums.Length)); + } +#else + /// + /// Return a random enum value from the specified type + /// + /// + /// object + public object GetEnum(Type enumType) + { + Array enums = TypeHelper.GetEnumValues(enumType); + return enums.GetValue(Rand.Next(0, enums.Length)); + } +#endif + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Randomizer.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Randomizer.cs new file mode 100644 index 00000000000..ad805153c9c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Randomizer.cs @@ -0,0 +1,187 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; + +namespace NUnit.Framework.Internal +{ + /// + /// Randomizer returns a set of random values in a repeatable + /// way, to allow re-running of tests if necessary. + /// + /// This class is an internal framework class used for setting up tests. + /// It is used to generate random test parameters, at the time of loading + /// the tests. It also generates seeds for use at execution time, when + /// creating a RandomGenerator for use by the test. + /// + public class Randomizer : Random + { + #region Static Members + + private static int initialSeed = new Random().Next(); + + private static Random seedGenerator; + +#if CLR_2_0 || CLR_4_0 + private static Dictionary randomizers = new Dictionary(); +#else + private static System.Collections.Hashtable randomizers = new System.Collections.Hashtable(); +#endif + + /// + /// Initial seed used to create randomizers for this run + /// + public static int InitialSeed + { + get { return initialSeed; } + set { initialSeed = value; } + } + + /// + /// Get a randomizer for a particular member, returning + /// one that has already been created if it exists. + /// This ensures that the same values are generated + /// each time the tests are reloaded. + /// + public static Randomizer GetRandomizer(MemberInfo member) + { + if (randomizers.ContainsKey(member)) + return (Randomizer)randomizers[member]; + else + { + Randomizer r = CreateRandomizer(); + randomizers[member] = r; + return (Randomizer)r; + } + } + + /// + /// Get a randomizer for a particular parameter, returning + /// one that has already been created if it exists. + /// This ensures that the same values are generated + /// each time the tests are reloaded. + /// + public static Randomizer GetRandomizer(ParameterInfo parameter) + { + return GetRandomizer(parameter.Member); + } + + /// + /// Create a new Randomizer using the next seed + /// available to ensure that each randomizer gives + /// a unique sequence of values. + /// + /// + public static Randomizer CreateRandomizer() + { + if (seedGenerator == null) + seedGenerator = new Random(initialSeed); + + return new Randomizer(seedGenerator.Next()); + } + + #endregion + + #region Constructor + + /// + /// Construct a randomizer using a specified seed + /// + public Randomizer(int seed) : base(seed) { } + + #endregion + + #region Public Methods + /// + /// Return an array of random doubles between 0.0 and 1.0. + /// + /// + /// + public double[] GetDoubles(int count) + { + double[] rvals = new double[count]; + + for (int index = 0; index < count; index++) + rvals[index] = NextDouble(); + + return rvals; + } + + /// + /// Return an array of random Enums + /// + /// + /// + /// + public object[] GetEnums(int count, Type enumType) + { + if (!enumType.IsEnum) + throw new ArgumentException(string.Format("The specified type: {0} was not an enum", enumType)); + +#if !NETCF && !SILVERLIGHT + Array values = Enum.GetValues(enumType); +#else + Array values = TypeHelper.GetEnumValues(enumType); +#endif + object[] rvals = new Enum[count]; + + for (int index = 0; index < count; index++) + rvals[index] = values.GetValue(Next(values.Length)); + + return rvals; + } + + /// + /// Return an array of random doubles with values in a specified range. + /// + public double[] GetDoubles(double min, double max, int count) + { + double range = max - min; + double[] rvals = new double[count]; + + for (int index = 0; index < count; index++) + rvals[index] = NextDouble() * range + min; + + return rvals; + } + + /// + /// Return an array of random ints with values in a specified range. + /// + public int[] GetInts(int min, int max, int count) + { + int[] ivals = new int[count]; + + for (int index = 0; index < count; index++) + ivals[index] = Next(min, max); + + return ivals; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Reflect.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Reflect.cs new file mode 100644 index 00000000000..cc51ce61196 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Reflect.cs @@ -0,0 +1,249 @@ +// *********************************************************************** +// Copyright (c) 2007-2012 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; + +namespace NUnit.Framework.Internal +{ + /// + /// Helper methods for inspecting a type by reflection. + /// + /// Many of these methods take ICustomAttributeProvider as an + /// argument to avoid duplication, even though certain attributes can + /// only appear on specific types of members, like MethodInfo or Type. + /// + /// In the case where a type is being examined for the presence of + /// an attribute, interface or named member, the Reflect methods + /// operate with the full name of the member being sought. This + /// removes the necessity of the caller having a reference to the + /// assembly that defines the item being sought and allows the + /// NUnit core to inspect assemblies that reference an older + /// version of the NUnit framework. + /// + public class Reflect + { + private static readonly BindingFlags AllMembers = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy; + + // A zero-length Type array - not provided by System.Type for all CLR versions we support. + private static readonly Type[] EmptyTypes = new Type[0]; + + #region Get Methods of a type + + /// + /// Examine a fixture type and return an array of methods having a + /// particular attribute. The array is order with base methods first. + /// + /// The type to examine + /// The attribute Type to look for + /// Specifies whether to search the fixture type inheritance chain + /// The array of methods found + public static MethodInfo[] GetMethodsWithAttribute(Type fixtureType, Type attributeType, bool inherit) + { + MethodInfoList list = new MethodInfoList(); + + foreach (MethodInfo method in fixtureType.GetMethods(AllMembers)) + { + if (method.IsDefined(attributeType, inherit)) + list.Add(method); + } + + list.Sort(new BaseTypesFirstComparer()); + + return list.ToArray(); + } + +#if CLR_2_0 || CLR_4_0 + private class BaseTypesFirstComparer : IComparer + { + public int Compare(MethodInfo m1, MethodInfo m2) + { + if (m1 == null || m2 == null) return 0; + + Type m1Type = m1.DeclaringType; + Type m2Type = m2.DeclaringType; + + if ( m1Type == m2Type ) return 0; + if ( m1Type.IsAssignableFrom(m2Type) ) return -1; + + return 1; + } + } +#else + private class BaseTypesFirstComparer : IComparer + { + public int Compare(object x, object y) + { + MethodInfo m1 = x as MethodInfo; + MethodInfo m2 = y as MethodInfo; + + if (m1 == null || m2 == null) return 0; + + Type m1Type = m1.DeclaringType; + Type m2Type = m2.DeclaringType; + + if (m1Type == m2Type) return 0; + if (m1Type.IsAssignableFrom(m2Type)) return -1; + + return 1; + } + } +#endif + + /// + /// Examine a fixture type and return true if it has a method with + /// a particular attribute. + /// + /// The type to examine + /// The attribute Type to look for + /// Specifies whether to search the fixture type inheritance chain + /// True if found, otherwise false + public static bool HasMethodWithAttribute(Type fixtureType, Type attributeType) + { + foreach (MethodInfo method in fixtureType.GetMethods(AllMembers)) + { + if (method.IsDefined(attributeType, false)) + return true; + } + + return false; + } + + #endregion + + #region Invoke Constructors + + /// + /// Invoke the default constructor on a Type + /// + /// The Type to be constructed + /// An instance of the Type + public static object Construct(Type type) + { + ConstructorInfo ctor = type.GetConstructor(EmptyTypes); + if (ctor == null) + throw new InvalidTestFixtureException(type.FullName + " does not have a default constructor"); + + return ctor.Invoke(null); + } + + /// + /// Invoke a constructor on a Type with arguments + /// + /// The Type to be constructed + /// Arguments to the constructor + /// An instance of the Type + public static object Construct(Type type, object[] arguments) + { + if (arguments == null) return Construct(type); + + Type[] argTypes = GetTypeArray(arguments); + ConstructorInfo ctor = type.GetConstructor(argTypes); + if (ctor == null) + throw new InvalidTestFixtureException(type.FullName + " does not have a suitable constructor"); + + return ctor.Invoke(arguments); + } + + /// + /// Returns an array of types from an array of objects. + /// Used because the compact framework doesn't support + /// Type.GetTypeArray() + /// + /// An array of objects + /// An array of Types + private static Type[] GetTypeArray(object[] objects) + { + Type[] types = new Type[objects.Length]; + int index = 0; + foreach (object o in objects) + types[index++] = o.GetType(); + return types; + } + + #endregion + + #region Invoke Methods + + /// + /// Invoke a parameterless method returning void on an object. + /// + /// A MethodInfo for the method to be invoked + /// The object on which to invoke the method + public static object InvokeMethod( MethodInfo method, object fixture ) + { + return InvokeMethod( method, fixture, null ); + } + + /// + /// Invoke a method, converting any TargetInvocationException to an NUnitException. + /// + /// A MethodInfo for the method to be invoked + /// The object on which to invoke the method + /// The argument list for the method + /// The return value from the invoked method + public static object InvokeMethod( MethodInfo method, object fixture, params object[] args ) + { + if(method != null) + { + try + { + return method.Invoke( fixture, args ); + } + catch(Exception e) + { + if (e is TargetInvocationException) + throw new NUnitException("Rethrown", e.InnerException); + else + throw new NUnitException("Rethrown", e); + } + } + + return null; + } + + #endregion + + #region Private Constructor for static-only class + + private Reflect() { } + + #endregion + +#if CLR_2_0 || CLR_4_0 + class MethodInfoList : List { } +#else + class MethodInfoList : ArrayList + { + public new MethodInfo[] ToArray() + { + return (MethodInfo[])base.ToArray(typeof(MethodInfo)); + } + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestCaseResult.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestCaseResult.cs new file mode 100644 index 00000000000..481180277fe --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestCaseResult.cs @@ -0,0 +1,60 @@ +using System; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// Represents the result of running a single test case. + /// + public class TestCaseResult : TestResult + { + /// + /// Construct a TestCaseResult based on a TestMethod + /// + /// A TestMethod to which the result applies. + public TestCaseResult(TestMethod test) : base(test) { } + + /// + /// Gets the number of test cases that failed + /// when running the test and all its children. + /// + public override int FailCount + { + get { return ResultState.Status == TestStatus.Failed ? 1 : 0; } + } + + /// + /// Gets the number of test cases that passed + /// when running the test and all its children. + /// + public override int PassCount + { + get { return ResultState.Status == TestStatus.Passed ? 1 : 0; } + } + + /// + /// Gets the number of test cases that were skipped + /// when running the test and all its children. + /// + public override int SkipCount + { + get { return ResultState.Status == TestStatus.Skipped ? 1 : 0; } + } + + /// + /// Gets the number of test cases that were inconclusive + /// when running the test and all its children. + /// + public override int InconclusiveCount + { + get { return ResultState.Status == TestStatus.Inconclusive ? 1 : 0; } + } + + //public override XmlNode AddToXml(XmlNode parentNode, bool recursive) + //{ + // XmlNode thisNode = this.test.AddToXml(parentNode, recursive); + // //thisNode.AddAttribute("seed", this.test.Seed.ToString()); + // return thisNode; + //} + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestResult.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestResult.cs new file mode 100644 index 00000000000..a8cba441582 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestResult.cs @@ -0,0 +1,467 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// The TestResult class represents the result of a test. + /// + public abstract class TestResult : ITestResult + { + #region Fields + + /// + /// Indicates the result of the test + /// + [CLSCompliant(false)] + protected ResultState resultState; + + /// + /// The elapsed time for executing this test + /// + private TimeSpan time = TimeSpan.Zero; + + /// + /// The test that this result pertains to + /// + [CLSCompliant(false)] + protected readonly ITest test; + + /// + /// The stacktrace at the point of failure + /// + private string stackTrace; + + /// + /// Message giving the reason for failure, error or skipping the test + /// + [CLSCompliant(false)] + protected string message; + + /// + /// Number of asserts executed by this test + /// + [CLSCompliant(false)] + protected int assertCount = 0; + + /// + /// List of child results + /// +#if CLR_2_0 || CLR_4_0 + private System.Collections.Generic.List children; +#else + private System.Collections.ArrayList children; +#endif + + #endregion + + #region Constructor + + /// + /// Construct a test result given a Test + /// + /// The test to be used + public TestResult(ITest test) + { + this.test = test; + this.resultState = ResultState.Inconclusive; + } + + #endregion + + #region ITestResult Members + + /// + /// Gets the test with which this result is associated. + /// + public ITest Test + { + get { return test; } + } + + /// + /// Gets the ResultState of the test result, which + /// indicates the success or failure of the test. + /// + public ResultState ResultState + { + get { return resultState; } + } + + /// + /// Gets the name of the test result + /// + public virtual string Name + { + get { return test.Name; } + } + + /// + /// Gets the full name of the test result + /// + public virtual string FullName + { + get { return test.FullName; } + } + + /// + /// Gets or sets the elapsed time for running the test + /// + public TimeSpan Duration + { + get { return time; } + set { time = value; } + } + + /// + /// Gets the message associated with a test + /// failure or with not running the test + /// + public string Message + { + get { return message; } + } + + /// + /// Gets any stacktrace associated with an + /// error or failure. Not available in + /// the Compact Framework 1.0. + /// + public virtual string StackTrace + { + get { return stackTrace; } + } + + /// + /// Gets or sets the count of asserts executed + /// when running the test. + /// + public int AssertCount + { + get { return assertCount; } + set { assertCount = value; } + } + + /// + /// Gets the number of test cases that failed + /// when running the test and all its children. + /// + public abstract int FailCount { get; } + + /// + /// Gets the number of test cases that passed + /// when running the test and all its children. + /// + public abstract int PassCount { get; } + + /// + /// Gets the number of test cases that were skipped + /// when running the test and all its children. + /// + public abstract int SkipCount { get; } + + /// + /// Gets the number of test cases that were inconclusive + /// when running the test and all its children. + /// + public abstract int InconclusiveCount { get; } + + /// + /// Indicates whether this result has any child results. + /// Test HasChildren before accessing Children to avoid + /// the creation of an empty collection. + /// + public bool HasChildren + { + get { return children != null && children.Count > 0; } + } + + /// + /// Gets the collection of child results. + /// +#if CLR_2_0 || CLR_4_0 + public System.Collections.Generic.IList Children + { + get + { + if (children == null) + children = new System.Collections.Generic.List(); + + return children; + } + } +#else + public System.Collections.IList Children + { + get + { + if (children == null) + children = new System.Collections.ArrayList(); + + return children; + } + } +#endif + + #endregion + + #region IXmlNodeBuilder Members + + /// + /// Returns the Xml representation of the result. + /// + /// If true, descendant results are included + /// An XmlNode representing the result + public XmlNode ToXml(bool recursive) + { + XmlNode topNode = XmlNode.CreateTopLevelElement("dummy"); + + AddToXml(topNode, recursive); + + return topNode.FirstChild; + } + + /// + /// Adds the XML representation of the result as a child of the + /// supplied parent node.. + /// + /// The parent node. + /// If true, descendant results are included + /// + public virtual XmlNode AddToXml(XmlNode parentNode, bool recursive) + { + // A result node looks like a test node with extra info added + XmlNode thisNode = this.test.AddToXml(parentNode, false); + + thisNode.AddAttribute("result", ResultState.Status.ToString()); + if (ResultState.Label != string.Empty) // && ResultState.Label != ResultState.Status.ToString()) + thisNode.AddAttribute("label", ResultState.Label); + + thisNode.AddAttribute("time", this.Duration.ToString()); + + if (this.test is TestSuite) + { + thisNode.AddAttribute("total", (PassCount + FailCount + SkipCount + InconclusiveCount).ToString()); + thisNode.AddAttribute("passed", PassCount.ToString()); + thisNode.AddAttribute("failed", FailCount.ToString()); + thisNode.AddAttribute("inconclusive", InconclusiveCount.ToString()); + thisNode.AddAttribute("skipped", SkipCount.ToString()); + } + + thisNode.AddAttribute("asserts", this.AssertCount.ToString()); + + switch (ResultState.Status) + { + case TestStatus.Failed: + AddFailureElement(thisNode); + break; + case TestStatus.Skipped: + AddReasonElement(thisNode); + break; + case TestStatus.Passed: + case TestStatus.Inconclusive: + if (this.Message != null) + AddReasonElement(thisNode); + break; + } + + if (recursive && HasChildren) + foreach (TestResult child in Children) + child.AddToXml(thisNode, recursive); + + return thisNode; + } + + #endregion + + #region Other Public Methods + + /// + /// Add a child result + /// + /// The child result to be added + public virtual void AddResult(TestResult result) + { + this.Children.Add(result); + + this.assertCount += result.AssertCount; + + switch (result.ResultState.Status) + { + case TestStatus.Passed: + + if (this.resultState.Status == TestStatus.Inconclusive) + SetResult(ResultState.Success); + + break; + + case TestStatus.Failed: + + if (this.resultState.Status != TestStatus.Failed) + SetResult(ResultState.Failure, "One or more child tests had errors"); + + break; + + case TestStatus.Skipped: + + switch (result.ResultState.Label) + { + case "Invalid": + + if (this.ResultState != ResultState.NotRunnable && this.ResultState.Status != TestStatus.Failed) + SetResult(ResultState.Failure, "One or more child tests had errors"); + + break; + + case "Ignored": + + if (this.ResultState.Status == TestStatus.Inconclusive || this.ResultState.Status == TestStatus.Passed) + SetResult(ResultState.Ignored, "One or more child tests were ignored"); + + break; + + default: + + // Tests skipped for other reasons do not change the outcome + // of the containing suite when added. + + break; + } + + break; + + case TestStatus.Inconclusive: + + // An inconclusive result does not change the outcome + // of the containing suite when added. + + break; + } + } + + /// + /// Set the result of the test + /// + /// The ResultState to use in the result + public void SetResult(ResultState resultState) + { + SetResult(resultState, null, null); + } + + /// + /// Set the result of the test + /// + /// The ResultState to use in the result + /// A message associated with the result state + public void SetResult(ResultState resultState, string message) + { + SetResult(resultState, message, null); + } + + /// + /// Set the result of the test + /// + /// The ResultState to use in the result + /// A message associated with the result state + /// Stack trace giving the location of the command + public void SetResult(ResultState resultState, string message, string stackTrace) + { + this.resultState = resultState; + this.message = message; + this.stackTrace = stackTrace; + } + + /// + /// Set the test result based on the type of exception thrown + /// + /// The exception that was thrown + public void RecordException(Exception ex) + { + if (ex is NUnitException) + ex = ex.InnerException; + + if (ex is System.Threading.ThreadAbortException) + SetResult(ResultState.Cancelled, "Test cancelled by user", ex.StackTrace); + else if (ex is AssertionException) + SetResult(ResultState.Failure, ex.Message, StackFilter.Filter(ex.StackTrace)); + else if (ex is IgnoreException) + SetResult(ResultState.Ignored, ex.Message, StackFilter.Filter(ex.StackTrace)); + else if (ex is InconclusiveException) + SetResult(ResultState.Inconclusive, ex.Message, StackFilter.Filter(ex.StackTrace)); + else if (ex is SuccessException) + SetResult(ResultState.Success, ex.Message, StackFilter.Filter(ex.StackTrace)); + else + SetResult(ResultState.Error, + ExceptionHelper.BuildMessage(ex), + ExceptionHelper.BuildStackTrace(ex)); + } + + #endregion + + #region Helper Methods + + /// + /// Adds a reason element to a node and returns it. + /// + /// The target node. + /// The new reason element. + private XmlNode AddReasonElement(XmlNode targetNode) + { + XmlNode reasonNode = targetNode.AddElement("reason"); + reasonNode.AddElement("message").TextContent = this.Message; + return reasonNode; + } + + /// + /// Adds a failure element to a node and returns it. + /// + /// The target node. + /// The new failure element. + private XmlNode AddFailureElement(XmlNode targetNode) + { + XmlNode failureNode = targetNode.AddElement("failure"); + + if (this.Message != null) + { + failureNode.AddElement("message").TextContent = this.Message; + } + + if (this.StackTrace != null) + { + failureNode.AddElement("stack-trace").TextContent = this.StackTrace; + } + + return failureNode; + } + + //private static bool IsTestCase(ITest test) + //{ + // return !(test is TestSuite); + //} + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestSuiteResult.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestSuiteResult.cs new file mode 100644 index 00000000000..6c09a318ea2 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Results/TestSuiteResult.cs @@ -0,0 +1,72 @@ +using System; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// Represents the result of running a test suite + /// + public class TestSuiteResult : TestResult + { + private int passCount = 0; + private int failCount = 0; + private int skipCount = 0; + private int inconclusiveCount = 0; + + /// + /// Construct a TestSuiteResult base on a TestSuite + /// + /// The TestSuite to which the result applies + public TestSuiteResult(TestSuite suite) : base(suite) { } + + /// + /// Gets the number of test cases that failed + /// when running the test and all its children. + /// + public override int FailCount + { + get { return this.failCount; } + } + + /// + /// Gets the number of test cases that passed + /// when running the test and all its children. + /// + public override int PassCount + { + get { return this.passCount; } + } + + /// + /// Gets the number of test cases that were skipped + /// when running the test and all its children. + /// + public override int SkipCount + { + get { return this.skipCount; } + } + + /// + /// Gets the number of test cases that were inconclusive + /// when running the test and all its children. + /// + public override int InconclusiveCount + { + get { return this.inconclusiveCount; } + } + + /// + /// Add a child result + /// + /// The child result to be added + public override void AddResult(TestResult result) + { + base.AddResult(result); + + this.passCount += result.PassCount; + this.failCount += result.FailCount; + this.skipCount += result.SkipCount; + this.inconclusiveCount += result.InconclusiveCount; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/RuntimeFramework.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/RuntimeFramework.cs new file mode 100644 index 00000000000..4d26ecd8664 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/RuntimeFramework.cs @@ -0,0 +1,398 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.IO; +using System.Reflection; +using Microsoft.Win32; + +namespace NUnit.Framework.Internal +{ + /// + /// Enumeration identifying a common language + /// runtime implementation. + /// + public enum RuntimeType + { + /// Any supported runtime framework + Any, + /// Microsoft .NET Framework + Net, + /// Microsoft .NET Compact Framework + NetCF, + /// Microsoft Shared Source CLI + SSCLI, + /// Mono + Mono, + /// Silverlight + Silverlight, + /// MonoTouch + MonoTouch + } + + /// + /// RuntimeFramework represents a particular version + /// of a common language runtime implementation. + /// + [Serializable] + public sealed class RuntimeFramework + { + #region Static and Instance Fields + + /// + /// DefaultVersion is an empty Version, used to indicate that + /// NUnit should select the CLR version to use for the test. + /// + public static readonly Version DefaultVersion = new Version(0,0); + + private static RuntimeFramework currentFramework; + + private RuntimeType runtime; + private Version frameworkVersion; + private Version clrVersion; + private string displayName; + #endregion + + #region Constructor + + /// + /// Construct from a runtime type and version. If the version has + /// two parts, it is taken as a framework version. If it has three + /// or more, it is taken as a CLR version. In either case, the other + /// version is deduced based on the runtime type and provided version. + /// + /// The runtime type of the framework + /// The version of the framework + public RuntimeFramework( RuntimeType runtime, Version version) + { + this.runtime = runtime; + + this.frameworkVersion = runtime == RuntimeType.Mono && version.Major == 1 + ? new Version(1, 0) + : new Version(version.Major, version.Minor); + this.clrVersion = version; + + if (version.Build < 0) + this.clrVersion = GetClrVersion(runtime, version); + + this.displayName = GetDefaultDisplayName(runtime, version); + } + + private static Version GetClrVersion(RuntimeType runtime, Version version) + { + switch (runtime) + { + case RuntimeType.Silverlight: + return version.Major >= 4 + ? new Version(4, 0, 60310) + : new Version(2, 0, 50727); + + default: + switch (version.Major) + { + case 4: + return new Version(4, 0, 30319); + + case 2: + case 3: + return new Version(2, 0, 50727); + + case 1: + return version.Minor == 0 && runtime != RuntimeType.Mono + ? new Version(1, 0, 3705) + : new Version(1, 1, 4322); + + default: + return version; + } + } + } + + #endregion + + #region Properties + /// + /// Static method to return a RuntimeFramework object + /// for the framework that is currently in use. + /// + public static RuntimeFramework CurrentFramework + { + get + { + if (currentFramework == null) + { +#if SILVERLIGHT + currentFramework = new RuntimeFramework( + RuntimeType.Silverlight, + new Version(Environment.Version.Major, Environment.Version.Minor)); +#else + Type monoRuntimeType = Type.GetType("Mono.Runtime", false); + Type monoTouchType = Type.GetType("MonoTouch.UIKit.UIApplicationDelegate, monotouch"); + bool isMonoTouch = monoTouchType != null; + bool isMono = monoRuntimeType != null; + + RuntimeType runtime = isMonoTouch + ? RuntimeType.MonoTouch + : isMono + ? RuntimeType.Mono + : Environment.OSVersion.Platform == PlatformID.WinCE + ? RuntimeType.NetCF + : RuntimeType.Net; + + int major = Environment.Version.Major; + int minor = Environment.Version.Minor; + + if (isMono) + { + switch (major) + { + case 1: + minor = 0; + break; + case 2: + major = 3; + minor = 5; + break; + } + } +#if !__MOBILE__ + else /* It's windows */ + if (major == 2) + { + RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework"); + if (key != null) + { + string installRoot = key.GetValue("InstallRoot") as string; + if (installRoot != null) + { + if (Directory.Exists(Path.Combine(installRoot, "v3.5"))) + { + major = 3; + minor = 5; + } + else if (Directory.Exists(Path.Combine(installRoot, "v3.0"))) + { + major = 3; + minor = 0; + } + } + } + } +#endif + + currentFramework = new RuntimeFramework(runtime, new Version(major, minor)); + currentFramework.clrVersion = Environment.Version; + + if (isMono) + { + MethodInfo getDisplayNameMethod = monoRuntimeType.GetMethod( + "GetDisplayName", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.ExactBinding); + if (getDisplayNameMethod != null) + currentFramework.displayName = (string)getDisplayNameMethod.Invoke(null, new object[0]); + } +#endif + } + + return currentFramework; + } + } + + /// + /// The type of this runtime framework + /// + public RuntimeType Runtime + { + get { return runtime; } + } + + /// + /// The framework version for this runtime framework + /// + public Version FrameworkVersion + { + get { return frameworkVersion; } + } + + /// + /// The CLR version for this runtime framework + /// + public Version ClrVersion + { + get { return clrVersion; } + } + + /// + /// Return true if any CLR version may be used in + /// matching this RuntimeFramework object. + /// + public bool AllowAnyVersion + { + get { return this.clrVersion == DefaultVersion; } + } + + /// + /// Returns the Display name for this framework + /// + public string DisplayName + { + get { return displayName; } + } + + #endregion + + #region Public Methods + + /// + /// Parses a string representing a RuntimeFramework. + /// The string may be just a RuntimeType name or just + /// a Version or a hyphentated RuntimeType-Version or + /// a Version prefixed by 'v'. + /// + /// + /// + public static RuntimeFramework Parse(string s) + { + RuntimeType runtime = RuntimeType.Any; + Version version = DefaultVersion; + + string[] parts = s.Split(new char[] { '-' }); + if (parts.Length == 2) + { + runtime = (RuntimeType)System.Enum.Parse(typeof(RuntimeType), parts[0], true); + string vstring = parts[1]; + if (vstring != "") + version = new Version(vstring); + } + else if (char.ToLower(s[0]) == 'v') + { + version = new Version(s.Substring(1)); + } + else if (IsRuntimeTypeName(s)) + { + runtime = (RuntimeType)System.Enum.Parse(typeof(RuntimeType), s, true); + } + else + { + version = new Version(s); + } + + return new RuntimeFramework(runtime, version); + } + + /// + /// Overridden to return the short name of the framework + /// + /// + public override string ToString() + { + if (this.AllowAnyVersion) + { + return runtime.ToString().ToLower(); + } + else + { + string vstring = frameworkVersion.ToString(); + if (runtime == RuntimeType.Any) + return "v" + vstring; + else + return runtime.ToString().ToLower() + "-" + vstring; + } + } + + /// + /// Returns true if the current framework matches the + /// one supplied as an argument. Two frameworks match + /// if their runtime types are the same or either one + /// is RuntimeType.Any and all specified version components + /// are equal. Negative (i.e. unspecified) version + /// components are ignored. + /// + /// The RuntimeFramework to be matched. + /// True on match, otherwise false + public bool Supports(RuntimeFramework target) + { + if (this.Runtime != RuntimeType.Any + && target.Runtime != RuntimeType.Any + && this.Runtime != target.Runtime) + return false; + + if (this.AllowAnyVersion || target.AllowAnyVersion) + return true; + + if (!VersionsMatch(this.ClrVersion, target.ClrVersion)) + return false; + + return Runtime == RuntimeType.Silverlight + ? this.frameworkVersion.Major == target.FrameworkVersion.Major && this.frameworkVersion.Minor == target.FrameworkVersion.Minor + : this.FrameworkVersion.Major >= target.FrameworkVersion.Major && this.FrameworkVersion.Minor >= target.FrameworkVersion.Minor; + } + + #endregion + + #region Helper Methods + + private static bool IsRuntimeTypeName(string name) + { + foreach (string item in TypeHelper.GetEnumNames(typeof(RuntimeType))) + if (item.ToLower() == name.ToLower()) + return true; + + return false; + } + + private static string GetDefaultDisplayName(RuntimeType runtime, Version version) + { + if (version == DefaultVersion) + return runtime.ToString(); + else if (runtime == RuntimeType.Any) + return "v" + version.ToString(); + else + return runtime.ToString() + " " + version.ToString(); + } + + private static bool VersionsMatch(Version v1, Version v2) + { + return v1.Major == v2.Major && + v1.Minor == v2.Minor && + (v1.Build < 0 || v2.Build < 0 || v1.Build == v2.Build) && + (v1.Revision < 0 || v2.Revision < 0 || v1.Revision == v2.Revision); + } + +#if CLR_2_0 || CLR_4_0 + class FrameworkList : System.Collections.Generic.List { } +#else + class FrameworkList : System.Collections.ArrayList + { + public new RuntimeFramework[] ToArray() + { + return (RuntimeFramework[])base.ToArray(typeof(RuntimeFramework)); + } + } +#endif + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/StackFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/StackFilter.cs new file mode 100644 index 00000000000..34d571b62a6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/StackFilter.cs @@ -0,0 +1,52 @@ +// ***************************************************** +// Copyright 2007, Charlie Poole +// +// Licensed under the Open Software License version 3.0 +// ***************************************************** + +using System; +using System.IO; + +namespace NUnit.Framework.Internal +{ + /// + /// StackFilter class is used to remove internal NUnit + /// entries from a stack trace so that the resulting + /// trace provides better information about the test. + /// + public class StackFilter + { + /// + /// Filters a raw stack trace and returns the result. + /// + /// The original stack trace + /// A filtered stack trace + public static string Filter(string rawTrace) + { + if (rawTrace == null) return null; + + StringReader sr = new StringReader(rawTrace); + StringWriter sw = new StringWriter(); + + try + { + string line; + while ((line = sr.ReadLine()) != null && line.IndexOf("NUnit.Framework.Assert") >= 0) + /*Skip*/ + ; + + while (line != null) + { + sw.WriteLine(line); + line = sr.ReadLine(); + } + } + catch (Exception) + { + return rawTrace; + } + + return sw.ToString(); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/StringUtil.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/StringUtil.cs new file mode 100644 index 00000000000..c98bc60e136 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/StringUtil.cs @@ -0,0 +1,40 @@ +using System; + +namespace NUnit.Framework.Internal +{ + /// + /// Provides methods to support legacy string comparison methods. + /// + public class StringUtil + { + /// + /// Compares two strings for equality, ignoring case if requested. + /// + /// The first string. + /// The second string.. + /// if set to true, the case of the letters in the strings is ignored. + /// Zero if the strings are equivalent, a negative number if strA is sorted first, a positive number if + /// strB is sorted first + public static int Compare(string strA, string strB, bool ignoreCase) + { +#if SILVERLIGHT + StringComparison comparison = ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture; + return string.Compare(strA, strB, comparison); +#else + return string.Compare(strA, strB, ignoreCase); +#endif + } + + /// + /// Compares two strings for equality, ignoring case if requested. + /// + /// The first string. + /// The second string.. + /// if set to true, the case of the letters in the strings is ignored. + /// True if the strings are equivalent, false if not. + public static bool StringsEqual(string strA, string strB, bool ignoreCase) + { + return Compare(strA, strB, ignoreCase) == 0; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestExecutionContext.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestExecutionContext.cs new file mode 100644 index 00000000000..7b06fa69aaa --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestExecutionContext.cs @@ -0,0 +1,629 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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; +using System.Collections.Specialized; +using System.IO; +using System.Diagnostics; +using System.Globalization; +using System.Threading; + +#if !NUNITLITE +using System.Security.Principal; +#endif + +using NUnit.Framework.Api; +#if !SILVERLIGHT && !NETCF +using System.Runtime.Remoting.Messaging; +#endif + +namespace NUnit.Framework.Internal +{ + /// + /// Helper class used to save and restore certain static or + /// singleton settings in the environment that affect tests + /// or which might be changed by the user tests. + /// + /// An internal class is used to hold settings and a stack + /// of these objects is pushed and popped as Save and Restore + /// are called. + /// + /// Static methods for each setting forward to the internal + /// object on the top of the stack. + /// + public class TestExecutionContext +#if !SILVERLIGHT && !NETCF + : ILogicalThreadAffinative +#endif + { + #region Instance Fields + + /// + /// Link to a prior saved context + /// + public TestExecutionContext prior; + + /// + /// The currently executing test + /// + private Test currentTest; + + /// + /// The time the test began execution + /// + private DateTime startTime; + + /// + /// The active TestResult for the current test + /// + private TestResult currentResult; + + /// + /// The work directory to receive test output + /// + private string workDirectory; + + /// + /// The object on which tests are currently being executed - i.e. the user fixture object + /// + private object testObject; + + /// + /// The event listener currently receiving notifications + /// + private ITestListener listener = TestListener.NULL; + + /// + /// The number of assertions for the current test + /// + private int assertCount; + + /// + /// Indicates whether execution should terminate after the first error + /// + private bool stopOnError; + + /// + /// Default timeout for test cases + /// + private int testCaseTimeout; + + private RandomGenerator randomGenerator; + +#if !NETCF + /// + /// The current culture + /// + private CultureInfo currentCulture; + + /// + /// The current UI culture + /// + private CultureInfo currentUICulture; +#endif + +#if !NETCF && !SILVERLIGHT + /// + /// Destination for standard output + /// + private TextWriter outWriter; + + /// + /// Destination for standard error + /// + private TextWriter errorWriter; + + /// + /// Indicates whether trace is enabled + /// + private bool tracing; + + /// + /// Destination for Trace output + /// + private TextWriter traceWriter; +#endif + +#if !NUNITLITE + /// + /// Indicates whether logging is enabled + /// + private bool logging; + + /// + /// The current working directory + /// + private string currentDirectory; + + private Log4NetCapture logCapture; + + /// + /// The current Principal. + /// + private IPrincipal currentPrincipal; +#endif + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public TestExecutionContext() + { + this.prior = null; + this.testCaseTimeout = 0; + +#if !NETCF + this.currentCulture = CultureInfo.CurrentCulture; + this.currentUICulture = CultureInfo.CurrentUICulture; +#endif + +#if !NETCF && !SILVERLIGHT + this.outWriter = Console.Out; + this.errorWriter = Console.Error; + this.traceWriter = null; + this.tracing = false; +#endif + +#if !NUNITLITE + this.logging = false; + this.currentDirectory = Environment.CurrentDirectory; + this.logCapture = new Log4NetCapture(); + this.currentPrincipal = Thread.CurrentPrincipal; +#endif + } + + /// + /// Initializes a new instance of the class. + /// + /// An existing instance of TestExecutionContext. + public TestExecutionContext( TestExecutionContext other ) + { + this.prior = other; + + this.currentTest = other.currentTest; + this.currentResult = other.currentResult; + this.testObject = other.testObject; + this.workDirectory = other.workDirectory; + this.listener = other.listener; + this.stopOnError = other.stopOnError; + this.testCaseTimeout = other.testCaseTimeout; + +#if !NETCF + this.currentCulture = CultureInfo.CurrentCulture; + this.currentUICulture = CultureInfo.CurrentUICulture; +#endif + +#if !NETCF && !SILVERLIGHT + this.outWriter = other.outWriter; + this.errorWriter = other.errorWriter; + this.traceWriter = other.traceWriter; + this.tracing = other.tracing; +#endif + +#if !NUNITLITE + this.logging = other.logging; + this.currentDirectory = Environment.CurrentDirectory; + this.logCapture = other.logCapture; + this.currentPrincipal = Thread.CurrentPrincipal; +#endif + } + + #endregion + + #region Static Singleton Instance + + /// + /// The current context, head of the list of saved contexts. + /// +#if SILVERLIGHT || NETCF || __MOBILE__ +#if (CLR_2_0 || CLR_4_0) && !NETCF + [ThreadStatic] +#endif + private static TestExecutionContext current; +#else + private static readonly string CONTEXT_KEY = "NUnit.Framework.TestContext"; +#endif + + /// + /// Gets the current context. + /// + /// The current context. + public static TestExecutionContext CurrentContext + { + get + { +#if SILVERLIGHT || NETCF || __MOBILE__ + if (current == null) + current = new TestExecutionContext(); + + return current; +#else + return CallContext.GetData(CONTEXT_KEY) as TestExecutionContext; +#endif + } + } + + #endregion + + #region Static Methods + + internal static void SetCurrentContext(TestExecutionContext ec) + { +#if SILVERLIGHT || NETCF || __MOBILE__ + current = ec; +#else + CallContext.SetData(CONTEXT_KEY, ec); +#endif + } + + #endregion + + #region Properties + + /// + /// Gets or sets the current test + /// + public Test CurrentTest + { + get { return currentTest; } + set { currentTest = value; } + } + + /// + /// The time the current test started execution + /// + public DateTime StartTime + { + get { return startTime; } + set { startTime = value; } + } + + /// + /// Gets or sets the current test result + /// + public TestResult CurrentResult + { + get { return currentResult; } + set { currentResult = value; } + } + + /// + /// The current test object - that is the user fixture + /// object on which tests are being executed. + /// + public object TestObject + { + get { return testObject; } + set { testObject = value; } + } + + /// + /// Get or set the working directory + /// + public string WorkDirectory + { + get { return workDirectory; } + set { workDirectory = value; } + } + + /// + /// Get or set indicator that run should stop on the first error + /// + public bool StopOnError + { + get { return stopOnError; } + set { stopOnError = value; } + } + + /// + /// The current test event listener + /// + internal ITestListener Listener + { + get { return listener; } + set { listener = value; } + } + + /// + /// Gets the RandomGenerator specific to this Test + /// + public RandomGenerator RandomGenerator + { + get + { + if (randomGenerator == null) + { + randomGenerator = new RandomGenerator(currentTest.Seed); + } + return randomGenerator; + } + } + + /// + /// Gets the assert count. + /// + /// The assert count. + internal int AssertCount + { + get { return assertCount; } + set { assertCount = value; } + } + + /// + /// Gets or sets the test case timeout value + /// + public int TestCaseTimeout + { + get { return testCaseTimeout; } + set { testCaseTimeout = value; } + } + +#if !NETCF + /// + /// Saves or restores the CurrentCulture + /// + public CultureInfo CurrentCulture + { + get { return currentCulture; } + set + { + currentCulture = value; + Thread.CurrentThread.CurrentCulture = currentCulture; + } + } + + /// + /// Saves or restores the CurrentUICulture + /// + public CultureInfo CurrentUICulture + { + get { return currentUICulture; } + set + { + currentUICulture = value; + Thread.CurrentThread.CurrentUICulture = currentUICulture; + } + } +#endif + +#if !NETCF && !SILVERLIGHT + /// + /// Controls where Console.Out is directed + /// + internal TextWriter Out + { + get { return outWriter; } + set + { + if ( outWriter != value ) + { + outWriter = value; + Console.Out.Flush(); + Console.SetOut( outWriter ); + } + } + } + + /// + /// Controls where Console.Error is directed + /// + internal TextWriter Error + { + get { return errorWriter; } + set + { + if ( errorWriter != value ) + { + errorWriter = value; + Console.Error.Flush(); + Console.SetError( errorWriter ); + } + } + } + + /// + /// Controls whether trace and debug output are written + /// to the standard output. + /// + internal bool Tracing + { + get { return tracing; } + set + { + if (tracing != value) + { + if (traceWriter != null && tracing) + StopTracing(); + + tracing = value; + + if (traceWriter != null && tracing) + StartTracing(); + } + } + } + + /// + /// Controls where Trace output is directed + /// + internal TextWriter TraceWriter + { + get { return traceWriter; } + set + { + if ( traceWriter != value ) + { + if ( traceWriter != null && tracing ) + StopTracing(); + + traceWriter = value; + + if ( traceWriter != null && tracing ) + StartTracing(); + } + } + } + + private void StopTracing() + { + traceWriter.Close(); + System.Diagnostics.Trace.Listeners.Remove( "NUnit" ); + } + + private void StartTracing() + { +#if !__MOBILE__ + System.Diagnostics.Trace.Listeners.Add( new TextWriterTraceListener( traceWriter, "NUnit" ) ); +#endif + } +#endif + +#if !NUNITLITE + /// + /// Controls whether log output is captured + /// + public bool Logging + { + get { return logCapture.Enabled; } + set { logCapture.Enabled = value; } + } + + /// + /// Gets or sets the Log writer, which is actually held by a log4net + /// TextWriterAppender. When first set, the appender will be created + /// and will thereafter send any log events to the writer. + /// + /// In normal operation, LogWriter is set to an EventListenerTextWriter + /// connected to the EventQueue in the test domain. The events are + /// subsequently captured in the Gui an the output displayed in + /// the Log tab. The application under test does not need to define + /// any additional appenders. + /// + public TextWriter LogWriter + { + get { return logCapture.Writer; } + set { logCapture.Writer = value; } + } + + /// + /// Saves and restores the CurrentDirectory + /// + public string CurrentDirectory + { + get { return currentDirectory; } + set + { + currentDirectory = value; + Environment.CurrentDirectory = currentDirectory; + } + } + + /// + /// Gets or sets the current for the Thread. + /// + public IPrincipal CurrentPrincipal + { + get { return this.currentPrincipal; } + set + { + this.currentPrincipal = value; + Thread.CurrentPrincipal = this.currentPrincipal; + } + } +#endif + + #endregion + + #region Instance Methods + + /// + /// Saves the old context and returns a fresh one + /// with the same settings. + /// + public TestExecutionContext Save() + { + return new TestExecutionContext(this); + } + + /// + /// Restores the last saved context and puts + /// any saved settings back into effect. + /// + public TestExecutionContext Restore() + { + if (prior == null) + throw new InvalidOperationException("TestContext: too many Restores"); + + this.TestCaseTimeout = prior.TestCaseTimeout; + +#if !NETCF + this.CurrentCulture = prior.CurrentCulture; + this.CurrentUICulture = prior.CurrentUICulture; +#endif + +#if !NETCF && !SILVERLIGHT + this.Out = prior.Out; + this.Error = prior.Error; + this.Tracing = prior.Tracing; +#endif + +#if !NUNITLITE + this.CurrentDirectory = prior.CurrentDirectory; + this.CurrentPrincipal = prior.CurrentPrincipal; +#endif + + return prior; + } + + /// + /// Record any changes in the environment made by + /// the test code in the execution context so it + /// will be passed on to lower level tests. + /// + public void UpdateContext() + { +#if !NETCF + this.currentCulture = CultureInfo.CurrentCulture; + this.currentUICulture = CultureInfo.CurrentUICulture; +#endif +#if !NUNITLITE + this.currentDirectory = Environment.CurrentDirectory; + this.currentPrincipal = System.Threading.Thread.CurrentPrincipal; +#endif + } + + /// + /// Increments the assert count. + /// + public void IncrementAssertCount() + { + System.Threading.Interlocked.Increment(ref assertCount); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestFilter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestFilter.cs new file mode 100644 index 00000000000..a27b61e4c6a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestFilter.cs @@ -0,0 +1,183 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// Interface to be implemented by filters applied to tests. + /// The filter applies when running the test, after it has been + /// loaded, since this is the only time an ITest exists. + /// + [Serializable] + public abstract class TestFilter : ITestFilter + { + /// + /// Unique Empty filter. + /// + public static TestFilter Empty = new EmptyFilter(); + + /// + /// Indicates whether this is the EmptyFilter + /// + public bool IsEmpty + { + get { return this is TestFilter.EmptyFilter; } + } + + /// + /// Determine if a particular test passes the filter criteria. The default + /// implementation checks the test itself, its parents and any descendants. + /// + /// Derived classes may override this method or any of the Match methods + /// to change the behavior of the filter. + /// + /// The test to which the filter is applied + /// True if the test passes the filter, otherwise false + public virtual bool Pass( ITest test ) + { + return Match(test) || MatchParent(test) || MatchDescendant(test); + } + + /// + /// Determine whether the test itself matches the filter criteria, without + /// examining either parents or descendants. + /// + /// The test to which the filter is applied + /// True if the filter matches the any parent of the test + public abstract bool Match(ITest test); + + /// + /// Determine whether any ancestor of the test matches the filter criteria + /// + /// The test to which the filter is applied + /// True if the filter matches the an ancestor of the test + protected virtual bool MatchParent(ITest test) + { + return (test.RunState != RunState.Explicit && test.Parent != null && + (Match(test.Parent) || MatchParent(test.Parent))); + } + + /// + /// Determine whether any descendant of the test matches the filter criteria. + /// + /// The test to be matched + /// True if at least one descendant matches the filter criteria + protected virtual bool MatchDescendant(ITest test) + { + if (test.Tests == null) + return false; + + foreach (ITest child in test.Tests) + { + if (Match(child) || MatchDescendant(child)) + return true; + } + + return false; + } + +#if !NUNITLITE + public static TestFilter FromXml(string xmlText) + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlText); + XmlNode topNode = doc.FirstChild; + + if (topNode.Name != "filter") + throw new Exception("Expected filter element at top level"); + + // Initially, an empty filter + TestFilter result = TestFilter.Empty; + bool isEmptyResult = true; + + XmlNodeList testNodes = topNode.SelectNodes("tests/test"); + XmlNodeList includeNodes = topNode.SelectNodes("include/category"); + XmlNodeList excludeNodes = topNode.SelectNodes("exclude/category"); + + if (testNodes.Count > 0) + { + SimpleNameFilter nameFilter = new SimpleNameFilter(); + foreach (XmlNode testNode in topNode.SelectNodes("tests/test")) + nameFilter.Add(testNode.InnerText); + + result = nameFilter; + isEmptyResult = false; + } + + if (includeNodes.Count > 0) + { + //CategoryFilter includeFilter = new CategoryFilter(); + //foreach (XmlNode includeNode in includeNodes) + // includeFilter.AddCategory(includeNode.InnerText); + + // Temporarily just look at the first element + XmlNode includeNode = includeNodes[0]; + TestFilter includeFilter = new CategoryExpression(includeNode.InnerText).Filter; + + if (isEmptyResult) + result = includeFilter; + else + result = new AndFilter(result, includeFilter); + isEmptyResult = false; + } + + if (excludeNodes.Count > 0) + { + CategoryFilter categoryFilter = new CategoryFilter(); + foreach (XmlNode excludeNode in excludeNodes) + categoryFilter.AddCategory(excludeNode.InnerText); + TestFilter excludeFilter = new NotFilter(categoryFilter); + + if (isEmptyResult) + result = excludeFilter; + else + result = new AndFilter(result, excludeFilter); + isEmptyResult = false; + } + + return result; + } +#endif + + /// + /// Nested class provides an empty filter - one that always + /// returns true when called, unless the test is marked explicit. + /// + [Serializable] + private class EmptyFilter : TestFilter + { + public override bool Match( ITest test ) + { + return test.RunState != RunState.Explicit; + } + + public override bool Pass( ITest test ) + { + return test.RunState != RunState.Explicit; + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestFixtureBuilder.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestFixtureBuilder.cs new file mode 100644 index 00000000000..c67404222be --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestFixtureBuilder.cs @@ -0,0 +1,80 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Builders; + +namespace NUnit.Framework.Internal +{ + /// + /// TestFixtureBuilder contains static methods for building + /// TestFixtures from types. It uses builtin SuiteBuilders + /// and any installed extensions to do it. + /// + public class TestFixtureBuilder + { + private static Extensibility.ISuiteBuilder builder = new NUnitTestFixtureBuilder(); + + /// + /// Determines whether this instance [can build from] the specified type. + /// + /// The type. + /// + /// true if this instance [can build from] the specified type; otherwise, false. + /// + public static bool CanBuildFrom( Type type ) + { + return builder.CanBuildFrom(type); + } + + /// + /// Build a test fixture from a given type. + /// + /// The type to be used for the fixture + /// A TestSuite if the fixture can be built, null if not + public static Test BuildFrom( Type type ) + { + return builder.BuildFrom( type ); + } + + /// + /// Build a fixture from an object. + /// + /// The object to be used for the fixture + /// A TestSuite if fixture type can be built, null if not + public static Test BuildFrom( object fixture ) + { + Test suite = BuildFrom( fixture.GetType() ); + if( suite != null) + suite.Fixture = fixture; + return suite; + } + + /// + /// Private constructor to prevent instantiation + /// + private TestFixtureBuilder() { } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestListener.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestListener.cs new file mode 100644 index 00000000000..537ab6fefcc --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TestListener.cs @@ -0,0 +1,66 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// TestListener provides an implementation of ITestListener that + /// does nothing. It is used only throught its NULL property. + /// + public class TestListener : ITestListener + { + /// + /// Called when a test has just started + /// + /// The test that is starting + public void TestStarted(ITest test){} + + /// + /// Called when a test case has finished + /// + /// The result of the test + public void TestFinished(ITestResult result){} + + /// + /// Called when the test creates text output. + /// + /// A console message + public void TestOutput(TestOutput testOutput) {} + + /// + /// Construct a new TestListener - private so it may not be used. + /// + private TestListener() { } + + /// + /// Get a listener that does nothing + /// + public static ITestListener NULL + { + get { return new TestListener();} + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/ParameterizedFixtureSuite.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/ParameterizedFixtureSuite.cs new file mode 100644 index 00000000000..d0e050c55de --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/ParameterizedFixtureSuite.cs @@ -0,0 +1,71 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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 NUnit.Framework.Internal +{ + /// + /// ParameterizedFixtureSuite serves as a container for the set of test + /// fixtures created from a given Type using various parameters. + /// + public class ParameterizedFixtureSuite : TestSuite + { + private Type type; + + /// + /// Initializes a new instance of the class. + /// + /// The type. + public ParameterizedFixtureSuite(Type type) : base(type.Namespace, TypeHelper.GetDisplayName(type)) + { + this.type = type; + } + + /// + /// Gets the Type represented by this suite. + /// + /// A Sysetm.Type. + public Type ParameterizedType + { + get { return type; } + } + + /// + /// Gets a string representing the type of test + /// + /// + public override string TestType + { + get + { +#if CLR_2_0 || CLR_4_0 + if (this.ParameterizedType.ContainsGenericParameters) + return "GenericFixture"; +#endif + + return "ParameterizedFixture"; + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/ParameterizedMethodSuite.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/ParameterizedMethodSuite.cs new file mode 100644 index 00000000000..0af0cc50c93 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/ParameterizedMethodSuite.cs @@ -0,0 +1,95 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Internal.Commands; + +namespace NUnit.Framework.Internal +{ + /// + /// ParameterizedMethodSuite holds a collection of individual + /// TestMethods with their arguments applied. + /// + public class ParameterizedMethodSuite : TestSuite + { + private MethodInfo _method; + private bool _isTheory; + + /// + /// Construct from a MethodInfo + /// + /// + public ParameterizedMethodSuite(MethodInfo method) + : base(method.ReflectedType.FullName, method.Name) + { + _method = method; + _isTheory = method.IsDefined(typeof(TheoryAttribute), true); + this.maintainTestOrder = true; + } + + /// + /// Gets the MethodInfo for which this suite is being built. + /// + public MethodInfo Method + { + get { return _method; } + } + + /// + /// Gets a string representing the type of test + /// + /// + public override string TestType + { + get + { + if (_isTheory) + return "Theory"; + +#if CLR_2_0 || CLR_4_0 + if (this.Method.ContainsGenericParameters) + return "GenericMethod"; +#endif + + return "ParameterizedMethod"; + } + } + + /// + /// Gets the command to be executed after all the child + /// tests are run. Overridden in ParameterizedMethodSuite + /// to set the result to failure if all the child tests + /// were inconclusive. + /// + /// + public override TestCommand GetOneTimeTearDownCommand() + { + TestCommand command = base.GetOneTimeTearDownCommand(); + + if (_isTheory) + command = new TheoryResultCommand(command); + + return command; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/Test.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/Test.cs new file mode 100644 index 00000000000..093dd1f8ec8 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/Test.cs @@ -0,0 +1,416 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Internal.WorkItems; + +namespace NUnit.Framework.Internal +{ + /// + /// The Test abstract class represents a test within the framework. + /// + public abstract class Test : ITest, IComparable + { + #region Fields + + /// + /// Static value to seed ids. It's started at 1000 so any + /// uninitialized ids will stand out. + /// + private static int nextID = 1000; + + private int id; + private string name; + private string fullName; + private int seed; + + /// + /// Indicates whether the test should be executed + /// + private RunState runState; + + /// + /// Test suite containing this test, or null + /// + private ITest parent; + + /// + /// A dictionary of properties, used to add information + /// to tests without requiring the class to change. + /// + private PropertyBag properties; + + /// + /// The System.Type of the fixture for this test, if there is one + /// + private Type fixtureType; + + /// + /// The fixture object, if it has been created + /// + private object fixture; + + /// + /// The SetUp methods. + /// + protected MethodInfo[] setUpMethods; + + /// + /// The teardown methods + /// + protected MethodInfo[] tearDownMethods; + + #endregion + + #region Construction + + /// + /// Constructs a test given its name + /// + /// The name of the test + protected Test( string name ) + { + this.fullName = name; + this.name = name; + this.id = unchecked(nextID++); + + this.runState = RunState.Runnable; + } + + /// + /// Constructs a test given the path through the + /// test hierarchy to its parent and a name. + /// + /// The parent tests full name + /// The name of the test + protected Test( string pathName, string name ) + { + this.fullName = pathName == null || pathName == string.Empty + ? name : pathName + "." + name; + this.name = name; + this.id = unchecked(nextID++); + + this.runState = RunState.Runnable; + } + + /// + /// TODO: Documentation needed for constructor + /// + /// + protected Test(Type fixtureType) : this(fixtureType.FullName) + { + this.fixtureType = fixtureType; + } + + #endregion + + #region ITest Members + + /// + /// Gets or sets the id of the test + /// + /// + public int Id + { + get { return id; } + set { id = value; } + } + + /// + /// Gets or sets the name of the test + /// + public string Name + { + get { return name; } + set { name = value; } + } + + /// + /// Gets or sets the fully qualified name of the test + /// + /// + public string FullName + { + get { return fullName; } + set { fullName = value; } + } + + /// + /// Gets the Type of the fixture used in running this test + /// or null if no fixture type is associated with it. + /// + public Type FixtureType + { + get { return fixtureType; } + } + + /// + /// Whether or not the test should be run + /// + public RunState RunState + { + get { return runState; } + set { runState = value; } + } + + /// + /// Gets the name used for the top-level element in the + /// XML representation of this test + /// + public abstract string XmlElementName + { + get; + } + + /// + /// Gets a string representing the type of test. Used as an attribute + /// value in the XML representation of a test and has no other + /// function in the framework. + /// + public virtual string TestType + { + get { return this.GetType().Name; } + } + + /// + /// Gets a count of test cases represented by + /// or contained under this test. + /// + public virtual int TestCaseCount + { + get { return 1; } + } + + /// + /// Gets the properties for this test + /// + public IPropertyBag Properties + { + get + { + if ( properties == null ) + properties = new PropertyBag(); + + return properties; + } + } + + /// + /// Returns true if this is a TestSuite + /// + public bool IsSuite + { + get { return this is TestSuite; } + } + + /// + /// Gets a bool indicating whether the current test + /// has any descendant tests. + /// + public abstract bool HasChildren { get; } + + /// + /// Gets the parent as a Test object. + /// Used by the core to set the parent. + /// + public ITest Parent + { + get { return parent; } + set { parent = value; } + } + + /// + /// Gets or Sets the Int value representing the seed for the RandomGenerator + /// + /// + public int Seed + { + get { return seed; } + set { seed = value; } + } + + /// + /// Gets this test's child tests + /// + /// A list of child tests + +#if CLR_2_0 || CLR_4_0 + public abstract System.Collections.Generic.IList Tests { get; } +#else + public abstract System.Collections.IList Tests { get; } +#endif + + #endregion + + #region IXmlNodeBuilder Members + + /// + /// Returns the Xml representation of the test + /// + /// If true, include child tests recursively + /// + public XmlNode ToXml(bool recursive) + { + XmlNode topNode = XmlNode.CreateTopLevelElement("dummy"); + + XmlNode thisNode = AddToXml(topNode, recursive); + + return thisNode; + } + + /// + /// Returns an XmlNode representing the current result after + /// adding it as a child of the supplied parent node. + /// + /// The parent node. + /// If true, descendant results are included + /// + public abstract XmlNode AddToXml(XmlNode parentNode, bool recursive); + + #endregion + + #region IComparable Members + + /// + /// Compares this test to another test for sorting purposes + /// + /// The other test + /// Value of -1, 0 or +1 depending on whether the current test is less than, equal to or greater than the other test + public int CompareTo(object obj) + { + Test other = obj as Test; + + if (other == null) + return -1; + + return this.FullName.CompareTo(other.FullName); + } + + #endregion + + #region Other Public Methods + + /// + /// Creates a TestResult for this test. + /// + /// A TestResult suitable for this type of test. + public abstract TestResult MakeTestResult(); + + /// + /// Creates a WorkItem for executing this test. + /// + /// A filter to be used in selecting child tests + /// A new WorkItem + public abstract WorkItem CreateWorkItem(ITestFilter childFilter); + + /// + /// Modify a newly constructed test by applying any of NUnit's common + /// attributes, based on a supplied ICustomAttributeProvider, which is + /// usually the reflection element from which the test was constructed, + /// but may not be in some instances. The attributes retrieved are + /// saved for use in subsequent operations. + /// + /// An object implementing ICustomAttributeProvider + public void ApplyAttributesToTest(ICustomAttributeProvider provider) + { + foreach (IApplyToTest iApply in provider.GetCustomAttributes(typeof(IApplyToTest), true)) + iApply.ApplyToTest(this); + } + + #endregion + + #region Protected Methods + + /// + /// Add standard attributes and members to a test node. + /// + /// + /// + protected void PopulateTestNode(XmlNode thisNode, bool recursive) + { + thisNode.AddAttribute("id", this.Id.ToString()); + thisNode.AddAttribute("name", this.Name); + thisNode.AddAttribute("fullname", this.FullName); + + if (Properties.Count > 0) + Properties.AddToXml(thisNode, recursive); + } + + #endregion + + #region Internal Properties + + /// + /// Gets or sets a fixture object for running this test. + /// Provided for use by LegacySuiteBuilder. + /// + public object Fixture + { + get { return fixture; } + set { fixture = value; } + } + + /// + /// Gets the set up methods. + /// + /// + internal virtual MethodInfo[] SetUpMethods + { + get + { + if (setUpMethods == null && this.Parent != null) + { + TestSuite suite = this.Parent as TestSuite; + if (suite != null) + setUpMethods = suite.SetUpMethods; + } + + return setUpMethods; + } + } + + /// + /// Gets the tear down methods. + /// + /// + internal virtual MethodInfo[] TearDownMethods + { + get + { + if (tearDownMethods == null && this.Parent != null) + { + TestSuite suite = this.Parent as TestSuite; + if (suite != null) + tearDownMethods = suite.TearDownMethods; + } + + return tearDownMethods; + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestAssembly.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestAssembly.cs new file mode 100644 index 00000000000..d554b472d40 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestAssembly.cs @@ -0,0 +1,57 @@ +// *********************************************************************** +// Copyright (c) 2010 Charlie Poole +// +// 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.IO; +using System.Reflection; + +namespace NUnit.Framework.Internal +{ + /// + /// TestAssembly is a TestSuite that represents the execution + /// of tests in a managed assembly. + /// + public class TestAssembly : TestSuite + { + /// + /// Initializes a new instance of the class. + /// + /// The assembly containing the tests. + /// The path used to load the assembly. + public TestAssembly(Assembly assembly, string path) : base(path) + { + this.Name = Path.GetFileName(path); + } + + /// + /// Gets the name used for the top-level element in the + /// XML representation of this test + /// + public override string TestType + { + get + { + return "Assembly"; + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestFixture.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestFixture.cs new file mode 100644 index 00000000000..279c8614e6b --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestFixture.cs @@ -0,0 +1,60 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Reflection; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal +{ + /// + /// TestFixture is a surrogate for a user test fixture class, + /// containing one or more tests. + /// + public class TestFixture : TestSuite + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// Type of the fixture. + public TestFixture(Type fixtureType) + : this(fixtureType, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// Type of the fixture. + /// The arguments. + public TestFixture(Type fixtureType, object[] arguments) + : base(fixtureType, arguments) + { + this.setUpMethods = Reflect.GetMethodsWithAttribute(FixtureType, typeof(SetUpAttribute), true); + this.tearDownMethods = Reflect.GetMethodsWithAttribute(FixtureType, typeof(TearDownAttribute), true); + } + + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestMethod.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestMethod.cs new file mode 100644 index 00000000000..cdbbd68c375 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestMethod.cs @@ -0,0 +1,268 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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. +// *********************************************************************** + +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Internal.WorkItems; + +namespace NUnit.Framework.Internal +{ + /// + /// The TestMethod class represents a Test implemented as a method. + /// Because of how exceptions are handled internally, this class + /// must incorporate processing of expected exceptions. A change to + /// the Test interface might make it easier to process exceptions + /// in an object that aggregates a TestMethod in the future. + /// + public class TestMethod : Test + { + #region Fields + + /// + /// The test method + /// + internal MethodInfo method; + + /// + /// A list of all decorators applied to the test by attributes or parameterset arguments + /// +#if CLR_2_0 || CLR_4_0 + private List decorators = new List(); +#else + private System.Collections.ArrayList decorators = new System.Collections.ArrayList(); +#endif + + /// + /// The ParameterSet used to create this test method + /// + internal ParameterSet parms; + + #endregion + + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + /// The method to be used as a test. + /// The suite or fixture to which the new test will be added + public TestMethod(MethodInfo method, Test parentSuite) + : base( method.ReflectedType ) + { + this.Name = method.Name; + this.FullName += "." + this.Name; + + // Disambiguate call to base class methods + // TODO: This should not be here - it's a presentation issue + if( method.DeclaringType != method.ReflectedType) + this.Name = method.DeclaringType.Name + "." + method.Name; + + // Needed to give proper fullname to test in a parameterized fixture. + // Without this, the arguments to the fixture are not included. + string prefix = method.ReflectedType.FullName; + if (parentSuite != null) + { + prefix = parentSuite.FullName; + this.FullName = prefix + "." + this.Name; + } + + this.method = method; + } + + #endregion + + #region Properties + + /// + /// Gets the method. + /// + /// The method that performs the test. + public MethodInfo Method + { + get { return method; } + } + + /// + /// Gets a list of custom decorators for this test. + /// +#if CLR_2_0 || CLR_4_0 + public IList CustomDecorators +#else + public System.Collections.IList CustomDecorators +#endif + { + get { return decorators; } + } + + internal bool HasExpectedResult + { + get { return parms != null && parms.HasExpectedResult; } + } + + internal object ExpectedResult + { + get { return parms != null ? parms.ExpectedResult : null; } + } + + internal object[] Arguments + { + get { return parms != null ? parms.Arguments : null; } + } + + internal bool IsAsync + { + get + { +#if NET_4_5 + return method.IsDefined(typeof(System.Runtime.CompilerServices.AsyncStateMachineAttribute), false); +#else + return false; +#endif + } + } + + #endregion + + #region Test Overrides + + /// + /// Overridden to return a TestCaseResult. + /// + /// A TestResult for this test. + public override TestResult MakeTestResult() + { + return new TestCaseResult(this); + } + + /// + /// Gets a bool indicating whether the current test + /// has any descendant tests. + /// + public override bool HasChildren + { + get { return false; } + } + + /// + /// Returns an XmlNode representing the current result after + /// adding it as a child of the supplied parent node. + /// + /// The parent node. + /// If true, descendant results are included + /// + public override XmlNode AddToXml(XmlNode parentNode, bool recursive) + { + XmlNode thisNode = parentNode.AddElement(XmlElementName); + + PopulateTestNode(thisNode, recursive); + + thisNode.AddAttribute("seed", this.Seed.ToString()); + + return thisNode; + } + + /// + /// Gets this test's child tests + /// + /// A list of child tests +#if CLR_2_0 || CLR_4_0 + public override IList Tests +#else + public override System.Collections.IList Tests +#endif + { + get { return new ITest[0]; } + } + + /// + /// Gets the name used for the top-level element in the + /// XML representation of this test + /// + public override string XmlElementName + { + get { return "test-case"; } + } + + /// + /// Creates a test command for use in running this test. + /// + /// + public virtual TestCommand MakeTestCommand() + { + if (RunState != RunState.Runnable && RunState != RunState.Explicit) + return new SkipCommand(this); + + TestCommand command = new TestMethodCommand(this); + + command = ApplyDecoratorsToCommand(command); + + IApplyToContext[] changes = (IApplyToContext[])this.Method.GetCustomAttributes(typeof(IApplyToContext), true); + if (changes.Length > 0) + command = new ApplyChangesToContextCommand(command, changes); + + return command; + } + + /// + /// Creates a WorkItem for executing this test. + /// + /// A filter to be used in selecting child tests + /// A new WorkItem + public override WorkItem CreateWorkItem(ITestFilter childFilter) + { + // For simple test cases, we ignore the filter + return new SimpleWorkItem(this); + } + + #endregion + + #region Helper Methods + + private TestCommand ApplyDecoratorsToCommand(TestCommand command) + { + CommandDecoratorList decorators = new CommandDecoratorList(); + + // Add Standard stuff + decorators.Add(new SetUpTearDownDecorator()); + + // Add Decorators supplied by attributes and parameter sets + foreach (ICommandDecorator decorator in CustomDecorators) + decorators.Add(decorator); + + decorators.OrderByStage(); + + foreach (ICommandDecorator decorator in decorators) + { + command = decorator.Decorate(command); + } + + return command; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestSuite.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestSuite.cs new file mode 100644 index 00000000000..85cf8d63bb6 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/Tests/TestSuite.cs @@ -0,0 +1,317 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#else +using System.Collections; +#endif +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Internal.WorkItems; + +namespace NUnit.Framework.Internal +{ + /// + /// TestSuite represents a composite test, which contains other tests. + /// + public class TestSuite : Test + { + #region Fields + + /// + /// Our collection of child tests + /// +#if CLR_2_0 || CLR_4_0 + private List tests = new List(); +#else + private ArrayList tests = new ArrayList(); +#endif + + /// + /// Set to true to suppress sorting this suite's contents + /// + protected bool maintainTestOrder; + + /// + /// Argument list for use in creating the fixture. + /// + internal object[] arguments; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The name of the suite. + public TestSuite( string name ) + : base( name ) { } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the parent suite. + /// The name of the suite. + public TestSuite( string parentSuiteName, string name ) + : base( parentSuiteName, name ) { } + + /// + /// Initializes a new instance of the class. + /// + /// Type of the fixture. + public TestSuite(Type fixtureType) + : this(fixtureType, null) { } + + /// + /// Initializes a new instance of the class. + /// + /// Type of the fixture. + /// The arguments. + public TestSuite(Type fixtureType, object[] arguments) + : base(fixtureType) + { + string name = TypeHelper.GetDisplayName(fixtureType, arguments); + this.Name = name; + + this.FullName = name; + string nspace = fixtureType.Namespace; + if (nspace != null && nspace != "") + this.FullName = nspace + "." + name; + this.arguments = arguments; + } + + #endregion + + #region Public Methods + + /// + /// Sorts tests under this suite. + /// + public void Sort() + { + if (!maintainTestOrder) + { + this.tests.Sort(); + + foreach (Test test in Tests) + { + TestSuite suite = test as TestSuite; + if (suite != null) + suite.Sort(); + } + } + } + +#if false + /// + /// Sorts tests under this suite using the specified comparer. + /// + /// The comparer. + public void Sort(IComparer comparer) + { + this.tests.Sort(comparer); + + foreach( Test test in Tests ) + { + TestSuite suite = test as TestSuite; + if ( suite != null ) + suite.Sort(comparer); + } + } +#endif + + /// + /// Adds a test to the suite. + /// + /// The test. + public void Add( Test test ) + { +// if( test.RunState == RunState.Runnable ) +// { +// test.RunState = this.RunState; +// test.IgnoreReason = this.IgnoreReason; +// } + test.Parent = this; + tests.Add(test); + } + +#if !NUNITLITE + /// + /// Adds a pre-constructed test fixture to the suite. + /// + /// The fixture. + public void Add( object fixture ) + { + Test test = TestFixtureBuilder.BuildFrom( fixture ); + if ( test != null ) + Add( test ); + } +#endif + + /// + /// Gets the command to be executed before any of + /// the child tests are run. + /// + /// A TestCommand + public virtual TestCommand GetOneTimeSetUpCommand() + { + if (RunState != RunState.Runnable && RunState != RunState.Explicit) + return new SkipCommand(this); + + TestCommand command = new OneTimeSetUpCommand(this); + + if (this.FixtureType != null) + { + IApplyToContext[] changes = (IApplyToContext[])this.FixtureType.GetCustomAttributes(typeof(IApplyToContext), true); + if (changes.Length > 0) + command = new ApplyChangesToContextCommand(command, changes); + } + + return command; + } + + /// + /// Gets the command to be executed after all of the + /// child tests are run. + /// + /// A TestCommand + public virtual TestCommand GetOneTimeTearDownCommand() + { + TestCommand command = new OneTimeTearDownCommand(this); + + return command; + } + + #endregion + + #region Properties + + /// + /// Gets this test's child tests + /// + /// The list of child tests +#if CLR_2_0 || CLR_4_0 + public override IList Tests +#else + public override IList Tests +#endif + { + get { return tests; } + } + + /// + /// Gets a count of test cases represented by + /// or contained under this test. + /// + /// + public override int TestCaseCount + { + get + { + int count = 0; + + foreach(Test test in Tests) + { + count += test.TestCaseCount; + } + return count; + } + } + + #endregion + + #region Test Overrides + + /// + /// Overridden to return a TestSuiteResult. + /// + /// A TestResult for this test. + public override TestResult MakeTestResult() + { + return new TestSuiteResult(this); + } + + /// + /// Creates a WorkItem for executing this test. + /// + /// A filter to be used in selecting child tests + /// A new WorkItem + public override WorkItem CreateWorkItem(ITestFilter childFilter) + { + //return RunState == Api.RunState.Runnable || RunState == Api.RunState.Explicit + // ? (WorkItem)new CompositeWorkItem(this, childFilter) + // : (WorkItem)new SimpleWorkItem(this); + return new CompositeWorkItem(this, childFilter); + } + + /// + /// Gets a bool indicating whether the current test + /// has any descendant tests. + /// + public override bool HasChildren + { + get + { + return tests.Count > 0; + } + } + + /// + /// Gets the name used for the top-level element in the + /// XML representation of this test + /// + public override string XmlElementName + { + get { return "test-suite"; } + } + + /// + /// Returns an XmlNode representing the current result after + /// adding it as a child of the supplied parent node. + /// + /// The parent node. + /// If true, descendant results are included + /// + public override XmlNode AddToXml(XmlNode parentNode, bool recursive) + { + XmlNode thisNode = parentNode.AddElement("test-suite"); + thisNode.AddAttribute("type", this.TestType); + + PopulateTestNode(thisNode, recursive); + thisNode.AddAttribute("testcasecount", this.TestCaseCount.ToString()); + + + if (recursive) + foreach (Test test in this.Tests) + test.AddToXml(thisNode, recursive); + + return thisNode; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TextMessageWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TextMessageWriter.cs new file mode 100644 index 00000000000..2748c633a2d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TextMessageWriter.cs @@ -0,0 +1,489 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; +using System.Globalization; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework.Internal +{ + /// + /// TextMessageWriter writes constraint descriptions and messages + /// in displayable form as a text stream. It tailors the display + /// of individual message components to form the standard message + /// format of NUnit assertion failure messages. + /// + public class TextMessageWriter : MessageWriter + { + #region Message Formats and Constants + private static readonly int DEFAULT_LINE_LENGTH = 78; + + // Prefixes used in all failure messages. All must be the same + // length, which is held in the PrefixLength field. Should not + // contain any tabs or newline characters. + /// + /// Prefix used for the expected value line of a message + /// + public static readonly string Pfx_Expected = " Expected: "; + /// + /// Prefix used for the actual value line of a message + /// + public static readonly string Pfx_Actual = " But was: "; + /// + /// Length of a message prefix + /// + public static readonly int PrefixLength = Pfx_Expected.Length; + + private static readonly string Fmt_Connector = " {0} "; + private static readonly string Fmt_Predicate = "{0} "; + //private static readonly string Fmt_Label = "{0}"; + private static readonly string Fmt_Modifier = ", {0}"; + + private static readonly string Fmt_Null = "null"; + private static readonly string Fmt_EmptyString = ""; + private static readonly string Fmt_EmptyCollection = ""; + + private static readonly string Fmt_String = "\"{0}\""; + private static readonly string Fmt_Char = "'{0}'"; + private static readonly string Fmt_DateTime = "yyyy-MM-dd HH:mm:ss.fff"; + private static readonly string Fmt_ValueType = "{0}"; + private static readonly string Fmt_Default = "<{0}>"; + #endregion + + private int maxLineLength = DEFAULT_LINE_LENGTH; + + #region Constructors + /// + /// Construct a TextMessageWriter + /// + public TextMessageWriter() { } + + /// + /// Construct a TextMessageWriter, specifying a user message + /// and optional formatting arguments. + /// + /// + /// + public TextMessageWriter(string userMessage, params object[] args) + { + if ( userMessage != null && userMessage != string.Empty) + this.WriteMessageLine(userMessage, args); + } + #endregion + + #region Properties + /// + /// Gets or sets the maximum line length for this writer + /// + public override int MaxLineLength + { + get { return maxLineLength; } + set { maxLineLength = value; } + } + #endregion + + #region Public Methods - High Level + /// + /// Method to write single line message with optional args, usually + /// written to precede the general failure message, at a givel + /// indentation level. + /// + /// The indentation level of the message + /// The message to be written + /// Any arguments used in formatting the message + public override void WriteMessageLine(int level, string message, params object[] args) + { + if (message != null) + { + while (level-- >= 0) Write(" "); + + if (args != null && args.Length > 0) + message = string.Format(message, args); + + WriteLine(message); + } + } + + /// + /// Display Expected and Actual lines for a constraint. This + /// is called by MessageWriter's default implementation of + /// WriteMessageTo and provides the generic two-line display. + /// + /// The constraint that failed + public override void DisplayDifferences(Constraint constraint) + { + WriteExpectedLine(constraint); + WriteActualLine(constraint); + } + + /// + /// Display Expected and Actual lines for given values. This + /// method may be called by constraints that need more control over + /// the display of actual and expected values than is provided + /// by the default implementation. + /// + /// The expected value + /// The actual value causing the failure + public override void DisplayDifferences(object expected, object actual) + { + WriteExpectedLine(expected); + WriteActualLine(actual); + } + + /// + /// Display Expected and Actual lines for given values, including + /// a tolerance value on the expected line. + /// + /// The expected value + /// The actual value causing the failure + /// The tolerance within which the test was made + public override void DisplayDifferences(object expected, object actual, Tolerance tolerance) + { + WriteExpectedLine(expected, tolerance); + WriteActualLine(actual); + } + + /// + /// Display the expected and actual string values on separate lines. + /// If the mismatch parameter is >=0, an additional line is displayed + /// line containing a caret that points to the mismatch point. + /// + /// The expected string value + /// The actual string value + /// The point at which the strings don't match or -1 + /// If true, case is ignored in string comparisons + /// If true, clip the strings to fit the max line length + public override void DisplayStringDifferences(string expected, string actual, int mismatch, bool ignoreCase, bool clipping) + { + // Maximum string we can display without truncating + int maxDisplayLength = MaxLineLength + - PrefixLength // Allow for prefix + - 2; // 2 quotation marks + + if ( clipping ) + MsgUtils.ClipExpectedAndActual(ref expected, ref actual, maxDisplayLength, mismatch); + + expected = MsgUtils.EscapeControlChars(expected); + actual = MsgUtils.EscapeControlChars(actual); + + // The mismatch position may have changed due to clipping or white space conversion + mismatch = MsgUtils.FindMismatchPosition(expected, actual, 0, ignoreCase); + + Write( Pfx_Expected ); + WriteExpectedValue( expected ); + if ( ignoreCase ) + WriteModifier( "ignoring case" ); + WriteLine(); + WriteActualLine( actual ); + //DisplayDifferences(expected, actual); + if (mismatch >= 0) + WriteCaretLine(mismatch); + } + #endregion + + #region Public Methods - Low Level + /// + /// Writes the text for a connector. + /// + /// The connector. + public override void WriteConnector(string connector) + { + Write(Fmt_Connector, connector); + } + + /// + /// Writes the text for a predicate. + /// + /// The predicate. + public override void WritePredicate(string predicate) + { + Write(Fmt_Predicate, predicate); + } + + //public override void WriteLabel(string label) + //{ + // Write(Fmt_Label, label); + //} + + /// + /// Write the text for a modifier. + /// + /// The modifier. + public override void WriteModifier(string modifier) + { + Write(Fmt_Modifier, modifier); + } + + + /// + /// Writes the text for an expected value. + /// + /// The expected value. + public override void WriteExpectedValue(object expected) + { + WriteValue(expected); + } + + /// + /// Writes the text for an actual value. + /// + /// The actual value. + public override void WriteActualValue(object actual) + { + WriteValue(actual); + } + + /// + /// Writes the text for a generalized value. + /// + /// The value. + public override void WriteValue(object val) + { + if (val == null) + Write(Fmt_Null); + else if (val.GetType().IsArray) + WriteArray((Array)val); + else if (val is string) + WriteString((string)val); + else if (val is IEnumerable) + WriteCollectionElements((IEnumerable)val, 0, 10); + else if (val is char) + WriteChar((char)val); + else if (val is double) + WriteDouble((double)val); + else if (val is float) + WriteFloat((float)val); + else if (val is decimal) + WriteDecimal((decimal)val); + else if (val is DateTime) + WriteDateTime((DateTime)val); + else if (val.GetType().IsValueType) + Write(Fmt_ValueType, val); + else + Write(Fmt_Default, val); + } + + /// + /// Writes the text for a collection value, + /// starting at a particular point, to a max length + /// + /// The collection containing elements to write. + /// The starting point of the elements to write + /// The maximum number of elements to write + public override void WriteCollectionElements(IEnumerable collection, int start, int max) + { + int count = 0; + int index = 0; + + foreach (object obj in collection) + { + if ( index++ >= start) + { + if (++count > max) + break; + Write(count == 1 ? "< " : ", "); + WriteValue(obj); + } + } + + if (count == 0) + { + Write(Fmt_EmptyCollection); + return; + } + + if (count > max) + Write("..."); + + Write(" >"); + } + + private void WriteArray(Array array) + { + if ( array.Length == 0 ) + { + Write( Fmt_EmptyCollection ); + return; + } + + int rank = array.Rank; + int[] products = new int[rank]; + + for (int product = 1, r = rank; --r >= 0; ) + products[r] = product *= array.GetLength(r); + + int count = 0; + foreach (object obj in array) + { + if (count > 0) + Write(", "); + + bool startSegment = false; + for (int r = 0; r < rank; r++) + { + startSegment = startSegment || count % products[r] == 0; + if (startSegment) Write("< "); + } + + WriteValue(obj); + + ++count; + + bool nextSegment = false; + for (int r = 0; r < rank; r++) + { + nextSegment = nextSegment || count % products[r] == 0; + if (nextSegment) Write(" >"); + } + } + } + + private void WriteString(string s) + { + if (s == string.Empty) + Write(Fmt_EmptyString); + else + Write(Fmt_String, s); + } + + private void WriteChar(char c) + { + Write(Fmt_Char, c); + } + + private void WriteDouble(double d) + { + + if (double.IsNaN(d) || double.IsInfinity(d)) + Write(d); + else + { + string s = d.ToString("G17", CultureInfo.InvariantCulture); + + if (s.IndexOf('.') > 0) + Write(s + "d"); + else + Write(s + ".0d"); + } + } + + private void WriteFloat(float f) + { + if (float.IsNaN(f) || float.IsInfinity(f)) + Write(f); + else + { + string s = f.ToString("G9", CultureInfo.InvariantCulture); + + if (s.IndexOf('.') > 0) + Write(s + "f"); + else + Write(s + ".0f"); + } + } + + private void WriteDecimal(Decimal d) + { + Write(d.ToString("G29", CultureInfo.InvariantCulture) + "m"); + } + + private void WriteDateTime(DateTime dt) + { + Write(dt.ToString(Fmt_DateTime, CultureInfo.InvariantCulture)); + } + #endregion + + #region Helper Methods + /// + /// Write the generic 'Expected' line for a constraint + /// + /// The constraint that failed + private void WriteExpectedLine(Constraint constraint) + { + Write(Pfx_Expected); + constraint.WriteDescriptionTo(this); + WriteLine(); + } + + /// + /// Write the generic 'Expected' line for a given value + /// + /// The expected value + private void WriteExpectedLine(object expected) + { + WriteExpectedLine(expected, null); + } + + /// + /// Write the generic 'Expected' line for a given value + /// and tolerance. + /// + /// The expected value + /// The tolerance within which the test was made + private void WriteExpectedLine(object expected, Tolerance tolerance) + { + Write(Pfx_Expected); + WriteExpectedValue(expected); + + if (tolerance != null && !tolerance.IsEmpty) + { + WriteConnector("+/-"); + WriteExpectedValue(tolerance.Value); + if (tolerance.Mode != ToleranceMode.Linear) + Write(" {0}", tolerance.Mode); + } + + WriteLine(); + } + + /// + /// Write the generic 'Actual' line for a constraint + /// + /// The constraint for which the actual value is to be written + private void WriteActualLine(Constraint constraint) + { + Write(Pfx_Actual); + constraint.WriteActualValueTo(this); + WriteLine(); + } + + /// + /// Write the generic 'Actual' line for a given value + /// + /// The actual value causing a failure + private void WriteActualLine(object actual) + { + Write(Pfx_Actual); + WriteActualValue(actual); + WriteLine(); + } + + private void WriteCaretLine(int mismatch) + { + // We subtract 2 for the initial 2 blanks and add back 1 for the initial quote + WriteLine(" {0}^", new string('-', PrefixLength + mismatch - 2 + 1)); + } + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ThreadUtility.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ThreadUtility.cs new file mode 100644 index 00000000000..df645e48797 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/ThreadUtility.cs @@ -0,0 +1,74 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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. +// *********************************************************************** + +#if (CLR_2_0 || CLR_4_0) && !NETCF && !SILVERLIGHT +using System; +using System.Threading; + +namespace NUnit.Framework.Internal +{ + /// + /// The ThreadUtility class encapsulates several static methods + /// useful when working with threads. + /// + public class ThreadUtility + { + /// + /// Do our best to Kill a thread + /// + /// The thread to kill + public static void Kill(Thread thread) + { + Kill(thread, null); + } + + /// + /// Do our best to kill a thread, passing state info + /// + /// The thread to kill + /// Info for the ThreadAbortException handler + public static void Kill(Thread thread, object stateInfo) + { + try + { + if (stateInfo == null) + thread.Abort(); + else + thread.Abort(stateInfo); + } + catch (ThreadStateException) + { + // Although obsolete, this use of Resume() takes care of + // the odd case where a ThreadStateException is received + // so we continue to use it. + thread.Resume(); + } + + if ( (thread.ThreadState & ThreadState.WaitSleepJoin) != 0 ) + thread.Interrupt(); + } + + private ThreadUtility() { } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TypeHelper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TypeHelper.cs new file mode 100644 index 00000000000..fb184471346 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/TypeHelper.cs @@ -0,0 +1,340 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Reflection; +using System.Text; + +namespace NUnit.Framework.Internal +{ + /// + /// TypeHelper provides static methods that operate on Types. + /// + public class TypeHelper + { + /// + /// Gets the display name for a Type as used by NUnit. + /// + /// The Type for which a display name is needed. + /// The display name for the Type + public static string GetDisplayName(Type type) + { +#if CLR_2_0 || CLR_4_0 + if (type.IsGenericParameter) + return type.Name; + + if (type.IsGenericType) + { + string name = type.FullName; + int index = name.IndexOf('['); + if (index >= 0) name = name.Substring(0, index); + + index = name.LastIndexOf('.'); + if (index >= 0) name = name.Substring(index+1); + + index = name.IndexOf('`'); + if (index >= 0) name = name.Substring(0, index); + + StringBuilder sb = new StringBuilder(name); + + sb.Append("<"); + int cnt = 0; + foreach (Type t in type.GetGenericArguments()) + { + if (cnt++ > 0) sb.Append(","); + sb.Append(GetDisplayName(t)); + } + sb.Append(">"); + + return sb.ToString(); + } +#endif + + int lastdot = type.FullName.LastIndexOf('.'); + return lastdot >= 0 + ? type.FullName.Substring(lastdot+1) + : type.FullName; + } + + /// + /// Gets the display name for a Type as used by NUnit. + /// + /// The Type for which a display name is needed. + /// The arglist provided. + /// The display name for the Type + public static string GetDisplayName(Type type, object[] arglist) + { + string baseName = GetDisplayName(type); + if (arglist == null || arglist.Length == 0) + return baseName; + + StringBuilder sb = new StringBuilder( baseName ); + + sb.Append("("); + for (int i = 0; i < arglist.Length; i++) + { + if (i > 0) sb.Append(","); + + object arg = arglist[i]; + string display = arg == null ? "null" : arg.ToString(); + + if (arg is double || arg is float) + { + if (display.IndexOf('.') == -1) + display += ".0"; + display += arg is double ? "d" : "f"; + } + else if (arg is decimal) display += "m"; + else if (arg is long) display += "L"; + else if (arg is ulong) display += "UL"; + else if (arg is string) display = "\"" + display + "\""; + + sb.Append(display); + } + sb.Append(")"); + + return sb.ToString(); + } + + /// + /// Returns the best fit for a common type to be used in + /// matching actual arguments to a methods Type parameters. + /// + /// The first type. + /// The second type. + /// Either type1 or type2, depending on which is more general. + public static Type BestCommonType(Type type1, Type type2) + { + if (type1 == type2) return type1; + if (type1 == null) return type2; + if (type2 == null) return type1; + + if (TypeHelper.IsNumeric(type1) && TypeHelper.IsNumeric(type2)) + { + if (type1 == typeof(double)) return type1; + if (type2 == typeof(double)) return type2; + + if (type1 == typeof(float)) return type1; + if (type2 == typeof(float)) return type2; + + if (type1 == typeof(decimal)) return type1; + if (type2 == typeof(decimal)) return type2; + + if (type1 == typeof(UInt64)) return type1; + if (type2 == typeof(UInt64)) return type2; + + if (type1 == typeof(Int64)) return type1; + if (type2 == typeof(Int64)) return type2; + + if (type1 == typeof(UInt32)) return type1; + if (type2 == typeof(UInt32)) return type2; + + if (type1 == typeof(Int32)) return type1; + if (type2 == typeof(Int32)) return type2; + + if (type1 == typeof(UInt16)) return type1; + if (type2 == typeof(UInt16)) return type2; + + if (type1 == typeof(Int16)) return type1; + if (type2 == typeof(Int16)) return type2; + + if (type1 == typeof(byte)) return type1; + if (type2 == typeof(byte)) return type2; + + if (type1 == typeof(sbyte)) return type1; + if (type2 == typeof(sbyte)) return type2; + } + + return type1; + } + + /// + /// Determines whether the specified type is numeric. + /// + /// The type to be examined. + /// + /// true if the specified type is numeric; otherwise, false. + /// + public static bool IsNumeric(Type type) + { + return type == typeof(double) || + type == typeof(float) || + type == typeof(decimal) || + type == typeof(Int64) || + type == typeof(Int32) || + type == typeof(Int16) || + type == typeof(UInt64) || + type == typeof(UInt32) || + type == typeof(UInt16) || + type == typeof(byte) || + type == typeof(sbyte); + } + + /// + /// Convert an argument list to the required paramter types. + /// Currently, only widening numeric conversions are performed. + /// + /// An array of args to be converted + /// A ParamterInfo[] whose types will be used as targets + public static void ConvertArgumentList(object[] arglist, ParameterInfo[] parameters) + { + System.Diagnostics.Debug.Assert(arglist.Length == parameters.Length); + + for (int i = 0; i < parameters.Length; i++) + { + object arg = arglist[i]; + + if (arg != null && arg is IConvertible) + { + Type argType = arg.GetType(); + Type targetType = parameters[i].ParameterType; + bool convert = false; + + if (argType != targetType && !argType.IsAssignableFrom(targetType)) + { + if (IsNumeric(argType) && IsNumeric(targetType)) + { + if (targetType == typeof(double) || targetType == typeof(float)) + convert = arg is int || arg is long || arg is short || arg is byte || arg is sbyte; + else + if (targetType == typeof(long)) + convert = arg is int || arg is short || arg is byte || arg is sbyte; + else + if (targetType == typeof(short)) + convert = arg is byte || arg is sbyte; + } + } + + if (convert) + arglist[i] = Convert.ChangeType(arg, targetType, + System.Globalization.CultureInfo.InvariantCulture); + } + } + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Creates an instance of a generic Type using the supplied Type arguments + /// + /// The generic type to be specialized. + /// The type args. + /// An instance of the generic type. + public static Type MakeGenericType(Type type, Type[] typeArgs) + { + // TODO: Add error handling + return type.MakeGenericType(typeArgs); + } + + /// + /// Determines whether this instance can deduce type args for a generic type from the supplied arguments. + /// + /// The type to be examined. + /// The arglist. + /// The type args to be used. + /// + /// true if this the provided args give sufficient information to determine the type args to be used; otherwise, false. + /// + public static bool CanDeduceTypeArgsFromArgs(Type type, object[] arglist, ref Type[] typeArgsOut) + { + Type[] typeParameters = type.GetGenericArguments(); + + foreach (ConstructorInfo ctor in type.GetConstructors()) + { + ParameterInfo[] parameters = ctor.GetParameters(); + if (parameters.Length != arglist.Length) + continue; + + Type[] typeArgs = new Type[typeParameters.Length]; + for (int i = 0; i < typeArgs.Length; i++) + { + for (int j = 0; j < arglist.Length; j++) + { + if (parameters[j].ParameterType.Equals(typeParameters[i])) + typeArgs[i] = TypeHelper.BestCommonType( + typeArgs[i], + arglist[j].GetType()); + } + + if (typeArgs[i] == null) + { + typeArgs = null; + break; + } + } + + if (typeArgs != null) + { + typeArgsOut = typeArgs; + return true; + } + } + + return false; + } +#endif + + /// + /// Gets the values for an enumeration, using Enum.GetTypes + /// where available, otherwise through reflection. + /// + /// + /// + public static Array GetEnumValues(Type enumType) + { +#if NETCF || SILVERLIGHT + FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); + + Array enumValues = Array.CreateInstance(enumType, fields.Length); + + for (int index = 0; index < fields.Length; index++) + enumValues.SetValue(fields[index].GetValue(enumType), index); + + return enumValues; +#else + return Enum.GetValues(enumType); +#endif + } + + /// + /// Gets the names defined for an enumeration, using Enum.GetNames + /// where available, otherwise through reflection. + /// + /// + /// + public static string[] GetEnumNames(Type enumType) + { +#if NETCF || SILVERLIGHT + FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); + + string[] names = new string[fields.Length]; + + for (int index = 0; index < fields.Length; index++) + names[index] = fields[index].Name; + + return names; +#else + return Enum.GetNames(enumType); +#endif + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/CompositeWorkItem.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/CompositeWorkItem.cs new file mode 100644 index 00000000000..94194c47855 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/CompositeWorkItem.cs @@ -0,0 +1,220 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Threading; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.WorkItems +{ + /// + /// A CompositeWorkItem represents a test suite and + /// encapsulates the execution of the suite as well + /// as all its child tests. + /// + public class CompositeWorkItem : WorkItem + { + private TestSuite _suite; + private ITestFilter _childFilter; +#if CLR_2_0 || CLR_4_0 + private System.Collections.Generic.Queue _children = new System.Collections.Generic.Queue(); +#else + private System.Collections.Queue _children = new System.Collections.Queue(); +#endif + private TestCommand _setupCommand; + private TestCommand _teardownCommand; + + private CountdownEvent _childTestCountdown; + + /// + /// Construct a CompositeWorkItem for executing a test suite + /// using a filter to select child tests. + /// + /// The TestSuite to be executed + /// A filter used to select child tests + public CompositeWorkItem(TestSuite suite, ITestFilter childFilter) + : base(suite) + { + _suite = suite; + _setupCommand = suite.GetOneTimeSetUpCommand(); + _teardownCommand = suite.GetOneTimeTearDownCommand(); + _childFilter = childFilter; + } + + /// + /// Method that actually performs the work. Overridden + /// in CompositeWorkItem to do setup, run all child + /// items and then do teardown. + /// + protected override void PerformWork() + { + if (_suite.HasChildren) + foreach (Test test in _suite.Tests) + if (_childFilter.Pass(test)) + _children.Enqueue(test.CreateWorkItem(_childFilter)); + + switch (Test.RunState) + { + default: + case RunState.Runnable: + case RunState.Explicit: + // Assume success, since the result will be inconclusive + // if there is no setup method to run or if the + // context initialization fails. + Result.SetResult(ResultState.Success); + + PerformOneTimeSetUp(); + + if (_children.Count > 0) + switch (Result.ResultState.Status) + { + case TestStatus.Passed: + RunChildren(); + return; + // Just return: completion event will take care + // of TestFixtureTearDown when all tests are done. + + case TestStatus.Skipped: + case TestStatus.Inconclusive: + case TestStatus.Failed: + SkipChildren(); + break; + } + + PerformOneTimeTearDown(); + break; + + case RunState.Skipped: + SkipFixture(ResultState.Skipped, GetSkipReason(), null); + break; + + case RunState.Ignored: + SkipFixture(ResultState.Ignored, GetSkipReason(), null); + break; + + case RunState.NotRunnable: + SkipFixture(ResultState.NotRunnable, GetSkipReason(), GetProviderStackTrace()); + break; + } + + // Fall through in case no child tests were run. + // Otherwise, this is done in the completion event. + WorkItemComplete(); + } + + #region Helper Methods + + private void PerformOneTimeSetUp() + { + try + { + _setupCommand.Execute(Context); + + // SetUp may have changed some things + Context.UpdateContext(); + } + catch (Exception ex) + { + if (ex is NUnitException || ex is System.Reflection.TargetInvocationException) + ex = ex.InnerException; + + Result.RecordException(ex); + } + } + + private void RunChildren() + { + _childTestCountdown = new CountdownEvent(_children.Count); + + while (_children.Count > 0) + { + WorkItem child = (WorkItem)_children.Dequeue(); + child.Completed += new EventHandler(OnChildCompleted); + child.Execute(this.Context); + } + } + + private void SkipFixture(ResultState resultState, string message, string stackTrace) + { + Result.SetResult(resultState, message, stackTrace); + SkipChildren(); + } + + private void SkipChildren() + { + while (_children.Count > 0) + { + WorkItem child = (WorkItem)_children.Dequeue(); + Test test = child.Test; + TestResult result = test.MakeTestResult(); + if (Result.ResultState.Status == TestStatus.Failed) + result.SetResult(ResultState.Failure, "TestFixtureSetUp Failed"); + else + result.SetResult(Result.ResultState, Result.Message); + Result.AddResult(result); + } + } + + private void PerformOneTimeTearDown() + { + TestExecutionContext.SetCurrentContext(Context); + _teardownCommand.Execute(Context); + } + + + private string GetSkipReason() + { + return (string)Test.Properties.Get(PropertyNames.SkipReason); + } + + private string GetProviderStackTrace() + { + return (string)Test.Properties.Get(PropertyNames.ProviderStackTrace); + } + + private object _completionLock = new object(); + + private void OnChildCompleted(object sender, EventArgs e) + { + lock (_completionLock) + { + WorkItem childTask = sender as WorkItem; + if (childTask != null) + { + childTask.Completed -= new EventHandler(OnChildCompleted); + Result.AddResult(childTask.Result); + _childTestCountdown.Signal(); + + if (_childTestCountdown.CurrentCount == 0) + { + PerformOneTimeTearDown(); + WorkItemComplete(); + } + } + } + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/CountdownEvent.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/CountdownEvent.cs new file mode 100644 index 00000000000..ae1b3a301ed --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/CountdownEvent.cs @@ -0,0 +1,87 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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. +// *********************************************************************** + +#if !CLR_4_0 || SILVERLIGHT +using System.Threading; + +namespace NUnit.Framework.Internal.WorkItems +{ + /// + /// A simplified implementation of .NET 4 CountdownEvent + /// for use in earlier versions of .NET. Only the methods + /// used by NUnit are implemented. + /// + public class CountdownEvent + { + int _initialCount; + int _remainingCount; + object _lock = new object(); + ManualResetEvent _event = new ManualResetEvent(false); + + /// + /// Construct a CountdownEvent + /// + /// The initial count + public CountdownEvent(int initialCount) + { + _initialCount = _remainingCount = initialCount; + } + + /// + /// Gets the initial count established for the CountdownEvent + /// + public int InitialCount + { + get { return _initialCount; } + } + + /// + /// Gets the current count remaining for the CountdownEvent + /// + public int CurrentCount + { + get { return _remainingCount; } + } + + /// + /// Decrement the count by one + /// + public void Signal() + { + lock (_lock) + { + if (--_remainingCount == 0) + _event.Set(); + } + } + + /// + /// Block the thread until the count reaches zero + /// + public void Wait() + { + _event.WaitOne(); + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/SimpleWorkItem.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/SimpleWorkItem.cs new file mode 100644 index 00000000000..075f4a4f4de --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/SimpleWorkItem.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Threading; +using NUnit.Framework.Internal.Commands; + +namespace NUnit.Framework.Internal.WorkItems +{ + /// + /// A SimpleWorkItem represents a single test case and is + /// marked as completed immediately upon execution. This + /// class is also used for skipped or ignored test suites. + /// + public class SimpleWorkItem : WorkItem + { + private TestCommand _command; + + /// + /// Construct a simple work item for a test. + /// + /// The test to be executed + public SimpleWorkItem(TestMethod test) : base(test) + { + _command = test.MakeTestCommand(); + } + + /// + /// Construct a simple work item for a test command. + /// + /// The command to be executed + public SimpleWorkItem(TestCommand command) : base(command.Test) + { + _command = command; + } + + /// + /// Method that performs actually performs the work. + /// + protected override void PerformWork() + { + try + { + testResult = _command.Execute(Context); + } + finally + { + WorkItemComplete(); + } + } + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/WorkItem.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/WorkItem.cs new file mode 100644 index 00000000000..331f83e5d7c --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/WorkItem.cs @@ -0,0 +1,235 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.Diagnostics; +using System.Threading; +using NUnit.Framework.Api; + +namespace NUnit.Framework.Internal.WorkItems +{ + /// + /// A WorkItem may be an individual test case, a fixture or + /// a higher level grouping of tests. All WorkItems inherit + /// from the abstract WorkItem class, which uses the template + /// pattern to allow derived classes to perform work in + /// whatever way is needed. + /// + public abstract class WorkItem + { + // The current state of the WorkItem + private WorkItemState _state; + + // The test this WorkItem represents + private Test _test; + + /// + /// The result of running the test + /// + protected TestResult testResult; + + // The execution context used by this work item + private TestExecutionContext _context; + + #region Constructor + + /// + /// Construct a WorkItem for a particular test. + /// + /// The test that the WorkItem will run + public WorkItem(Test test) + { + _test = test; + testResult = test.MakeTestResult(); + _state = WorkItemState.Ready; + } + + #endregion + + #region Properties and Events + + /// + /// Event triggered when the item is complete + /// + public event EventHandler Completed; + + /// + /// Gets the current state of the WorkItem + /// + public WorkItemState State + { + get { return _state; } + } + + /// + /// The test being executed by the work item + /// + public Test Test + { + get { return _test; } + } + + /// + /// The execution context + /// + protected TestExecutionContext Context + { + get { return _context; } + } + + /// + /// The test result + /// + public TestResult Result + { + get { return testResult; } + } + + #endregion + + #region Public Methods + + /// + /// Execute the current work item, including any + /// child work items. + /// + public virtual void Execute(TestExecutionContext context) + { + _context = new TestExecutionContext(context); + +#if (CLR_2_0 || CLR_4_0) && !SILVERLIGHT + // Timeout set at a higher level + int timeout = _context.TestCaseTimeout; + + // Timeout set on this test + if (Test.Properties.ContainsKey(PropertyNames.Timeout)) + timeout = (int)Test.Properties.Get(PropertyNames.Timeout); + + if (Test is TestMethod && timeout > 0) + RunTestWithTimeout(timeout); + else + RunTest(); +#else + RunTest(); +#endif + } + +#if (CLR_2_0 || CLR_4_0) && !SILVERLIGHT + private void RunTestWithTimeout(int timeout) + { + Thread thread = new Thread(new ThreadStart(RunTest)); + + thread.Start(); + + if (timeout <= 0) + timeout = Timeout.Infinite; + +#if NETCF + // NETCF doesn't support IsAlive as well as various + // members required by our ThreadUtilitity.Kill + if (!thread.Join(timeout)) + { + thread.Abort(); +#else + thread.Join(timeout); + + if (thread.IsAlive) + { + ThreadUtility.Kill(thread); +#endif + // NOTE: Without the use of Join, there is a race condition here. + // The thread sets the result to Cancelled and our code below sets + // it to Failure. In order for the result to be shown as a failure, + // we need to ensure that the following code executes after the + // thread has terminated. There is a risk here: the test code might + // refuse to terminate. However, it's more important to deal with + // the normal rather than a pathological case. + thread.Join(); + + Result.SetResult(ResultState.Failure, + string.Format("Test exceeded Timeout value of {0}ms", timeout)); + + WorkItemComplete(); + } + } +#endif + + private void RunTest() + { + _context.CurrentTest = this.Test; + _context.CurrentResult = this.Result; + _context.Listener.TestStarted(this.Test); + _context.StartTime = DateTime.Now; + + TestExecutionContext.SetCurrentContext(_context); + +#if (CLR_2_0 || CLR_4_0) && !SILVERLIGHT && !NETCF_2_0 + long startTicks = Stopwatch.GetTimestamp(); +#endif + + try + { + PerformWork(); + } + finally + { +#if (CLR_2_0 || CLR_4_0) && !SILVERLIGHT && !NETCF_2_0 + long tickCount = Stopwatch.GetTimestamp() - startTicks; + double seconds = (double)tickCount / Stopwatch.Frequency; + Result.Duration = TimeSpan.FromSeconds(seconds); +#else + Result.Duration = DateTime.Now - Context.StartTime; +#endif + + Result.AssertCount = _context.AssertCount; + + _context.Listener.TestFinished(Result); + + _context = _context.Restore(); + _context.AssertCount += Result.AssertCount; + } + } + + #endregion + + #region Protected Methods + + /// + /// Method that performs actually performs the work. It should + /// set the State to WorkItemState.Complete when done. + /// + protected abstract void PerformWork(); + + /// + /// Method called by the derived class when all work is complete + /// + protected void WorkItemComplete() + { + _state = WorkItemState.Complete; + if (Completed != null) + Completed(this, EventArgs.Empty); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/WorkItemState.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/WorkItemState.cs new file mode 100644 index 00000000000..ece993a3afb --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Internal/WorkItems/WorkItemState.cs @@ -0,0 +1,46 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework.Internal.WorkItems +{ + /// + /// The current state of a work item + /// + public enum WorkItemState + { + /// + /// Ready to run or continue + /// + Ready, + + /// + /// Waiting for a dependency to complete + /// + Waiting, + + /// + /// Complete + /// + Complete + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Is.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Is.cs new file mode 100644 index 00000000000..55b61603310 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Is.cs @@ -0,0 +1,545 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework +{ + /// + /// Helper class with properties and methods that supply + /// a number of constraints used in Asserts. + /// + public class Is + { + #region Not + + /// + /// Returns a ConstraintExpression that negates any + /// following constraint. + /// + public static ConstraintExpression Not + { + get { return new ConstraintExpression().Not; } + } + + #endregion + + #region All + + /// + /// Returns a ConstraintExpression, which will apply + /// the following constraint to all members of a collection, + /// succeeding if all of them succeed. + /// + public static ConstraintExpression All + { + get { return new ConstraintExpression().All; } + } + + #endregion + + #region Null + + /// + /// Returns a constraint that tests for null + /// + public static NullConstraint Null + { + get { return new NullConstraint(); } + } + + #endregion + + #region True + + /// + /// Returns a constraint that tests for True + /// + public static TrueConstraint True + { + get { return new TrueConstraint(); } + } + + #endregion + + #region False + + /// + /// Returns a constraint that tests for False + /// + public static FalseConstraint False + { + get { return new FalseConstraint(); } + } + + #endregion + + #region Positive + + /// + /// Returns a constraint that tests for a positive value + /// + public static GreaterThanConstraint Positive + { + get { return new GreaterThanConstraint(0); } + } + + #endregion + + #region Negative + + /// + /// Returns a constraint that tests for a negative value + /// + public static LessThanConstraint Negative + { + get { return new LessThanConstraint(0); } + } + + #endregion + + #region NaN + + /// + /// Returns a constraint that tests for NaN + /// + public static NaNConstraint NaN + { + get { return new NaNConstraint(); } + } + + #endregion + + #region Empty + + /// + /// Returns a constraint that tests for empty + /// + public static EmptyConstraint Empty + { + get { return new EmptyConstraint(); } + } + + #endregion + + #region Unique + + /// + /// Returns a constraint that tests whether a collection + /// contains all unique items. + /// + public static UniqueItemsConstraint Unique + { + get { return new UniqueItemsConstraint(); } + } + + #endregion + + #region BinarySerializable + +#if !NETCF && !SILVERLIGHT + /// + /// Returns a constraint that tests whether an object graph is serializable in binary format. + /// + public static BinarySerializableConstraint BinarySerializable + { + get { return new BinarySerializableConstraint(); } + } +#endif + + #endregion + + #region XmlSerializable + +#if !SILVERLIGHT + /// + /// Returns a constraint that tests whether an object graph is serializable in xml format. + /// + public static XmlSerializableConstraint XmlSerializable + { + get { return new XmlSerializableConstraint(); } + } +#endif + + #endregion + + #region EqualTo + + /// + /// Returns a constraint that tests two items for equality + /// + public static EqualConstraint EqualTo(object expected) + { + return new EqualConstraint(expected); + } + + #endregion + + #region SameAs + + /// + /// Returns a constraint that tests that two references are the same object + /// + public static SameAsConstraint SameAs(object expected) + { + return new SameAsConstraint(expected); + } + + #endregion + + #region GreaterThan + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than the suppled argument + /// + public static GreaterThanConstraint GreaterThan(object expected) + { + return new GreaterThanConstraint(expected); + } + + #endregion + + #region GreaterThanOrEqualTo + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than or equal to the suppled argument + /// + public static GreaterThanOrEqualConstraint GreaterThanOrEqualTo(object expected) + { + return new GreaterThanOrEqualConstraint(expected); + } + + /// + /// Returns a constraint that tests whether the + /// actual value is greater than or equal to the suppled argument + /// + public static GreaterThanOrEqualConstraint AtLeast(object expected) + { + return new GreaterThanOrEqualConstraint(expected); + } + + #endregion + + #region LessThan + + /// + /// Returns a constraint that tests whether the + /// actual value is less than the suppled argument + /// + public static LessThanConstraint LessThan(object expected) + { + return new LessThanConstraint(expected); + } + + #endregion + + #region LessThanOrEqualTo + + /// + /// Returns a constraint that tests whether the + /// actual value is less than or equal to the suppled argument + /// + public static LessThanOrEqualConstraint LessThanOrEqualTo(object expected) + { + return new LessThanOrEqualConstraint(expected); + } + + /// + /// Returns a constraint that tests whether the + /// actual value is less than or equal to the suppled argument + /// + public static LessThanOrEqualConstraint AtMost(object expected) + { + return new LessThanOrEqualConstraint(expected); + } + + #endregion + + #region TypeOf + + /// + /// Returns a constraint that tests whether the actual + /// value is of the exact type supplied as an argument. + /// + public static ExactTypeConstraint TypeOf(Type expectedType) + { + return new ExactTypeConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual + /// value is of the exact type supplied as an argument. + /// + public static ExactTypeConstraint TypeOf() + { + return new ExactTypeConstraint(typeof(T)); + } +#endif + + #endregion + + /// + /// Is.InstanceOfType returns a constraint that tests whether + /// the actual value is of the type supplied as an argument + /// or a derived type. + /// + public static Constraint InstanceOfType(Type expectedType) + { + return new InstanceOfTypeConstraint(expectedType); + } + + #region InstanceOf + + /// + /// Returns a constraint that tests whether the actual value + /// is of the type supplied as an argument or a derived type. + /// + public static InstanceOfTypeConstraint InstanceOf(Type expectedType) + { + return new InstanceOfTypeConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is of the type supplied as an argument or a derived type. + /// + public static InstanceOfTypeConstraint InstanceOf() + { + return new InstanceOfTypeConstraint(typeof(T)); + } +#endif + + #endregion + + #region AssignableFrom + + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public static AssignableFromConstraint AssignableFrom(Type expectedType) + { + return new AssignableFromConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public static AssignableFromConstraint AssignableFrom() + { + return new AssignableFromConstraint(typeof(T)); + } +#endif + + #endregion + + #region AssignableTo + + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public static AssignableToConstraint AssignableTo(Type expectedType) + { + return new AssignableToConstraint(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value + /// is assignable from the type supplied as an argument. + /// + public static AssignableToConstraint AssignableTo() + { + return new AssignableToConstraint(typeof(T)); + } +#endif + + #endregion + + #region EquivalentTo + + /// + /// Returns a constraint that tests whether the actual value + /// is a collection containing the same elements as the + /// collection supplied as an argument. + /// + public static CollectionEquivalentConstraint EquivalentTo(IEnumerable expected) + { + return new CollectionEquivalentConstraint(expected); + } + + #endregion + + #region SubsetOf + + /// + /// Returns a constraint that tests whether the actual value + /// is a subset of the collection supplied as an argument. + /// + public static CollectionSubsetConstraint SubsetOf(IEnumerable expected) + { + return new CollectionSubsetConstraint(expected); + } + + #endregion + + #region Ordered + + /// + /// Returns a constraint that tests whether a collection is ordered + /// + public static CollectionOrderedConstraint Ordered + { + get { return new CollectionOrderedConstraint(); } + } + + #endregion + + #region StringContaining + + /// + /// Returns a constraint that succeeds if the actual + /// value contains the substring supplied as an argument. + /// + public static SubstringConstraint StringContaining(string expected) + { + return new SubstringConstraint(expected); + } + + #endregion + + #region StringStarting + + /// + /// Returns a constraint that succeeds if the actual + /// value starts with the substring supplied as an argument. + /// + public static StartsWithConstraint StringStarting(string expected) + { + return new StartsWithConstraint(expected); + } + + #endregion + + #region StringEnding + + /// + /// Returns a constraint that succeeds if the actual + /// value ends with the substring supplied as an argument. + /// + public static EndsWithConstraint StringEnding(string expected) + { + return new EndsWithConstraint(expected); + } + + #endregion + + #region StringMatching + +#if !NETCF + /// + /// Returns a constraint that succeeds if the actual + /// value matches the regular expression supplied as an argument. + /// + public static RegexConstraint StringMatching(string pattern) + { + return new RegexConstraint(pattern); + } +#endif + + #endregion + + #region SamePath + + /// + /// Returns a constraint that tests whether the path provided + /// is the same as an expected path after canonicalization. + /// + public static SamePathConstraint SamePath(string expected) + { + return new SamePathConstraint(expected); + } + + #endregion + + #region SubPath + + /// + /// Returns a constraint that tests whether the path provided + /// is under an expected path after canonicalization. + /// + public static SubPathConstraint SubPath(string expected) + { + return new SubPathConstraint(expected); + } + + #endregion + + #region SamePathOrUnder + + /// + /// Returns a constraint that tests whether the path provided + /// is the same path or under an expected path after canonicalization. + /// + public static SamePathOrUnderConstraint SamePathOrUnder(string expected) + { + return new SamePathOrUnderConstraint(expected); + } + + #endregion + + #region InRange + +#if CLR_2_0 || CLR_4_0 + /// + /// Returns a constraint that tests whether the actual value falls + /// within a specified range. + /// + public static RangeConstraint InRange(T from, T to) where T : IComparable + { + return new RangeConstraint(from, to); + } +#else + /// + /// Returns a constraint that tests whether the actual value falls + /// within a specified range. + /// + public static RangeConstraint InRange(IComparable from, IComparable to) + { + return new RangeConstraint(from, to); + } +#endif + + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Iz.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Iz.cs new file mode 100644 index 00000000000..838b0b538da --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Iz.cs @@ -0,0 +1,35 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// The Iz class is a synonym for Is intended for use in VB, + /// which regards Is as a keyword. + /// + public class Iz : Is + { + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/ListMapper.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/ListMapper.cs new file mode 100644 index 00000000000..845202d6f02 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/ListMapper.cs @@ -0,0 +1,69 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Reflection; + +namespace NUnit.Framework +{ + /// + /// ListMapper is used to transform a collection used as an actual argument + /// producing another collection to be used in the assertion. + /// + public class ListMapper + { + ICollection original; + + /// + /// Construct a ListMapper based on a collection + /// + /// The collection to be transformed + public ListMapper( ICollection original ) + { + this.original = original; + } + + /// + /// Produces a collection containing all the values of a property + /// + /// The collection of property values + /// + public ICollection Property( string name ) + { + ObjectList propList = new ObjectList(); + foreach( object item in original ) + { + PropertyInfo property = item.GetType().GetProperty( name, + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ); + if ( property == null ) + throw new ArgumentException( string.Format( + "{0} does not have a {1} property", item, name ) ); + + propList.Add( property.GetValue( item, null ) ); + } + + return propList; + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/MessageMatch.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/MessageMatch.cs new file mode 100644 index 00000000000..bd300f988b7 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/MessageMatch.cs @@ -0,0 +1,40 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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. +// *********************************************************************** + +namespace NUnit.Framework +{ + /// + /// Enumeration indicating how the expected message parameter is to be used + /// + public enum MessageMatch + { + /// Expect an exact match + Exact, + /// Expect a message containing the parameter string + Contains, + /// Match the regular expression provided as a parameter + Regex, + /// Expect a message that starts with the parameter string + StartsWith + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/ObjectList.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/ObjectList.cs new file mode 100644 index 00000000000..fd7f0b1fe09 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/ObjectList.cs @@ -0,0 +1,52 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit +{ + /// + /// ObjectList represents a collection of objects. It is implemented + /// as a List<object> in .NET 2.0 or higher and as an ArrayList otherwise. + /// ObjectList does not attempt to be a general replacement for either of + /// these classes but only implements what is needed within the framework. + /// +#if CLR_2_0 || CLR_4_0 + public class ObjectList : System.Collections.Generic.List + { + /// + /// Adds a range of values to the collection. + /// + /// The collection. + public void AddRange(System.Collections.ICollection collection) + { + foreach (object item in collection) + Add(item); + } + } +#else + public class ObjectList : System.Collections.ArrayList + { + } +#endif +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/CommandLineOptions.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/CommandLineOptions.cs new file mode 100644 index 00000000000..0f8dcd17b64 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/CommandLineOptions.cs @@ -0,0 +1,459 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Text; +using System.Collections; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#endif +using NUnit.Framework; + +namespace NUnitLite.Runner +{ + /// + /// The CommandLineOptions class parses and holds the values of + /// any options entered at the command line. + /// + public class CommandLineOptions + { + private string optionChars; + private static string NL = NUnit.Env.NewLine; + + private bool wait = false; + private bool noheader = false; + private bool help = false; + private bool full = false; + private bool explore = false; + private bool labelTestsInOutput = false; + + private string exploreFile; + private string resultFile; + private string resultFormat; + private string outFile; + private string includeCategory; + private string excludeCategory; + + private bool error = false; + + private StringList tests = new StringList(); + private StringList invalidOptions = new StringList(); + private StringList parameters = new StringList(); + + private int randomSeed = -1; + + #region Properties + + /// + /// Gets a value indicating whether the 'wait' option was used. + /// + public bool Wait + { + get { return wait; } + } + + /// + /// Gets a value indicating whether the 'nologo' option was used. + /// + public bool NoHeader + { + get { return noheader; } + } + + /// + /// Gets a value indicating whether the 'help' option was used. + /// + public bool ShowHelp + { + get { return help; } + } + + /// + /// Gets a list of all tests specified on the command line + /// + public string[] Tests + { + get { return (string[])tests.ToArray(); } + } + + /// + /// Gets a value indicating whether a full report should be displayed + /// + public bool Full + { + get { return full; } + } + + /// + /// Gets a value indicating whether tests should be listed + /// rather than run. + /// + public bool Explore + { + get { return explore; } + } + + /// + /// Gets the name of the file to be used for listing tests + /// + public string ExploreFile + { + get { return exploreFile; } + } + + /// + /// Gets the name of the file to be used for test results + /// + public string ResultFile + { + get { return resultFile; } + } + + /// + /// Gets the format to be used for test results + /// + public string ResultFormat + { + get { return resultFormat; } + } + + /// + /// Gets the full path of the file to be used for output + /// + public string OutFile + { + get + { + return outFile; + } + } + + /// + /// Gets the list of categories to include + /// + public string Include + { + get + { + return includeCategory; + } + } + + /// + /// Gets the list of categories to exclude + /// + public string Exclude + { + get + { + return excludeCategory; + } + } + + /// + /// Gets a flag indicating whether each test should + /// be labeled in the output. + /// + public bool LabelTestsInOutput + { + get { return labelTestsInOutput; } + } + + private string ExpandToFullPath(string path) + { + if (path == null) return null; + +#if NETCF + return Path.Combine(NUnit.Env.DocumentFolder, path); +#else + return Path.GetFullPath(path); +#endif + } + + /// + /// Gets the test count + /// + public int TestCount + { + get { return tests.Count; } + } + + /// + /// Gets the seed to be used for generating random values + /// + public int InitialSeed + { + get + { + if (randomSeed < 0) + randomSeed = new Random().Next(); + + return randomSeed; + } + } + + #endregion + + /// + /// Construct a CommandLineOptions object using default option chars + /// + public CommandLineOptions() + { + this.optionChars = System.IO.Path.DirectorySeparatorChar == '/' ? "-" : "/-"; + } + + /// + /// Construct a CommandLineOptions object using specified option chars + /// + /// + public CommandLineOptions(string optionChars) + { + this.optionChars = optionChars; + } + + /// + /// Parse command arguments and initialize option settings accordingly + /// + /// The argument list + public void Parse(params string[] args) + { + foreach( string arg in args ) + { + if (optionChars.IndexOf(arg[0]) >= 0 ) + ProcessOption(arg); + else + ProcessParameter(arg); + } + } + + /// + /// Gets the parameters provided on the commandline + /// + public string[] Parameters + { + get { return (string[])parameters.ToArray(); } + } + + private void ProcessOption(string option) + { + string opt = option; + int pos = opt.IndexOfAny( new char[] { ':', '=' } ); + string val = string.Empty; + + if (pos >= 0) + { + val = opt.Substring(pos + 1); + opt = opt.Substring(0, pos); + } + + switch (opt.Substring(1)) + { + case "wait": + wait = true; + break; + case "noheader": + case "noh": + noheader = true; + break; + case "help": + case "h": + help = true; + break; + case "test": + tests.Add(val); + break; + case "full": + full = true; + break; + case "explore": + explore = true; + if (val == null || val.Length == 0) + val = "tests.xml"; + try + { + exploreFile = ExpandToFullPath(val); + } + catch + { + InvalidOption(option); + } + break; + case "result": + if (val == null || val.Length == 0) + val = "TestResult.xml"; + try + { + resultFile = ExpandToFullPath(val); + } + catch + { + InvalidOption(option); + } + break; + case "format": + resultFormat = val; + if (resultFormat != "nunit3" && resultFormat != "nunit2") + InvalidOption(option); + break; + case "out": + try + { + outFile = ExpandToFullPath(val); + } + catch + { + InvalidOption(option); + } + break; + case "labels": + labelTestsInOutput = true; + break; + case "include": + includeCategory = val; + break; + case "exclude": + excludeCategory = val; + break; + case "seed": + try + { + randomSeed = int.Parse(val); + } + catch + { + InvalidOption(option); + } + break; + default: + InvalidOption(option); + break; + } + } + + private void InvalidOption(string option) + { + error = true; + invalidOptions.Add(option); + } + + private void ProcessParameter(string param) + { + parameters.Add(param); + } + + /// + /// Gets a value indicating whether there was an error in parsing the options. + /// + /// true if error; otherwise, false. + public bool Error + { + get { return error; } + } + + /// + /// Gets the error message. + /// + /// The error message. + public string ErrorMessage + { + get + { + StringBuilder sb = new StringBuilder(); + foreach (string opt in invalidOptions) + sb.Append( "Invalid option: " + opt + NL ); + return sb.ToString(); + } + } + + /// + /// Gets the help text. + /// + /// The help text. + public string HelpText + { + get + { + StringBuilder sb = new StringBuilder(); + +#if PocketPC || WindowsCE || NETCF || SILVERLIGHT + string name = "NUnitLite"; +#else + string name = System.Reflection.Assembly.GetEntryAssembly().GetName().Name; +#endif + + sb.Append("Usage: " + name + " [assemblies] [options]" + NL + NL); + sb.Append("Runs a set of NUnitLite tests from the console." + NL + NL); + sb.Append("You may specify one or more test assemblies by name, without a path or" + NL); + sb.Append("extension. They must be in the same in the same directory as the exe" + NL); + sb.Append("or on the probing path. If no assemblies are provided, tests in the" + NL); + sb.Append("executing assembly itself are run." + NL + NL); + sb.Append("Options:" + NL); + sb.Append(" -test:testname Provides the name of a test to run. This option may be" + NL); + sb.Append(" repeated. If no test names are given, all tests are run." + NL + NL); + sb.Append(" -out:FILE File to which output is redirected. If this option is not" + NL); + sb.Append(" used, output is to the Console, which means it is lost" + NL); + sb.Append(" on devices without a Console." + NL + NL); + sb.Append(" -full Prints full report of all test results." + NL + NL); + sb.Append(" -result:FILE File to which the xml test result is written." + NL + NL); + sb.Append(" -format:FORMAT Format in which the result is to be written. FORMAT must be" + NL); + sb.Append(" either nunit3 or nunit2. The default is nunit3." + NL + NL); + sb.Append(" -explore:FILE If provided, this option indicates that the tests" + NL); + sb.Append(" should be listed rather than executed. They are listed" + NL); + sb.Append(" to the specified file in XML format." + NL); + sb.Append(" -help,-h Displays this help" + NL + NL); + sb.Append(" -noheader,-noh Suppresses display of the initial message" + NL + NL); + sb.Append(" -labels Displays the name of each test when it starts" + NL + NL); + sb.Append(" -seed:SEED If provided, this option allows you to set the seed for the" + NL + NL); + sb.Append(" random generator in the test context." + NL + NL); + sb.Append(" -include:CAT List of categories to include" + NL + NL); + sb.Append(" -exclude:CAT List of categories to exclude" + NL + NL); + sb.Append(" -wait Waits for a key press before exiting" + NL + NL); + + sb.Append("Notes:" + NL); + sb.Append(" * File names may be listed by themselves, with a relative path or " + NL); + sb.Append(" using an absolute path. Any relative path is based on the current " + NL); + sb.Append(" directory or on the Documents folder if running on a under the " +NL); + sb.Append(" compact framework." + NL + NL); + if (System.IO.Path.DirectorySeparatorChar != '/') + sb.Append(" * On Windows, options may be prefixed by a '/' character if desired" + NL + NL); + sb.Append(" * Options that take values may use an equal sign or a colon" + NL); + sb.Append(" to separate the option from its value." + NL + NL); + + return sb.ToString(); + } + } + +#if CLR_2_0 || CLR_4_0 + class StringList : List { } +#else + class StringList : ArrayList + { + public new string[] ToArray() + { + return (string[])ToArray(typeof(string)); + } + } +#endif + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ConsoleWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ConsoleWriter.cs new file mode 100644 index 00000000000..8d79cd537e5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ConsoleWriter.cs @@ -0,0 +1,113 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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; + +namespace NUnitLite.Runner +{ + /// + /// Provide an alternative to Console.Out for + /// version 1.0 of the compact framework. + /// + public class ConsoleWriter : TextWriter + { + private static TextWriter writer; + + /// + /// Gets the underlying TextWriter, creating it if it does not already exist. + /// + /// The underlying TextWriter. + public static TextWriter Out + { + get + { + if ( writer == null ) + writer = new ConsoleWriter(); + + return writer; + } + } + + /// + /// Writes a character to the text stream. + /// + /// The character to write to the text stream. + /// + /// The is closed. + /// + /// + /// An I/O error occurs. + /// + public override void Write(char value) + { + Console.Write(value); + } + + /// + /// Writes a string to the text stream. + /// + /// The string to write. + /// + /// The is closed. + /// + /// + /// An I/O error occurs. + /// + public override void Write(string value) + { + Console.Write(value); + } + + /// + /// Writes a string followed by a line terminator to the text stream. + /// + /// The string to write. If is null, only the line termination characters are written. + /// + /// The is closed. + /// + /// + /// An I/O error occurs. + /// + public override void WriteLine(string value) + { + Console.WriteLine(value); + } + + /// + /// When overridden in a derived class, returns the in which the output is written. + /// + /// + /// + /// The Encoding in which the output is written. + /// + public override System.Text.Encoding Encoding + { +#if SILVERLIGHT + get { return System.Text.Encoding.UTF8; } +#else + get { return System.Text.Encoding.Default; } +#endif + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/DebugWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/DebugWriter.cs new file mode 100644 index 00000000000..59b8a454640 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/DebugWriter.cs @@ -0,0 +1,113 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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. +// *********************************************************************** + +#if !SILVERLIGHT +using System; +using System.Diagnostics; +using System.IO; + +namespace NUnitLite.Runner +{ + /// + /// DebugWriter is a TextWriter that sends it's + /// output to Debug. We don't use Trace because + /// writing to it is not supported in CF. + /// + public class DebugWriter : TextWriter + { + private static TextWriter writer; + + /// + /// Singleon instance of a DebugWriter. + /// + /// The DebugWriter singleton. + public static TextWriter Out + { + get + { + if (writer == null) + writer = new DebugWriter(); + + return writer; + } + } + + /// + /// Writes a character to the text stream. + /// + /// The character to write to the text stream. + /// + /// The is closed. + /// + /// + /// An I/O error occurs. + /// + public override void Write(char value) + { + Debug.Write(value); + } + + /// + /// Writes a string to the text stream. + /// + /// The string to write. + /// + /// The is closed. + /// + /// + /// An I/O error occurs. + /// + public override void Write(string value) + { + Debug.Write(value); + } + + /// + /// Writes a string followed by a line terminator to the text stream. + /// + /// The string to write. If is null, only the line termination characters are written. + /// + /// The is closed. + /// + /// + /// An I/O error occurs. + /// + public override void WriteLine(string value) + { + Debug.WriteLine(value); + } + + /// + /// When overridden in a derived class, returns the in which the output is written. + /// + /// + /// + /// The Encoding in which the output is written. + /// + public override System.Text.Encoding Encoding + { + get { return System.Text.Encoding.Default; } + } + } +} +#endif diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/NUnit2XmlOutputWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/NUnit2XmlOutputWriter.cs new file mode 100644 index 00000000000..d1f4eb1cd6d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/NUnit2XmlOutputWriter.cs @@ -0,0 +1,381 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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.Globalization; +using System.Reflection; +using System.Xml; +using System.IO; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +#if CLR_2_0 || CLR_4_0 +using System.Collections.Generic; +#else +using System.Collections.Specialized; +#endif + +namespace NUnitLite.Runner +{ + /// + /// NUnit2XmlOutputWriter is able to create an xml file representing + /// the result of a test run in NUnit 2.x format. + /// + public class NUnit2XmlOutputWriter : OutputWriter + { + private XmlWriter xmlWriter; + private DateTime startTime; + +#if CLR_2_0 || CLR_4_0 + private static Dictionary resultStates = new Dictionary(); +#else + private static StringDictionary resultStates = new StringDictionary(); +#endif + + static NUnit2XmlOutputWriter() + { + resultStates["Passed"] = "Success"; + resultStates["Failed"] = "Failure"; + resultStates["Failed:Error"] = "Error"; + resultStates["Failed:Cancelled"] = "Cancelled"; + resultStates["Inconclusive"] = "Inconclusive"; + resultStates["Skipped"] = "Skipped"; + resultStates["Skipped:Ignored"] = "Ignored"; + resultStates["Skipped:Invalid"] = "NotRunnable"; + } + + public NUnit2XmlOutputWriter(DateTime startTime) + { + this.startTime = startTime; + } + + /// + /// Writes the result of a test run to a specified TextWriter. + /// + /// The test result for the run + /// The TextWriter to which the xml will be written + public override void WriteResultFile(ITestResult result, TextWriter writer) + { + // NOTE: Under .NET 1.1, XmlTextWriter does not implement IDisposable, + // but does implement Close(). Hence we cannot use a 'using' clause. + //using (XmlTextWriter xmlWriter = new XmlTextWriter(writer)) +#if SILVERLIGHT + XmlWriter xmlWriter = XmlWriter.Create(writer); +#else + XmlTextWriter xmlWriter = new XmlTextWriter(writer); + xmlWriter.Formatting = Formatting.Indented; +#endif + + try + { + WriteXmlOutput(result, xmlWriter); + } + finally + { + writer.Close(); + } + } + + private void WriteXmlOutput(ITestResult result, XmlWriter xmlWriter) + { + this.xmlWriter = xmlWriter; + + InitializeXmlFile(result); + WriteResultElement(result); + TerminateXmlFile(); + } + + private void InitializeXmlFile(ITestResult result) + { + ResultSummary summaryResults = new ResultSummary(result); + + xmlWriter.WriteStartDocument(false); + xmlWriter.WriteComment("This file represents the results of running a test suite"); + + xmlWriter.WriteStartElement("test-results"); + + xmlWriter.WriteAttributeString("name", result.FullName); + xmlWriter.WriteAttributeString("total", summaryResults.TestCount.ToString()); + xmlWriter.WriteAttributeString("errors", summaryResults.ErrorCount.ToString()); + xmlWriter.WriteAttributeString("failures", summaryResults.FailureCount.ToString()); + xmlWriter.WriteAttributeString("not-run", summaryResults.NotRunCount.ToString()); + xmlWriter.WriteAttributeString("inconclusive", summaryResults.InconclusiveCount.ToString()); + xmlWriter.WriteAttributeString("ignored", summaryResults.IgnoreCount.ToString()); + xmlWriter.WriteAttributeString("skipped", summaryResults.SkipCount.ToString()); + xmlWriter.WriteAttributeString("invalid", summaryResults.InvalidCount.ToString()); + + xmlWriter.WriteAttributeString("date", XmlConvert.ToString(startTime, "yyyy-MM-dd")); + xmlWriter.WriteAttributeString("time", XmlConvert.ToString(startTime, "HH:mm:ss")); + WriteEnvironment(); + WriteCultureInfo(); + } + + private void WriteCultureInfo() + { + xmlWriter.WriteStartElement("culture-info"); + xmlWriter.WriteAttributeString("current-culture", + CultureInfo.CurrentCulture.ToString()); + xmlWriter.WriteAttributeString("current-uiculture", + CultureInfo.CurrentUICulture.ToString()); + xmlWriter.WriteEndElement(); + } + + private void WriteEnvironment() + { + xmlWriter.WriteStartElement("environment"); + AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(Assembly.GetExecutingAssembly()); + xmlWriter.WriteAttributeString("nunit-version", + assemblyName.Version.ToString()); + xmlWriter.WriteAttributeString("clr-version", + Environment.Version.ToString()); + xmlWriter.WriteAttributeString("os-version", + Environment.OSVersion.ToString()); + xmlWriter.WriteAttributeString("platform", + Environment.OSVersion.Platform.ToString()); +#if !NETCF + xmlWriter.WriteAttributeString("cwd", + Environment.CurrentDirectory); +#if !SILVERLIGHT + xmlWriter.WriteAttributeString("machine-name", + Environment.MachineName); + xmlWriter.WriteAttributeString("user", + Environment.UserName); + xmlWriter.WriteAttributeString("user-domain", + Environment.UserDomainName); +#endif +#endif + xmlWriter.WriteEndElement(); + } + + private void WriteResultElement(ITestResult result) + { + StartTestElement(result); + + WriteCategories(result); + WriteProperties(result); + + switch (result.ResultState.Status) + { + case TestStatus.Skipped: + WriteReasonElement(result.Message); + break; + case TestStatus.Failed: + WriteFailureElement(result.Message, result.StackTrace); + break; + } + + if (result.Test is TestSuite) + WriteChildResults(result); + + xmlWriter.WriteEndElement(); // test element + } + + private void TerminateXmlFile() + { + xmlWriter.WriteEndElement(); // test-results + xmlWriter.WriteEndDocument(); + xmlWriter.Flush(); + xmlWriter.Close(); + } + + + #region Element Creation Helpers + + private void StartTestElement(ITestResult result) + { + ITest test = result.Test; + TestSuite suite = test as TestSuite; + + if (suite != null) + { + xmlWriter.WriteStartElement("test-suite"); + xmlWriter.WriteAttributeString("type", suite.TestType); + xmlWriter.WriteAttributeString("name", suite.TestType == "Assembly" + ? result.Test.FullName + : result.Test.Name); + } + else + { + xmlWriter.WriteStartElement("test-case"); + xmlWriter.WriteAttributeString("name", result.Name); + } + + if (test.Properties.ContainsKey(PropertyNames.Description)) + { + string description = (string)test.Properties.Get(PropertyNames.Description); + xmlWriter.WriteAttributeString("description", description); + } + + TestStatus status = result.ResultState.Status; + string translatedResult = resultStates[result.ResultState.ToString()]; + + if (status != TestStatus.Skipped) + { + xmlWriter.WriteAttributeString("executed", "True"); + xmlWriter.WriteAttributeString("result", translatedResult); + xmlWriter.WriteAttributeString("success", status == TestStatus.Passed ? "True" : "False"); + xmlWriter.WriteAttributeString("time", result.Duration.TotalSeconds.ToString()); + xmlWriter.WriteAttributeString("asserts", result.AssertCount.ToString()); + } + else + { + xmlWriter.WriteAttributeString("executed", "False"); + xmlWriter.WriteAttributeString("result", translatedResult); + } + } + + private void WriteCategories(ITestResult result) + { + IPropertyBag properties = result.Test.Properties; + + if (properties.ContainsKey(PropertyNames.Category)) + { + xmlWriter.WriteStartElement("categories"); + + foreach (string category in properties[PropertyNames.Category]) + { + xmlWriter.WriteStartElement("category"); + xmlWriter.WriteAttributeString("name", category); + xmlWriter.WriteEndElement(); + } + + xmlWriter.WriteEndElement(); + } + } + + private void WriteProperties(ITestResult result) + { + IPropertyBag properties = result.Test.Properties; + int nprops = 0; + + foreach (string key in properties.Keys) + { + if (key != PropertyNames.Category) + { + if (nprops++ == 0) + xmlWriter.WriteStartElement("properties"); + + foreach (object prop in properties[key]) + { + xmlWriter.WriteStartElement("property"); + xmlWriter.WriteAttributeString("name", key); + xmlWriter.WriteAttributeString("value", prop.ToString()); + xmlWriter.WriteEndElement(); + } + } + } + + if (nprops > 0) + xmlWriter.WriteEndElement(); + } + + private void WriteReasonElement(string message) + { + xmlWriter.WriteStartElement("reason"); + xmlWriter.WriteStartElement("message"); + xmlWriter.WriteCData(message); + xmlWriter.WriteEndElement(); + xmlWriter.WriteEndElement(); + } + + private void WriteFailureElement(string message, string stackTrace) + { + xmlWriter.WriteStartElement("failure"); + xmlWriter.WriteStartElement("message"); + WriteCData(message); + xmlWriter.WriteEndElement(); + xmlWriter.WriteStartElement("stack-trace"); + if (stackTrace != null) + WriteCData(stackTrace); + xmlWriter.WriteEndElement(); + xmlWriter.WriteEndElement(); + } + + private void WriteChildResults(ITestResult result) + { + xmlWriter.WriteStartElement("results"); + + foreach (ITestResult childResult in result.Children) + WriteResultElement(childResult); + + xmlWriter.WriteEndElement(); + } + + #endregion + + #region Output Helpers + ///// + ///// Makes string safe for xml parsing, replacing control chars with '?' + ///// + ///// string to make safe + ///// xml safe string + //private static string CharacterSafeString(string encodedString) + //{ + // /*The default code page for the system will be used. + // Since all code pages use the same lower 128 bytes, this should be sufficient + // for finding uprintable control characters that make the xslt processor error. + // We use characters encoded by the default code page to avoid mistaking bytes as + // individual characters on non-latin code pages.*/ + // char[] encodedChars = System.Text.Encoding.Default.GetChars(System.Text.Encoding.Default.GetBytes(encodedString)); + + // System.Collections.ArrayList pos = new System.Collections.ArrayList(); + // for (int x = 0; x < encodedChars.Length; x++) + // { + // char currentChar = encodedChars[x]; + // //unprintable characters are below 0x20 in Unicode tables + // //some control characters are acceptable. (carriage return 0x0D, line feed 0x0A, horizontal tab 0x09) + // if (currentChar < 32 && (currentChar != 9 && currentChar != 10 && currentChar != 13)) + // { + // //save the array index for later replacement. + // pos.Add(x); + // } + // } + // foreach (int index in pos) + // { + // encodedChars[index] = '?';//replace unprintable control characters with ?(3F) + // } + // return System.Text.Encoding.Default.GetString(System.Text.Encoding.Default.GetBytes(encodedChars)); + //} + + private void WriteCData(string text) + { + int start = 0; + while (true) + { + int illegal = text.IndexOf("]]>", start); + if (illegal < 0) + break; + xmlWriter.WriteCData(text.Substring(start, illegal - start + 2)); + start = illegal + 2; + if (start >= text.Length) + return; + } + + if (start > 0) + xmlWriter.WriteCData(text.Substring(start)); + else + xmlWriter.WriteCData(text); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/NUnit3XmlOutputWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/NUnit3XmlOutputWriter.cs new file mode 100644 index 00000000000..471d75cb0a7 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/NUnit3XmlOutputWriter.cs @@ -0,0 +1,153 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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.Reflection; +using System.Xml; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnitLite.Runner +{ + /// + /// NUnit3XmlOutputWriter is responsible for writing the results + /// of a test to a file in NUnit 3.0 format. + /// + public class NUnit3XmlOutputWriter : OutputWriter + { + private DateTime runStartTime; + private XmlWriter xmlWriter; + + public NUnit3XmlOutputWriter(DateTime runStartTime) + { + this.runStartTime = runStartTime; + } + /// + /// Writes the test result to the specified TextWriter + /// + /// The result to be written to a file + /// A TextWriter to which the result is written + public override void WriteResultFile(ITestResult result, TextWriter writer) + { + // NOTE: Under .NET 1.1, XmlTextWriter does not implement IDisposable, + // but does implement Close(). Hence we cannot use a 'using' clause. +#if CLR_2_0 || CLR_4_0 + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + XmlWriter xmlWriter = XmlWriter.Create(writer, settings); +#else + XmlTextWriter xmlWriter = new XmlTextWriter(writer); + xmlWriter.Formatting = Formatting.Indented; +#endif + + try + { + WriteXmlOutput(result, xmlWriter); + } + finally + { + xmlWriter.Close(); + } + } + + private void WriteXmlOutput(ITestResult result, XmlWriter xmlWriter) + { + this.xmlWriter = xmlWriter; + + InitializeXmlFile(result); + + result.ToXml(true).WriteTo(xmlWriter); + + TerminateXmlFile(); + } + + private void InitializeXmlFile(ITestResult result) + { + xmlWriter.WriteStartDocument(false); + + // In order to match the format used by NUnit 3.0, we + // wrap the entire result from the framework in a + // element. + xmlWriter.WriteStartElement("test-run"); + + xmlWriter.WriteAttributeString("id", "2"); // TODO: Should not be hard-coded + xmlWriter.WriteAttributeString("name", result.Name); + xmlWriter.WriteAttributeString("fullname", result.FullName); + xmlWriter.WriteAttributeString("testcasecount", result.Test.TestCaseCount.ToString()); + + xmlWriter.WriteAttributeString("result", result.ResultState.Status.ToString()); + if (result.ResultState.Label != string.Empty) // && result.ResultState.Label != ResultState.Status.ToString()) + xmlWriter.WriteAttributeString("label", result.ResultState.Label); + + xmlWriter.WriteAttributeString("time", result.Duration.ToString()); + + xmlWriter.WriteAttributeString("total", (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString()); + xmlWriter.WriteAttributeString("passed", result.PassCount.ToString()); + xmlWriter.WriteAttributeString("failed", result.FailCount.ToString()); + xmlWriter.WriteAttributeString("inconclusive", result.InconclusiveCount.ToString()); + xmlWriter.WriteAttributeString("skipped", result.SkipCount.ToString()); + xmlWriter.WriteAttributeString("asserts", result.AssertCount.ToString()); + + xmlWriter.WriteAttributeString("run-date", XmlConvert.ToString(runStartTime, "yyyy-MM-dd")); + xmlWriter.WriteAttributeString("start-time", XmlConvert.ToString(runStartTime, "HH:mm:ss")); + + xmlWriter.WriteAttributeString("random-seed", Randomizer.InitialSeed.ToString()); + + WriteEnvironmentElement(); + } + + private void WriteEnvironmentElement() + { + xmlWriter.WriteStartElement("environment"); + + Assembly assembly = Assembly.GetExecutingAssembly(); + AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(assembly); + xmlWriter.WriteAttributeString("nunit-version", assemblyName.Version.ToString()); + + xmlWriter.WriteAttributeString("clr-version", Environment.Version.ToString()); + xmlWriter.WriteAttributeString("os-version", Environment.OSVersion.ToString()); + xmlWriter.WriteAttributeString("platform", Environment.OSVersion.Platform.ToString()); +#if !NETCF + xmlWriter.WriteAttributeString("cwd", Environment.CurrentDirectory); +#if !SILVERLIGHT + xmlWriter.WriteAttributeString("machine-name", Environment.MachineName); + xmlWriter.WriteAttributeString("user", Environment.UserName); + xmlWriter.WriteAttributeString("user-domain", Environment.UserDomainName); +#endif +#endif + xmlWriter.WriteAttributeString("culture", System.Globalization.CultureInfo.CurrentCulture.ToString()); + xmlWriter.WriteAttributeString("uiculture", System.Globalization.CultureInfo.CurrentUICulture.ToString()); + + xmlWriter.WriteEndElement(); + } + + private void TerminateXmlFile() + { + xmlWriter.WriteEndElement(); // test-run + xmlWriter.WriteEndDocument(); + xmlWriter.Flush(); + xmlWriter.Close(); + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/OutputWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/OutputWriter.cs new file mode 100644 index 00000000000..96840958840 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/OutputWriters/OutputWriter.cs @@ -0,0 +1,57 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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.IO; +using System.Text; +using NUnit.Framework.Api; + +namespace NUnitLite.Runner +{ + /// + /// OutputWriter is an abstract class used to write test + /// results to a file in various formats. Specific + /// OutputWriters are derived from this class. + /// + public abstract class OutputWriter + { + /// + /// Writes a test result to a file + /// + /// The result to be written + /// Path to the file to which the result is written + public void WriteResultFile(ITestResult result, string outputPath) + { + using (StreamWriter writer = new StreamWriter(outputPath, false, Encoding.UTF8)) + { + WriteResultFile(result, writer); + } + } + + /// + /// Abstract method that writes a test result to a TextWriter + /// + /// The result to be written + /// A TextWriter to which the result is written + public abstract void WriteResultFile(ITestResult result, TextWriter writer); + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ResultReporter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ResultReporter.cs new file mode 100644 index 00000000000..31921ad0006 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ResultReporter.cs @@ -0,0 +1,196 @@ +// *********************************************************************** +// Copyright (c) 2012 Charlie Poole +// +// 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.IO; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnitLite.Runner +{ + /// + /// ResultReporter writes the NUnitLite results to a TextWriter. + /// + public class ResultReporter + { + private TextWriter writer; + private ITestResult result; + private ResultSummary summary; + private int reportCount = 0; + + /// + /// Constructs an instance of ResultReporter + /// + /// The top-level result being reported + /// A TextWriter to which the report is written + public ResultReporter(ITestResult result, TextWriter writer) + { + this.result = result; + this.writer = writer; + + this.summary = new ResultSummary(this.result); + } + + /// + /// Gets the ResultSummary created by the ResultReporter + /// + public ResultSummary Summary + { + get { return summary; } + } + + /// + /// Produces the standard output reports. + /// + public void ReportResults() + { + PrintSummaryReport(); + + if (summary.FailureCount > 0 || summary.ErrorCount > 0) + PrintErrorReport(); + + if (summary.NotRunCount > 0) + PrintNotRunReport(); + + //if (commandLineOptions.Full) + // PrintFullReport(result); + } + + /// + /// Prints the Summary Report + /// + public void PrintSummaryReport() + { + writer.WriteLine( + "Tests run: {0}, Passed: {1}, Errors: {2}, Failures: {3}, Inconclusive: {4}", + summary.TestCount, summary.PassCount, summary.ErrorCount, summary.FailureCount, summary.InconclusiveCount); + writer.WriteLine( + " Not run: {0}, Invalid: {1}, Ignored: {2}, Skipped: {3}", + summary.NotRunCount, summary.InvalidCount, summary.IgnoreCount, summary.SkipCount); + writer.WriteLine("Elapsed time: {0}", result.Duration); + } + + /// + /// Prints the Error Report + /// + public void PrintErrorReport() + { + reportCount = 0; + writer.WriteLine(); + writer.WriteLine("Errors and Failures:"); + PrintErrorResults(this.result); + } + + /// + /// Prints the Not Run Report + /// + public void PrintNotRunReport() + { + reportCount = 0; + writer.WriteLine(); + writer.WriteLine("Tests Not Run:"); + PrintNotRunResults(this.result); + } + + /// + /// Prints a full report of all results + /// + public void PrintFullReport() + { + writer.WriteLine(); + writer.WriteLine("All Test Results:"); + PrintAllResults(this.result, " "); + } + + #region Helper Methods + + private void PrintErrorResults(ITestResult result) + { + if (result.ResultState.Status == TestStatus.Failed) + if (!result.HasChildren) + WriteSingleResult(result); + + if (result.HasChildren) + foreach (ITestResult childResult in result.Children) + PrintErrorResults(childResult); + } + + private void PrintNotRunResults(ITestResult result) + { + if (result.HasChildren) + foreach (ITestResult childResult in result.Children) + PrintNotRunResults(childResult); + else if (result.ResultState.Status == TestStatus.Skipped) + WriteSingleResult(result); + } + + private void PrintTestProperties(ITest test) + { + foreach (PropertyEntry entry in test.Properties) + writer.WriteLine(" {0}: {1}", entry.Name, entry.Value); + } + + private void PrintAllResults(ITestResult result, string indent) + { + string status = null; + switch (result.ResultState.Status) + { + case TestStatus.Failed: + status = "FAIL"; + break; + case TestStatus.Skipped: + status = "SKIP"; + break; + case TestStatus.Inconclusive: + status = "INC "; + break; + case TestStatus.Passed: + status = "OK "; + break; + } + + writer.Write(status); + writer.Write(indent); + writer.WriteLine(result.Name); + + if (result.HasChildren) + foreach (ITestResult childResult in result.Children) + PrintAllResults(childResult, indent + " "); + } + + private void WriteSingleResult(ITestResult result) + { + writer.WriteLine(); + writer.WriteLine("{0}) {1} ({2})", ++reportCount, result.Name, result.FullName); + + if (result.Message != null && result.Message != string.Empty) + writer.WriteLine(" {0}", result.Message); + + if (result.StackTrace != null && result.StackTrace != string.Empty) + writer.WriteLine(result.ResultState == ResultState.Failure + ? StackFilter.Filter(result.StackTrace) + : result.StackTrace + NUnit.Env.NewLine); + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ResultSummary.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ResultSummary.cs new file mode 100644 index 00000000000..6ff1eab2652 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/ResultSummary.cs @@ -0,0 +1,168 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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 NUnit.Framework.Api; + +namespace NUnitLite.Runner +{ + /// + /// Helper class used to summarize the result of a test run + /// + public class ResultSummary + { + private int testCount; + private int passCount; + private int errorCount; + private int failureCount; + private int notRunCount; + private int inconclusiveCount; + private int ignoreCount; + private int skipCount; + private int invalidCount; + + /// + /// Initializes a new instance of the class. + /// + /// The result. + public ResultSummary(ITestResult result) + { + Visit(result); + } + + /// + /// Gets the test count. + /// + /// The test count. + public int TestCount + { + get { return testCount; } + } + + /// + /// Gets the count of passed tests + /// + public int PassCount + { + get { return passCount; } + } + + /// + /// Gets the error count. + /// + /// The error count. + public int ErrorCount + { + get { return errorCount; } + } + + /// + /// Gets the failure count. + /// + /// The failure count. + public int FailureCount + { + get { return failureCount; } + } + + /// + /// Gets the not run count. + /// + /// The not run count. + public int NotRunCount + { + get { return notRunCount; } + } + + /// + /// Gets the ignore count + /// + public int IgnoreCount + { + get { return ignoreCount; } + } + + /// + /// Gets the skip count + /// + public int SkipCount + { + get { return skipCount; } + } + + /// + /// Gets the invalid count + /// + public int InvalidCount + { + get { return invalidCount; } + } + + /// + /// Gets the count of inconclusive results + /// + public int InconclusiveCount + { + get { return inconclusiveCount; } + } + + private void Visit(ITestResult result) + { + if (result.Test.IsSuite) + { + foreach (ITestResult r in result.Children) + Visit(r); + } + else + { + testCount++; + + switch (result.ResultState.Status) + { + case TestStatus.Passed: + passCount++; + break; + case TestStatus.Skipped: + if (result.ResultState == ResultState.Ignored) + ignoreCount++; + else if (result.ResultState == ResultState.Skipped) + skipCount++; + else if (result.ResultState == ResultState.NotRunnable) + invalidCount++; + notRunCount++; + break; + case TestStatus.Failed: + if (result.ResultState == ResultState.Failure) + failureCount++; + else + errorCount++; + break; + case TestStatus.Inconclusive: + inconclusiveCount++; + break; + } + + return; + } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/TcpWriter.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/TcpWriter.cs new file mode 100644 index 00000000000..2e916fddb39 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/TcpWriter.cs @@ -0,0 +1,73 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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.Net.Sockets; +using System.Text; + +namespace NUnitLite.Runner +{ + /// + /// Redirects output to a Tcp connection + /// + class TcpWriter : TextWriter + { + private string hostName; + private int port; + + private TcpClient client; + private NetworkStream stream; + private StreamWriter writer; + + public TcpWriter(string hostName, int port) + { + this.hostName = hostName; + this.port = port; + this.client = new TcpClient(hostName, port); + this.stream = client.GetStream(); + this.writer = new StreamWriter(stream); + } + + public override void Write(char value) + { + writer.Write(value); + } + + public override void Write(string value) + { + writer.Write(value); + } + + public override void WriteLine(string value) + { + writer.WriteLine(value); + writer.Flush(); + } + + public override System.Text.Encoding Encoding + { + get { return System.Text.Encoding.Default; } + } + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/TextUI.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/TextUI.cs new file mode 100644 index 00000000000..abba4e31544 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Runner/TextUI.cs @@ -0,0 +1,362 @@ +// *********************************************************************** +// Copyright (c) 2007 Charlie Poole +// +// 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.Collections; +using System.Reflection; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.Filters; +using System.Diagnostics; + +namespace NUnitLite.Runner +{ + /// + /// TextUI is a general purpose class that runs tests and + /// outputs to a TextWriter. + /// + /// Call it from your Main like this: + /// new TextUI(textWriter).Execute(args); + /// OR + /// new TextUI().Execute(args); + /// The provided TextWriter is used by default, unless the + /// arguments to Execute override it using -out. The second + /// form uses the Console, provided it exists on the platform. + /// + /// NOTE: When running on a platform without a Console, such + /// as Windows Phone, the results will simply not appear if + /// you fail to specify a file in the call itself or as an option. + /// + public class TextUI : ITestListener + { + private CommandLineOptions commandLineOptions; + + private NUnit.ObjectList assemblies = new NUnit.ObjectList(); + + private TextWriter writer; + + private ITestListener listener; + + private ITestAssemblyRunner runner; + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public TextUI() : this(ConsoleWriter.Out, TestListener.NULL) { } + + /// + /// Initializes a new instance of the class. + /// + /// The TextWriter to use. + public TextUI(TextWriter writer) : this(writer, TestListener.NULL) { } + + /// + /// Initializes a new instance of the class. + /// + /// The TextWriter to use. + /// The Test listener to use. + public TextUI(TextWriter writer, ITestListener listener) + { + // Set the default writer - may be overridden by the args specified + this.writer = writer; + this.runner = new NUnitLiteTestAssemblyRunner(new NUnitLiteTestAssemblyBuilder()); + this.listener = listener; + } + + #endregion + + #region Public Methods + + /// + /// Execute a test run based on the aruments passed + /// from Main. + /// + /// An array of arguments + public void Execute(string[] args) + { + // NOTE: Execute must be directly called from the + // test assembly in order for the mechanism to work. + Assembly callingAssembly = Assembly.GetCallingAssembly(); + + this.commandLineOptions = new CommandLineOptions(); + commandLineOptions.Parse(args); + + if (commandLineOptions.OutFile != null) + this.writer = new StreamWriter(commandLineOptions.OutFile); + + if (!commandLineOptions.NoHeader) + WriteHeader(this.writer); + + if (commandLineOptions.ShowHelp) + writer.Write(commandLineOptions.HelpText); + else if (commandLineOptions.Error) + { + writer.WriteLine(commandLineOptions.ErrorMessage); + writer.WriteLine(commandLineOptions.HelpText); + } + else + { + WriteRuntimeEnvironment(this.writer); + + if (commandLineOptions.Wait && commandLineOptions.OutFile != null) + writer.WriteLine("Ignoring /wait option - only valid for Console"); + +#if SILVERLIGHT + IDictionary loadOptions = new System.Collections.Generic.Dictionary(); +#else + IDictionary loadOptions = new Hashtable(); +#endif + //if (options.Load.Count > 0) + // loadOptions["LOAD"] = options.Load; + + //IDictionary runOptions = new Hashtable(); + //if (commandLineOptions.TestCount > 0) + // runOptions["RUN"] = commandLineOptions.Tests; + + ITestFilter filter = commandLineOptions.TestCount > 0 + ? new SimpleNameFilter(commandLineOptions.Tests) + : TestFilter.Empty; + + try + { + foreach (string name in commandLineOptions.Parameters) + assemblies.Add(Assembly.Load(name)); + + if (assemblies.Count == 0) + assemblies.Add(callingAssembly); + + // TODO: For now, ignore all but first assembly + Assembly assembly = assemblies[0] as Assembly; + + Randomizer.InitialSeed = commandLineOptions.InitialSeed; + + if (!runner.Load(assembly, loadOptions)) + { + AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(assembly); + Console.WriteLine("No tests found in assembly {0}", assemblyName.Name); + return; + } + + if (commandLineOptions.Explore) + ExploreTests(); + else + { + if (commandLineOptions.Include != null && commandLineOptions.Include != string.Empty) + { + TestFilter includeFilter = new SimpleCategoryExpression(commandLineOptions.Include).Filter; + + if (filter.IsEmpty) + filter = includeFilter; + else + filter = new AndFilter(filter, includeFilter); + } + + if (commandLineOptions.Exclude != null && commandLineOptions.Exclude != string.Empty) + { + TestFilter excludeFilter = new NotFilter(new SimpleCategoryExpression(commandLineOptions.Exclude).Filter); + + if (filter.IsEmpty) + filter = excludeFilter; + else if (filter is AndFilter) + ((AndFilter)filter).Add(excludeFilter); + else + filter = new AndFilter(filter, excludeFilter); + } + + RunTests(filter); + } + } + catch (FileNotFoundException ex) + { + writer.WriteLine(ex.Message); + } + catch (Exception ex) + { + writer.WriteLine(ex.ToString()); + } + finally + { + if (commandLineOptions.OutFile == null) + { + if (commandLineOptions.Wait) + { + Console.WriteLine("Press Enter key to continue . . ."); + Console.ReadLine(); + } + } + else + { + writer.Close(); + } + } + } + } + + /// + /// Write the standard header information to a TextWriter. + /// + /// The TextWriter to use + public static void WriteHeader(TextWriter writer) + { + Assembly executingAssembly = Assembly.GetExecutingAssembly(); +#if NUNITLITE + string title = "NUnitLite"; +#else + string title = "NUNit Framework"; +#endif + AssemblyName assemblyName = AssemblyHelper.GetAssemblyName(executingAssembly); + System.Version version = assemblyName.Version; + string copyright = "Copyright (C) 2012, Charlie Poole"; + string build = ""; + + object[] attrs = executingAssembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + if (attrs.Length > 0) + { + AssemblyTitleAttribute titleAttr = (AssemblyTitleAttribute)attrs[0]; + title = titleAttr.Title; + } + + attrs = executingAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + if (attrs.Length > 0) + { + AssemblyCopyrightAttribute copyrightAttr = (AssemblyCopyrightAttribute)attrs[0]; + copyright = copyrightAttr.Copyright; + } + + attrs = executingAssembly.GetCustomAttributes(typeof(AssemblyConfigurationAttribute), false); + if (attrs.Length > 0) + { + AssemblyConfigurationAttribute configAttr = (AssemblyConfigurationAttribute)attrs[0]; + if (configAttr.Configuration.Length > 0) + build = string.Format("({0})", configAttr.Configuration); + } + + writer.WriteLine(String.Format("{0} {1} {2}", title, version.ToString(3), build)); + writer.WriteLine(copyright); + writer.WriteLine(); + } + + /// + /// Write information about the current runtime environment + /// + /// The TextWriter to be used + public static void WriteRuntimeEnvironment(TextWriter writer) + { + string clrPlatform = Type.GetType("Mono.Runtime", false) == null ? ".NET" : "Mono"; + + writer.WriteLine("Runtime Environment -"); + writer.WriteLine(" OS Version: {0}", Environment.OSVersion); + writer.WriteLine(" {0} Version: {1}", clrPlatform, Environment.Version); + writer.WriteLine(); + } + + #endregion + + #region Helper Methods + + private void RunTests(ITestFilter filter) + { + DateTime startTime = DateTime.Now; + + ITestResult result = runner.Run(this, filter); + new ResultReporter(result, writer).ReportResults(); + string resultFile = commandLineOptions.ResultFile; + string resultFormat = commandLineOptions.ResultFormat; + + if (resultFile != null || commandLineOptions.ResultFormat != null) + { + if (resultFile == null) + resultFile = "TestResult.xml"; + + if (resultFormat == "nunit2") + new NUnit2XmlOutputWriter(startTime).WriteResultFile(result, resultFile); + else + new NUnit3XmlOutputWriter(startTime).WriteResultFile(result, resultFile); + + Console.WriteLine(); + Console.WriteLine("Results saved as {0}.", resultFile); + } + } + + private void ExploreTests() + { + XmlNode testNode = runner.LoadedTest.ToXml(true); + + string listFile = commandLineOptions.ExploreFile; + TextWriter textWriter = listFile != null && listFile.Length > 0 + ? new StreamWriter(listFile) + : Console.Out; + +#if CLR_2_0 || CLR_4_0 + System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings(); + settings.Indent = true; + settings.Encoding = System.Text.Encoding.UTF8; + System.Xml.XmlWriter testWriter = System.Xml.XmlWriter.Create(textWriter, settings); +#else + System.Xml.XmlTextWriter testWriter = new System.Xml.XmlTextWriter(textWriter); + testWriter.Formatting = System.Xml.Formatting.Indented; +#endif + + testNode.WriteTo(testWriter); + testWriter.Close(); + + Console.WriteLine(); + Console.WriteLine("Test info saved as {0}.", listFile); + } + + #endregion + + #region ITestListener Members + + /// + /// A test has just started + /// + /// The test + public void TestStarted(ITest test) + { + if (commandLineOptions.LabelTestsInOutput) + writer.WriteLine("***** {0}", test.Name); + } + + /// + /// A test has just finished + /// + /// The result of the test + public void TestFinished(ITestResult result) + { + } + + /// + /// A test has produced some text output + /// + /// A TestOutput object holding the text that was written + public void TestOutput(TestOutput testOutput) + { + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/SpecialValue.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/SpecialValue.cs new file mode 100644 index 00000000000..c7308921083 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/SpecialValue.cs @@ -0,0 +1,40 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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 NUnit.Framework +{ + /// + /// The SpecialValue enum is used to represent TestCase arguments + /// that cannot be used as arguments to an Attribute. + /// + public enum SpecialValue + { + /// + /// Null represents a null value, which cannot be used as an + /// argument to an attribute under .NET 1.x + /// + Null + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/TestCaseData.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/TestCaseData.cs new file mode 100644 index 00000000000..614d63bc403 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/TestCaseData.cs @@ -0,0 +1,389 @@ +// *********************************************************************** +// Copyright (c) 2008 Charlie Poole +// +// 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; +using System.Collections.Specialized; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +// TODO: Remove conditional code +namespace NUnit.Framework +{ + /// + /// The TestCaseData class represents a set of arguments + /// and other parameter info to be used for a parameterized + /// test case. It provides a number of instance modifiers + /// for use in initializing the test case. + /// + /// Note: Instance modifiers are getters that return + /// the same instance after modifying it's state. + /// + public class TestCaseData : ITestCaseData + { + + #region Instance Fields + + /// + /// The argument list to be provided to the test + /// + private object[] arguments; + + /// + /// The expected result to be returned + /// + private object expectedResult; + + /// + /// Data about any expected exception. + /// + private ExpectedExceptionData exceptionData; + + /// + /// A dictionary of properties, used to add information + /// to tests without requiring the class to change. + /// + private IPropertyBag properties; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The arguments. + public TestCaseData(params object[] args) + { + this.RunState = RunState.Runnable; + + if (args == null) + this.arguments = new object[] { null }; + else + this.arguments = args; + } + + /// + /// Initializes a new instance of the class. + /// + /// The argument. + public TestCaseData(object arg) + { + this.RunState = RunState.Runnable; + this.arguments = new object[] { arg }; + } + + /// + /// Initializes a new instance of the class. + /// + /// The first argument. + /// The second argument. + public TestCaseData(object arg1, object arg2) + { + this.RunState = RunState.Runnable; + this.arguments = new object[] { arg1, arg2 }; + } + + /// + /// Initializes a new instance of the class. + /// + /// The first argument. + /// The second argument. + /// The third argument. + public TestCaseData(object arg1, object arg2, object arg3) + { + this.RunState = RunState.Runnable; + this.arguments = new object[] { arg1, arg2, arg3 }; + } + + #endregion + + #region ITestCaseData Members + + /// + /// Gets the argument list to be provided to the test + /// + public object[] Arguments + { + get { return arguments; } + } + + /// + /// Gets the expected result + /// + public object ExpectedResult + { + get { return expectedResult; } + set + { + expectedResult = value; + HasExpectedResult = true; + } + } + + private bool hasExpectedResult; + /// + /// Returns true if the expected result has been set + /// + public bool HasExpectedResult + { + get { return hasExpectedResult; } + set { hasExpectedResult = value; } + } + + /// + /// Gets data about any expected exception. + /// + public ExpectedExceptionData ExceptionData + { + get { return exceptionData; } + } + + private string testName; + /// + /// Gets the name to be used for the test + /// + public string TestName + { + get { return testName; } + set { testName = value; } + } + + private RunState runState; + /// + /// Gets the RunState for this test case. + /// + public RunState RunState + { + get { return runState; } + set { runState = value; } + } + + /// + /// Gets the property dictionary for this test + /// + public IPropertyBag Properties + { + get + { + if (properties == null) + properties = new NUnit.Framework.Internal.PropertyBag(); + + return properties; + } + } + + #endregion + + #region Public Properties - NUnit 2.6 Compatibility + + /// + /// Gets the expected result. + /// + public object Result + { + get { return expectedResult; } + } + + /// + /// The type of exception expected + /// + public Type ExpectedException + { + get { return exceptionData.ExpectedExceptionType; } + } + + /// + /// The full name of the expected exception type + /// + public string ExpectedExceptionName + { + get { return exceptionData.ExpectedExceptionName; } + } + + /// + /// The message to expect on any exception + /// + public string ExpectedExceptionMessage + { + get { return exceptionData.ExpectedMessage; } + } + + /// + /// The type of match to be made on the message + /// + public MessageMatch MatchType + { + get { return exceptionData.MatchType; } + } + + #endregion + + #region Fluent Instance Modifiers + + /// + /// Sets the expected result for the test + /// + /// The expected result + /// A modified TestCaseData + public TestCaseData Returns(object result) + { + this.ExpectedResult = result; + return this; + } + + /// + /// Sets the expected exception type for the test + /// + /// Type of the expected exception. + /// The modified TestCaseData instance + public TestCaseData Throws(Type exceptionType) + { + //this.expectedExceptionType = exceptionType; + exceptionData.ExpectedExceptionName = exceptionType.FullName; + return this; + } + + /// + /// Sets the expected exception type for the test + /// + /// FullName of the expected exception. + /// The modified TestCaseData instance + public TestCaseData Throws(string exceptionName) + { + exceptionData.ExpectedExceptionName = exceptionName; + return this; + } + + /// + /// Sets the name of the test case + /// + /// The modified TestCaseData instance + public TestCaseData SetName(string name) + { + this.TestName = name; + return this; + } + + /// + /// Sets the description for the test case + /// being constructed. + /// + /// The description. + /// The modified TestCaseData instance. + public TestCaseData SetDescription(string description) + { + this.Properties.Set(PropertyNames.Description, description); + return this; + } + + /// + /// Applies a category to the test + /// + /// + /// + public TestCaseData SetCategory(string category) + { + this.Properties.Add(PropertyNames.Category, category); + return this; + } + + /// + /// Applies a named property to the test + /// + /// + /// + /// + public TestCaseData SetProperty(string propName, string propValue) + { + this.Properties.Add(propName, propValue); + return this; + } + + /// + /// Applies a named property to the test + /// + /// + /// + /// + public TestCaseData SetProperty(string propName, int propValue) + { + this.Properties.Add(propName, propValue); + return this; + } + + /// + /// Applies a named property to the test + /// + /// + /// + /// + public TestCaseData SetProperty(string propName, double propValue) + { + this.Properties.Add(propName, propValue); + return this; + } + + /// + /// Ignores this TestCase. + /// + /// + public TestCaseData Ignore() + { + this.RunState = RunState.Ignored; + return this; + } + + /// + /// Marks the test case as explicit. + /// + public TestCaseData Explicit() { + this.RunState = RunState.Explicit; + return this; + } + + /// + /// Marks the test case as explicit, specifying the reason. + /// + public TestCaseData Explicit(string reason) + { + this.RunState = RunState.Explicit; + this.Properties.Set(PropertyNames.SkipReason, reason); + return this; + } + + /// + /// Ignores this TestCase, specifying the reason. + /// + /// The reason. + /// + public TestCaseData Ignore(string reason) + { + this.RunState = RunState.Ignored; + this.Properties.Set(PropertyNames.SkipReason, reason); + return this; + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/TestContext.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/TestContext.cs new file mode 100644 index 00000000000..a5b34441093 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/TestContext.cs @@ -0,0 +1,257 @@ +// *********************************************************************** +// Copyright (c) 2011 Charlie Poole +// +// 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; +using NUnit.Framework.Api; +using NUnit.Framework.Internal; + +namespace NUnit.Framework +{ + /// + /// Provide the context information of the current test. + /// This is an adapter for the internal ExecutionContext + /// class, hiding the internals from the user test. + /// + public class TestContext + { + private TestExecutionContext ec; + private TestAdapter test; + private ResultAdapter result; + + #region Constructor + + /// + /// Construct a TestContext for an ExecutionContext + /// + /// The ExecutionContext to adapt + public TestContext(TestExecutionContext ec) + { + this.ec = ec; + } + + #endregion + + #region Properties + + /// + /// Get the current test context. This is created + /// as needed. The user may save the context for + /// use within a test, but it should not be used + /// outside the test for which it is created. + /// + public static TestContext CurrentContext + { + get { return new TestContext(TestExecutionContext.CurrentContext); } + } + + /// + /// Get a representation of the current test. + /// + public TestAdapter Test + { + get + { + if (test == null) + test = new TestAdapter(ec.CurrentTest); + + return test; + } + } + + /// + /// Gets a Representation of the TestResult for the current test. + /// + public ResultAdapter Result + { + get + { + if (result == null) + result = new ResultAdapter(ec.CurrentResult); + + return result; + } + } + +#if !NETCF + /// + /// Gets the directory containing the current test assembly. + /// + public string TestDirectory + { + get + { + return AssemblyHelper.GetDirectoryName(ec.CurrentTest.FixtureType.Assembly); + } + } +#endif + + /// + /// Gets the directory to be used for outputing files created + /// by this test run. + /// + public string WorkDirectory + { + get + { + return ec.WorkDirectory; + } + } + + public RandomGenerator Random + { + get + { + return ec.RandomGenerator; + } + } + + #endregion + + #region Nested TestAdapter Class + + /// + /// TestAdapter adapts a Test for consumption by + /// the user test code. + /// + public class TestAdapter + { + private Test test; + + #region Constructor + + /// + /// Construct a TestAdapter for a Test + /// + /// The Test to be adapted + public TestAdapter(Test test) + { + this.test = test; + } + + #endregion + + #region Properties + + /// + /// Gets the unique Id of a test + /// + public int ID + { + get { return test.Id; } + } + + /// + /// The name of the test, which may or may not be + /// the same as the method name. + /// + public string Name + { + get + { + return test.Name; + } + } + + /// + /// The name of the method representing the test. + /// + public string MethodName + { + get + { + return test is TestMethod + ? ((TestMethod)test).Method.Name + : null; + } + } + + /// + /// The FullName of the test + /// + public string FullName + { + get + { + return test.FullName; + } + } + + /// + /// The properties of the test. + /// + public IPropertyBag Properties + { + get + { + return test.Properties; + } + } + + #endregion + } + + #endregion + + #region Nested ResultAdapter Class + + /// + /// ResultAdapter adapts a TestResult for consumption by + /// the user test code. + /// + public class ResultAdapter + { + private TestResult result; + + #region Constructor + + /// + /// Construct a ResultAdapter for a TestResult + /// + /// The TestResult to be adapted + public ResultAdapter(TestResult result) + { + this.result = result; + } + + #endregion + + #region Properties + + /// + /// Gets a ResultState representing the outcome of the test. + /// + public ResultState Outcome + { + get + { + return result.ResultState; + } + } + + #endregion + } + + #endregion + } +} diff --git a/src/Xamarin.Android.NUnitLite/NUnitLite/Throws.cs b/src/Xamarin.Android.NUnitLite/NUnitLite/Throws.cs new file mode 100644 index 00000000000..8b49983629a --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/NUnitLite/Throws.cs @@ -0,0 +1,153 @@ +// *********************************************************************** +// Copyright (c) 2009 Charlie Poole +// +// 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; +using NUnit.Framework.Constraints; + +namespace NUnit.Framework +{ + /// + /// Helper class with properties and methods that supply + /// constraints that operate on exceptions. + /// + public class Throws + { + #region Exception + + /// + /// Creates a constraint specifying an expected exception + /// + public static ResolvableConstraintExpression Exception + { + get { return new ConstraintExpression().Append(new ThrowsOperator()); } + } + + #endregion + + #region InnerException + + /// + /// Creates a constraint specifying an exception with a given InnerException + /// + public static ResolvableConstraintExpression InnerException + { + get { return Exception.InnerException; } + } + + #endregion + + #region TargetInvocationException + + /// + /// Creates a constraint specifying an expected TargetInvocationException + /// + public static ExactTypeConstraint TargetInvocationException + { + get { return TypeOf(typeof(System.Reflection.TargetInvocationException)); } + } + + #endregion + + #region ArgumentException + + /// + /// Creates a constraint specifying an expected TargetInvocationException + /// + public static ExactTypeConstraint ArgumentException + { + get { return TypeOf(typeof(System.ArgumentException)); } + } + + #endregion + + #region InvalidOperationException + + /// + /// Creates a constraint specifying an expected TargetInvocationException + /// + public static ExactTypeConstraint InvalidOperationException + { + get { return TypeOf(typeof(System.InvalidOperationException)); } + } + + #endregion + + #region Nothing + + /// + /// Creates a constraint specifying that no exception is thrown + /// + public static ThrowsNothingConstraint Nothing + { + get { return new ThrowsNothingConstraint(); } + } + + #endregion + + #region TypeOf + + /// + /// Creates a constraint specifying the exact type of exception expected + /// + public static ExactTypeConstraint TypeOf(Type expectedType) + { + return Exception.TypeOf(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Creates a constraint specifying the exact type of exception expected + /// + public static ExactTypeConstraint TypeOf() + { + return TypeOf(typeof(T)); + } +#endif + + #endregion + + #region InstanceOf + + /// + /// Creates a constraint specifying the type of exception expected + /// + public static InstanceOfTypeConstraint InstanceOf(Type expectedType) + { + return Exception.InstanceOf(expectedType); + } + +#if CLR_2_0 || CLR_4_0 + /// + /// Creates a constraint specifying the type of exception expected + /// + public static InstanceOfTypeConstraint InstanceOf() + { + return InstanceOf(typeof(T)); + } +#endif + + #endregion + + } +} diff --git a/src/Xamarin.Android.NUnitLite/Properties/AssemblyInfo.cs b/src/Xamarin.Android.NUnitLite/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..28334c8ac62 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("Xamarin.Android.NUnitLite")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("jon")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/src/Xamarin.Android.NUnitLite/Resources/Resource.designer.cs b/src/Xamarin.Android.NUnitLite/Resources/Resource.designer.cs new file mode 100644 index 00000000000..795e06ae1f5 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Resources/Resource.designer.cs @@ -0,0 +1,133 @@ +#pragma warning disable 1591 +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +[assembly: Android.Runtime.ResourceDesignerAttribute("Xamarin.Android.NUnitLite.Resource", IsApplication=false)] + +namespace Xamarin.Android.NUnitLite +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f030001 + public static int OptionHostName = 2130903041; + + // aapt resource value: 0x7f030002 + public static int OptionPort = 2130903042; + + // aapt resource value: 0x7f030000 + public static int OptionRemoteServer = 2130903040; + + // aapt resource value: 0x7f030010 + public static int OptionsButton = 2130903056; + + // aapt resource value: 0x7f03000b + public static int ResultFullName = 2130903051; + + // aapt resource value: 0x7f03000d + public static int ResultMessage = 2130903053; + + // aapt resource value: 0x7f03000c + public static int ResultResultState = 2130903052; + + // aapt resource value: 0x7f03000a + public static int ResultRunSingleMethodTest = 2130903050; + + // aapt resource value: 0x7f03000e + public static int ResultStackTrace = 2130903054; + + // aapt resource value: 0x7f030006 + public static int ResultsFailed = 2130903046; + + // aapt resource value: 0x7f030003 + public static int ResultsId = 2130903043; + + // aapt resource value: 0x7f030007 + public static int ResultsIgnored = 2130903047; + + // aapt resource value: 0x7f030008 + public static int ResultsInconclusive = 2130903048; + + // aapt resource value: 0x7f030009 + public static int ResultsMessage = 2130903049; + + // aapt resource value: 0x7f030005 + public static int ResultsPassed = 2130903045; + + // aapt resource value: 0x7f030004 + public static int ResultsResult = 2130903044; + + // aapt resource value: 0x7f03000f + public static int RunTestsButton = 2130903055; + + // aapt resource value: 0x7f030011 + public static int TestSuiteListView = 2130903057; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f020000 + public static int options = 2130837504; + + // aapt resource value: 0x7f020001 + public static int results = 2130837505; + + // aapt resource value: 0x7f020002 + public static int test_result = 2130837506; + + // aapt resource value: 0x7f020003 + public static int test_suite = 2130837507; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/src/Xamarin.Android.NUnitLite/Resources/layout/Runner.axml b/src/Xamarin.Android.NUnitLite/Resources/layout/Runner.axml new file mode 100644 index 00000000000..dcc2bb7c02d --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Resources/layout/Runner.axml @@ -0,0 +1,39 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/Resources/layout/options.axml b/src/Xamarin.Android.NUnitLite/Resources/layout/options.axml new file mode 100644 index 00000000000..9d0cc309506 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Resources/layout/options.axml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/Resources/layout/results.axml b/src/Xamarin.Android.NUnitLite/Resources/layout/results.axml new file mode 100644 index 00000000000..066725f4296 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Resources/layout/results.axml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Xamarin.Android.NUnitLite/Resources/layout/test_result.axml b/src/Xamarin.Android.NUnitLite/Resources/layout/test_result.axml new file mode 100644 index 00000000000..532471259a1 --- /dev/null +++ b/src/Xamarin.Android.NUnitLite/Resources/layout/test_result.axml @@ -0,0 +1,35 @@ + + +