Added UriPermutationsTest.
authorMarcos Henrich <marcos.henrich@xamarin.com>
Tue, 1 Jul 2014 11:14:31 +0000 (12:14 +0100)
committerMarcos Henrich <marcos.henrich@xamarin.com>
Tue, 1 Jul 2014 11:14:31 +0000 (12:14 +0100)
Created a new set of tests that create&store or that load&assert uri permutations.
Uris are created with permutations of schemes, components, characters then methods and properties output is asserted against expected values obtained on .NET.

mcs/class/System/System_test.dll.sources
mcs/class/System/Test/System/StringTester.cs [new file with mode: 0644]
mcs/class/System/Test/System/UriPermutationsTest.cs [new file with mode: 0644]

index 33f8326b2d6e9041d793afd58945e5239378669a..e947d04dd99b607b8836194a64c517f9cf65536f 100644 (file)
@@ -25,11 +25,13 @@ System/LdapStyleUriParserTest.cs
 System/NetPipeStyleUriParserTest.cs
 System/NetTcpStyleUriParserTest.cs
 System/NewsStyleUriParserTest.cs
+System/StringTester.cs
 System/UriBuilderTest.cs
 System/UriParserTest.cs
 System/UriTest.cs
 System/UriTest2.cs
 System/UriTest3.cs
+System/UriPermutationsTest.cs
 System/UriTypeConverterTest.cs
 System.CodeDom/CodeArgumentReferenceExpressionTest.cs
 System.CodeDom/CodeArrayCreateExpressionTest.cs
diff --git a/mcs/class/System/Test/System/StringTester.cs b/mcs/class/System/Test/System/StringTester.cs
new file mode 100644 (file)
index 0000000..cc0a402
--- /dev/null
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using NUnit.Framework;
+
+namespace MonoTests.System {
+       public class StringTester {
+               private const string ext = ".txt";
+               public static string Location = "./StringTests/";
+               public static bool CreateMode = false;
+
+               private static readonly Dictionary<string, Asserts> asserts = new Dictionary<string, Asserts> ();
+
+               public static void Assert (string id, string actual, string message)
+               {
+                       string testFullName = GetTestMethodName ();
+
+                       Asserts testAsserts;
+                       if (!asserts.TryGetValue (testFullName, out testAsserts)) {
+                               testAsserts = new Asserts ();
+
+                               if (!CreateMode) {
+                                       string filePath = Path.GetFullPath (Path.Combine (Location, testFullName + ext));
+                                       if (!File.Exists (filePath)) {
+                                               NUnit.Framework.Assert.Ignore (filePath + " does not exist. \n" +
+                                                                                                          "The file should be generated by running on .NET the same test with StringTester.CreateMode = true.");
+                                       }
+
+                                       testAsserts.Load (filePath);
+                               }
+
+                               asserts.Add (testFullName, testAsserts);
+                       }
+
+                       if (CreateMode) {
+                               testAsserts.AddExpected (id, actual);
+                               return;
+                       }
+
+                       string expected = testAsserts.GetExpected (id);
+                       NUnit.Framework.Assert.AreEqual (expected, actual, message);
+               }
+
+               public static void Save ()
+               {
+                       if (!CreateMode)
+                               return;
+
+                       foreach (var test in asserts)
+                               test.Value.Save (Path.Combine (Location, test.Key + ext));
+               }
+
+               public static string GetTestMethodName ()
+               {
+                       var stackTrace = new StackTrace ();
+                       foreach (StackFrame stackFrame in stackTrace.GetFrames ()) {
+                               MethodBase methodBase = stackFrame.GetMethod ();
+                               Object [] attributes = methodBase.GetCustomAttributes (typeof (TestAttribute), false);
+                               if (attributes.Length >= 1)
+                                       return methodBase.DeclaringType.FullName + "." + methodBase.Name;
+                       }
+                       return "Not called from a test method";
+               }
+
+               public class Asserts {
+                       private const string escapes = "\n\t\0\r\\";
+                       private const string unescapes = @"\n\t\0\r\\";
+                       private static readonly Regex regex = new Regex (@"\\u(?<Value>[a-zA-Z0-9]{4})", RegexOptions.Compiled);
+                       private readonly Dictionary<string, string> values = new Dictionary<string, string> ();
+
+                       public void AddExpected (string id, string value)
+                       {
+                               values.Add (id, value);
+                       }
+
+                       public string GetExpected (string id)
+                       {
+                               return values [id];
+                       }
+
+                       public void Save (string filePath)
+                       {
+                               string dir = Path.GetDirectoryName (filePath);
+                               if (!Directory.Exists (dir))
+                                       Directory.CreateDirectory (dir);
+
+                               var sw = new StreamWriter (filePath, false, Encoding.UTF8);
+
+                               foreach (var kv in values) {
+                                       sw.WriteLine (Escape (kv.Key));
+                                       sw.WriteLine (Escape (kv.Value));
+                               }
+
+                               sw.Close ();
+                       }
+
+                       public void Load (string filePath)
+                       {
+                               if (!File.Exists (filePath))
+                                       return;
+
+                               var sr = new StreamReader (filePath, Encoding.UTF8);
+
+                               while (sr.Peek () > 0) {
+                                       string id = Unescape (sr.ReadLine ());
+
+                                       if (sr.Peek () == 0)
+                                               break;
+
+                                       string value = Unescape (sr.ReadLine ());
+                                       values.Add (id, value);
+                               }
+
+                               sr.Close ();
+                       }
+
+                       private static string Escape (string str)
+                       {
+                               var sb = new StringBuilder ();
+                               foreach (char c in str) {
+                                       int i = escapes.IndexOf (c);
+                                       if (i != -1) {
+                                               sb.Append (unescapes.Substring (i*2, 2));
+                                               continue;
+                                       }
+
+                                       if (c >= 0x7f || c < 0x20) {
+                                               sb.Append (string.Format (@"\u{0:x4}", (int) c));
+                                               continue;
+                                       }
+
+                                       sb.Append (c);
+                               }
+                               return sb.ToString ();
+                       }
+
+                       private static string Unescape (string str)
+                       {
+                               for (int i = 0; i < escapes.Length; i++)
+                                       str = str.Replace (unescapes.Substring (i*2, 2), "" + escapes [i]);
+
+                               return regex.Replace (str,
+                                       m => ((char) int.Parse (m.Groups ["Value"].Value, NumberStyles.HexNumber)).ToString ());
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/class/System/Test/System/UriPermutationsTest.cs b/mcs/class/System/Test/System/UriPermutationsTest.cs
new file mode 100644 (file)
index 0000000..f98e006
--- /dev/null
@@ -0,0 +1,218 @@
+using System;
+using System.Reflection;
+using System.Text;
+using NUnit.Framework;
+
+namespace MonoTests.System {
+       [TestFixture]
+       public class UriPermutationsTest {
+
+               // Set this to true to generate the expected values
+               // The tests should run first on .NET with CreateMode = true
+               // The generated files should then be used when running the tests in Mono with CreateMode = false
+               private const bool createMode = true;
+
+               private const string location = "./Test/System/UriPermutationsTest/";
+
+               private const string nonAsciiTestedChars = "☕";
+
+               private static readonly string [] schemes = {
+                       "http://", "https://", "file://", "ftp://", "gopher://", "ldap://", "mailto:",
+                       "net.pipe://", "net.tcp://", "news:", "nntp://", "telnet://", "custom:", "custom://"
+               };
+
+               private static readonly string [] componentLocations = {
+                       "a/a", "a/a/a", "a/a?", "a/a#"
+               };
+
+               private static readonly string [] reduceLocations = {
+                       "a/b/a./a", "a/b/.a/a", "a/b/./a", "a/b/a../a", "a/b/..a/a", "a/b/../a", "a/b/.../a"
+               };
+
+               public static readonly bool IriParsing;
+
+               static UriPermutationsTest ()
+               {
+                       FieldInfo iriParsingField = typeof (Uri).GetField ("s_IriParsing",
+                               BindingFlags.Static | BindingFlags.GetField | BindingFlags.NonPublic);
+                       if (iriParsingField != null)
+                               IriParsing = (bool) iriParsingField.GetValue (null);
+               }
+
+               [SetUp]
+               public void Setup()
+               {
+                       StringTester.CreateMode = createMode;
+                       StringTester.Location = location;
+                       StringTester.Location += (IriParsing) ? "IriParsing" : "NoIriParsing";
+               }
+
+               [TearDown]
+               public void Teardown()
+               {
+                       StringTester.Save();
+               }
+
+               private string GetTestedChars ()
+               {
+                       var sb = new StringBuilder ();
+                       for (int c = 0; c <= 0x7f; c++)
+                               sb.Append ((char) c);
+
+                       foreach (char c in nonAsciiTestedChars)
+                               sb.Append (c);
+
+                       return sb.ToString ();
+               }
+
+               internal static string HexEscapeMultiByte (char character)
+               {
+                       const string hex_upper_chars = "0123456789ABCDEF";
+                       string ret = "";
+                       byte [] bytes = Encoding.UTF8.GetBytes (new [] {character});
+                       foreach (byte b in bytes)
+                               ret += "%" + hex_upper_chars [((b & 0xf0) >> 4)] + hex_upper_chars [((b & 0x0f))];
+
+                       return ret;
+               }
+
+               private void TestScheme(Action<string> action)
+               {
+                       foreach (string scheme in schemes)
+                               action(scheme);
+               }
+
+               private delegate string UriToStringDelegate (Uri uri);
+
+               private void TestLocation (string id, string str, UriToStringDelegate toString, bool testRelative = true)
+               {
+                       TestScheme (scheme => {
+                               string uri = scheme + str;
+                               string actual = toString (new Uri (scheme + str, UriKind.Absolute));
+                               StringTester.Assert (scheme + id, actual, "");
+                       });
+
+                       if (!testRelative)
+                               return;
+
+                       string relActual = toString (new Uri ("./" + str, UriKind.Relative));
+                       StringTester.Assert ("./" + id, relActual, "");
+               }
+
+               private void TestLocations (string [] locations, string id, string str, UriToStringDelegate toString,
+                       bool testRelative = true)
+               {
+                       foreach (string location in locations)
+                               TestLocation (location + id, location + str, toString, testRelative);
+               }
+
+               private void TestPercentageEncoding (UriToStringDelegate toString, bool testRelative = false, string id = "")
+               {
+                       string unescapedStr = GetTestedChars ();
+
+                       var sb = new StringBuilder ();
+                       foreach (char c in unescapedStr)
+                               sb.Append (HexEscapeMultiByte (c));
+                       string escapedStr = sb.ToString ();
+
+                       TestLocations (componentLocations, "[un]" + id, escapedStr, toString, testRelative);
+                       TestLocations (componentLocations, "[es]" + id, escapedStr, toString, testRelative);
+               }
+
+               private void TestReduce (UriToStringDelegate toString, bool testRelative = true)
+               {
+                       TestLocations (reduceLocations, "", "", toString, testRelative);
+               }
+
+               private void TestComponent (UriComponents component)
+               {
+                       TestPercentageEncoding (uri => uri.GetComponents (component, UriFormat.SafeUnescaped), id: "[SafeUnescaped]");
+                       TestPercentageEncoding (uri => uri.GetComponents (component, UriFormat.Unescaped), id: "[Unescaped]");
+                       TestPercentageEncoding (uri => uri.GetComponents (component, UriFormat.UriEscaped), id: "[UriEscaped]");
+               }
+
+               [Test]
+               public void PercentageEncoding_AbsoluteUri ()
+               {
+                       TestPercentageEncoding (uri => uri.AbsoluteUri);
+               }
+
+               [Test]
+               public void PercentageEncoding_Fragment ()
+               {
+                       TestPercentageEncoding (uri => uri.Fragment);
+               }
+
+               [Test]
+               public void PercentageEncoding_GetComponents_AbsoluteUri ()
+               {
+                       TestComponent (UriComponents.AbsoluteUri);
+               }
+
+               [Test]
+               public void PercentageEncoding_GetComponents_Fragment ()
+               {
+                       TestComponent (UriComponents.Fragment);
+               }
+
+               [Test]
+               public void PercentageEncoding_GetComponents_Host ()
+               {
+                       TestComponent (UriComponents.Host);
+               }
+
+               [Test]
+               public void PercentageEncoding_GetComponents_Path ()
+               {
+                       TestComponent (UriComponents.Path);
+               }
+
+               [Test]
+               public void PercentageEncoding_GetComponents_PathAndQuery ()
+               {
+                       TestComponent (UriComponents.PathAndQuery);
+               }
+
+               [Test]
+               public void PercentageEncoding_GetComponents_Query ()
+               {
+                       TestComponent (UriComponents.Query);
+               }
+
+               [Test]
+               public void PercentageEncoding_LocalPath ()
+               {
+                       TestPercentageEncoding (uri => uri.LocalPath);
+               }
+
+               [Test]
+               public void PercentageEncoding_Query ()
+               {
+                       TestPercentageEncoding (uri => uri.Query);
+               }
+
+               [Test]
+               public void PercentageEncoding_ToString ()
+               {
+                       TestPercentageEncoding (uri => uri.ToString (), true);
+               }
+
+               [Test]
+               public void Reduce_AbsoluteUri ()
+               {
+                       TestReduce (uri => uri.AbsoluteUri, false);
+               }
+
+               [Test]
+               public void Reduce_LocalPath ()
+               {
+                       TestReduce (uri => uri.LocalPath, false);
+               }
+
+               [Test]
+               public void Reduce_ToString ()
+               {
+                       TestReduce (uri => uri.ToString (), true);
+               }
+       }
+}
\ No newline at end of file