2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Globalization;
6 using System.Reflection;
8 using System.Text.RegularExpressions;
11 namespace MonoTests.System {
12 public class StringTester {
13 private const string ext = ".txt";
14 public static string Location = "./StringTests/";
15 public static bool CreateMode = false;
17 private static readonly Dictionary<string, Asserts> asserts = new Dictionary<string, Asserts> ();
19 public static void Assert (string id, string actual, string message = "")
21 string testFullName = GetTestMethodName ();
24 if (!asserts.TryGetValue (testFullName, out testAsserts)) {
25 testAsserts = new Asserts ();
28 string filePath = Path.GetFullPath (Path.Combine (Location, testFullName + ext));
29 if (!File.Exists (filePath)) {
30 NUnit.Framework.Assert.Ignore (filePath + " does not exist. \n" +
31 "The file should be generated by running on .NET the same test with StringTester.CreateMode = true.");
34 testAsserts.Load (filePath);
37 asserts.Add (testFullName, testAsserts);
41 testAsserts.AddExpected (id, actual);
45 if (string.IsNullOrEmpty(message))
48 string expected = testAsserts.GetExpected (id);
49 NUnit.Framework.Assert.AreEqual (expected, actual, message);
52 public static void Save ()
57 foreach (var test in asserts)
58 test.Value.Save (Path.Combine (Location, test.Key + ext));
61 public static string GetTestMethodName ()
63 var stackTrace = new StackTrace ();
64 foreach (StackFrame stackFrame in stackTrace.GetFrames ()) {
65 MethodBase methodBase = stackFrame.GetMethod ();
66 Object [] attributes = methodBase.GetCustomAttributes (typeof (TestAttribute), false);
67 if (attributes.Length >= 1)
68 return methodBase.DeclaringType.FullName + "." + methodBase.Name;
70 return "Not called from a test method";
73 public class Asserts {
74 private const string escapes = "\n\t\0\r\\";
75 private const string unescapes = @"\n\t\0\r\\";
76 private static readonly Regex regex = new Regex (@"\\u(?<Value>[a-zA-Z0-9]{4})", RegexOptions.Compiled);
77 private readonly Dictionary<string, string> values = new Dictionary<string, string> ();
79 public void AddExpected (string id, string value)
81 values.Add (id, value);
84 public string GetExpected (string id)
89 public void Save (string filePath)
91 string dir = Path.GetDirectoryName (filePath);
92 if (!Directory.Exists (dir))
93 Directory.CreateDirectory (dir);
95 var sw = new StreamWriter (filePath, false, Encoding.UTF8);
97 foreach (var kv in values) {
98 sw.WriteLine (Escape (kv.Key));
99 sw.WriteLine (Escape (kv.Value));
105 public void Load (string filePath)
107 if (!File.Exists (filePath))
110 var sr = new StreamReader (filePath, Encoding.UTF8);
112 while (sr.Peek () > 0) {
113 string id = Unescape (sr.ReadLine ());
118 string value = Unescape (sr.ReadLine ());
119 values.Add (id, value);
125 private static string Escape (string str)
127 var sb = new StringBuilder ();
128 foreach (char c in str) {
129 int i = escapes.IndexOf (c);
131 sb.Append (unescapes.Substring (i*2, 2));
135 if (c >= 0x7f || c < 0x20) {
136 sb.Append (string.Format (@"\u{0:x4}", (int) c));
142 return sb.ToString ();
145 private static string Unescape (string str)
147 for (int i = 0; i < escapes.Length; i++)
148 str = str.Replace (unescapes.Substring (i*2, 2), "" + escapes [i]);
150 return regex.Replace (str,
151 m => ((char) int.Parse (m.Groups ["Value"].Value, NumberStyles.HexNumber)).ToString ());