[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Constraints / MsgUtils.cs
1 // ***********************************************************************
2 // Copyright (c) 2012 Charlie Poole
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
23 #define PORTABLE
24 #define TIZEN
25 #define NUNIT_FRAMEWORK
26 #define NUNITLITE
27 #define NET_4_5
28 #define PARALLEL
29 using System;
30 using System.Text;
31 using System.Collections;
32 using System.Globalization;
33 using NUnit.Framework.Internal;
34
35 namespace NUnit.Framework.Constraints
36 {
37     /// <summary>
38     /// Custom value formatter function
39     /// </summary>
40     /// <param name="val">The value</param>
41     /// <returns></returns>
42     public delegate string ValueFormatter(object val);
43
44     /// <summary>
45     /// Custom value formatter factory function
46     /// </summary>
47     /// <param name="next">The next formatter function</param>
48     /// <returns>ValueFormatter</returns>
49     /// <remarks>If the given formatter is unable to handle a certain format, it must call the next formatter in the chain</remarks>
50     public delegate ValueFormatter ValueFormatterFactory(ValueFormatter next);
51
52     /// <summary>
53     /// Static methods used in creating messages
54     /// </summary>
55     internal static class MsgUtils
56     {
57         /// <summary>
58         /// Static string used when strings are clipped
59         /// </summary>
60         private const string ELLIPSIS = "...";
61
62         /// <summary>
63         /// Formatting strings used for expected and actual _values
64         /// </summary>
65         private static readonly string Fmt_Null = "null";
66         private static readonly string Fmt_EmptyString = "<string.Empty>";
67         private static readonly string Fmt_EmptyCollection = "<empty>";
68
69         private static readonly string Fmt_String = "\"{0}\"";
70         private static readonly string Fmt_Char = "'{0}'";
71         private static readonly string Fmt_DateTime = "yyyy-MM-dd HH:mm:ss.fff";
72 #if !NETCF
73                 private static readonly string Fmt_DateTimeOffset = "yyyy-MM-dd HH:mm:ss.fffzzz";
74 #endif
75                 private static readonly string Fmt_ValueType = "{0}";
76         private static readonly string Fmt_Default = "<{0}>";
77
78         /// <summary>
79         /// Current head of chain of value formatters. Public for testing.
80         /// </summary>
81         public static ValueFormatter DefaultValueFormatter { get; set; }
82
83         static MsgUtils()
84         {
85             // Initialize formatter to default for values of indeterminate type.
86             DefaultValueFormatter = val => string.Format(Fmt_Default, val);
87
88             AddFormatter(next => val => val is ValueType ? string.Format(Fmt_ValueType, val) : next(val));
89
90             AddFormatter(next => val => val is DateTime ? FormatDateTime((DateTime)val) : next(val));
91
92 #if !NETCF
93                         AddFormatter(next => val => val is DateTimeOffset ? FormatDateTimeOffset ((DateTimeOffset)val) : next (val));
94 #endif
95
96                         AddFormatter(next => val => val is decimal ? FormatDecimal((decimal)val) : next(val));
97
98             AddFormatter(next => val => val is float ? FormatFloat((float)val) : next(val));
99
100             AddFormatter(next => val => val is double ? FormatDouble((double)val) : next(val));
101
102             AddFormatter(next => val => val is char ? string.Format(Fmt_Char, val) : next(val));
103
104             AddFormatter(next => val => val is IEnumerable ? FormatCollection((IEnumerable)val, 0, 10) : next(val));
105
106             AddFormatter(next => val => val is string ? FormatString((string)val) : next(val));
107
108             AddFormatter(next => val => val.GetType().IsArray ? FormatArray((Array)val) : next(val));
109
110 #if NETCF
111             AddFormatter(next => val =>
112             {
113                 var vi = val as System.Reflection.MethodInfo;
114                 return (vi != null && vi.IsGenericMethodDefinition)
115                         ? string.Format(Fmt_Default, vi.Name + "<>") 
116                         : next(val);
117             });
118 #endif
119         }
120
121         /// <summary>
122         /// Add a formatter to the chain of responsibility.
123         /// </summary>
124         /// <param name="formatterFactory"></param>
125         public static void AddFormatter(ValueFormatterFactory formatterFactory)
126         {
127             DefaultValueFormatter = formatterFactory(DefaultValueFormatter);
128         }
129
130         /// <summary>
131         /// Formats text to represent a generalized value.
132         /// </summary>
133         /// <param name="val">The value</param>
134         /// <returns>The formatted text</returns>
135         public static string FormatValue(object val)
136         {
137             if (val == null)
138                 return Fmt_Null;
139
140             var context = TestExecutionContext.CurrentContext;
141
142             if (context != null)
143                 return context.CurrentValueFormatter(val);
144             else
145                 return DefaultValueFormatter(val);
146         }
147
148         /// <summary>
149         /// Formats text for a collection value,
150         /// starting at a particular point, to a max length
151         /// </summary>
152         /// <param name="collection">The collection containing elements to write.</param>
153         /// <param name="start">The starting point of the elements to write</param>
154         /// <param name="max">The maximum number of elements to write</param>
155         public static string FormatCollection(IEnumerable collection, long start, int max)
156         {
157             int count = 0;
158             int index = 0;
159             System.Text.StringBuilder sb = new System.Text.StringBuilder();
160
161             foreach (object obj in collection)
162             {
163                 if (index++ >= start)
164                 {
165                     if (++count > max)
166                         break;
167                     sb.Append(count == 1 ? "< " : ", ");
168                     sb.Append(FormatValue(obj));
169                 }
170             }
171
172             if (count == 0)
173                 return Fmt_EmptyCollection;
174
175             if (count > max)
176                 sb.Append("...");
177
178             sb.Append(" >");
179
180             return sb.ToString();
181         }
182
183         private static string FormatArray(Array array)
184         {
185             if (array.Length == 0)
186                 return Fmt_EmptyCollection;
187
188             int rank = array.Rank;
189             int[] products = new int[rank];
190
191             for (int product = 1, r = rank; --r >= 0; )
192                 products[r] = product *= array.GetLength(r);
193
194             int count = 0;
195             System.Text.StringBuilder sb = new System.Text.StringBuilder();
196             foreach (object obj in array)
197             {
198                 if (count > 0)
199                     sb.Append(", ");
200
201                 bool startSegment = false;
202                 for (int r = 0; r < rank; r++)
203                 {
204                     startSegment = startSegment || count % products[r] == 0;
205                     if (startSegment) sb.Append("< ");
206                 }
207
208                 sb.Append(FormatValue(obj));
209
210                 ++count;
211
212                 bool nextSegment = false;
213                 for (int r = 0; r < rank; r++)
214                 {
215                     nextSegment = nextSegment || count % products[r] == 0;
216                     if (nextSegment) sb.Append(" >");
217                 }
218             }
219
220             return sb.ToString();
221         }
222
223         private static string FormatString(string s)
224         {
225             return s == string.Empty
226                 ? Fmt_EmptyString
227                 : string.Format(Fmt_String, s);
228         }
229
230         private static string FormatDouble(double d)
231         {
232
233             if (double.IsNaN(d) || double.IsInfinity(d))
234                 return d.ToString();
235             else
236             {
237                 string s = d.ToString("G17", CultureInfo.InvariantCulture);
238
239                 if (s.IndexOf('.') > 0)
240                     return s + "d";
241                 else
242                     return s + ".0d";
243             }
244         }
245
246         private static string FormatFloat(float f)
247         {
248             if (float.IsNaN(f) || float.IsInfinity(f))
249                 return f.ToString();
250             else
251             {
252                 string s = f.ToString("G9", CultureInfo.InvariantCulture);
253
254                 if (s.IndexOf('.') > 0)
255                     return s + "f";
256                 else
257                     return s + ".0f";
258             }
259         }
260
261         private static string FormatDecimal(Decimal d)
262         {
263             return d.ToString("G29", CultureInfo.InvariantCulture) + "m";
264         }
265
266         private static string FormatDateTime(DateTime dt)
267         {
268             return dt.ToString(Fmt_DateTime, CultureInfo.InvariantCulture);
269         }
270
271 #if !NETCF
272                 private static string FormatDateTimeOffset(DateTimeOffset dto)
273         {
274             return dto.ToString(Fmt_DateTimeOffset, CultureInfo.InvariantCulture);
275         }
276 #endif
277
278                 /// <summary>
279                 /// Returns the representation of a type as used in NUnitLite.
280                 /// This is the same as Type.ToString() except for arrays,
281                 /// which are displayed with their declared sizes.
282                 /// </summary>
283                 /// <param name="obj"></param>
284                 /// <returns></returns>
285                 public static string GetTypeRepresentation(object obj)
286         {
287             Array array = obj as Array;
288             if (array == null)
289                 return string.Format("<{0}>", obj.GetType());
290
291             StringBuilder sb = new StringBuilder();
292             Type elementType = array.GetType();
293             int nest = 0;
294             while (elementType.IsArray)
295             {
296                 elementType = elementType.GetElementType();
297                 ++nest;
298             }
299             sb.Append(elementType.ToString());
300             sb.Append('[');
301             for (int r = 0; r < array.Rank; r++)
302             {
303                 if (r > 0) sb.Append(',');
304                 sb.Append(array.GetLength(r));
305             }
306             sb.Append(']');
307
308             while (--nest > 0)
309                 sb.Append("[]");
310
311             return string.Format("<{0}>", sb.ToString());
312         }
313         /// <summary>
314         /// Converts any control characters in a string 
315         /// to their escaped representation.
316         /// </summary>
317         /// <param name="s">The string to be converted</param>
318         /// <returns>The converted string</returns>
319         public static string EscapeControlChars(string s)
320         {
321             if (s != null)
322             {
323                 StringBuilder sb = new StringBuilder();
324
325                 foreach (char c in s)
326                 {
327                     switch (c)
328                     {
329                         //case '\'':
330                         //    sb.Append("\\\'");
331                         //    break;
332                         //case '\"':
333                         //    sb.Append("\\\"");
334                         //    break;
335                         case '\\':
336                             sb.Append("\\\\");
337                             break;
338                         case '\0':
339                             sb.Append("\\0");
340                             break;
341                         case '\a':
342                             sb.Append("\\a");
343                             break;
344                         case '\b':
345                             sb.Append("\\b");
346                             break;
347                         case '\f':
348                             sb.Append("\\f");
349                             break;
350                         case '\n':
351                             sb.Append("\\n");
352                             break;
353                         case '\r':
354                             sb.Append("\\r");
355                             break;
356                         case '\t':
357                             sb.Append("\\t");
358                             break;
359                         case '\v':
360                             sb.Append("\\v");
361                             break;
362
363                         case '\x0085':
364                         case '\x2028':
365                         case '\x2029':
366                             sb.Append(string.Format("\\x{0:X4}", (int)c));
367                             break;
368
369                         default:
370                             sb.Append(c);
371                             break;
372                     }
373                 }
374
375                 s = sb.ToString();
376             }
377
378             return s;
379         }
380
381         /// <summary>
382         /// Return the a string representation for a set of indices into an array
383         /// </summary>
384         /// <param name="indices">Array of indices for which a string is needed</param>
385         public static string GetArrayIndicesAsString(int[] indices)
386         {
387             StringBuilder sb = new StringBuilder();
388             sb.Append('[');
389             for (int r = 0; r < indices.Length; r++)
390             {
391                 if (r > 0) sb.Append(',');
392                 sb.Append(indices[r].ToString());
393             }
394             sb.Append(']');
395             return sb.ToString();
396         }
397
398         /// <summary>
399         /// Get an array of indices representing the point in a collection or
400         /// array corresponding to a single int index into the collection.
401         /// </summary>
402         /// <param name="collection">The collection to which the indices apply</param>
403         /// <param name="index">Index in the collection</param>
404         /// <returns>Array of indices</returns>
405         public static int[] GetArrayIndicesFromCollectionIndex(IEnumerable collection, long index)
406         {
407             Array array = collection as Array;
408
409             int rank = array == null ? 1 : array.Rank;
410             int[] result = new int[rank];
411
412             for (int r = rank; --r > 0; )
413             {
414                 int l = array.GetLength(r);
415                 result[r] = (int)index % l;
416                 index /= l;
417             }
418
419             result[0] = (int)index;
420             return result;
421         }
422
423         /// <summary>
424         /// Clip a string to a given length, starting at a particular offset, returning the clipped
425         /// string with ellipses representing the removed parts
426         /// </summary>
427         /// <param name="s">The string to be clipped</param>
428         /// <param name="maxStringLength">The maximum permitted length of the result string</param>
429         /// <param name="clipStart">The point at which to start clipping</param>
430         /// <returns>The clipped string</returns>
431         public static string ClipString(string s, int maxStringLength, int clipStart)
432         {
433             int clipLength = maxStringLength;
434             StringBuilder sb = new StringBuilder();
435
436             if (clipStart > 0)
437             {
438                 clipLength -= ELLIPSIS.Length;
439                 sb.Append(ELLIPSIS);
440             }
441
442             if (s.Length - clipStart > clipLength)
443             {
444                 clipLength -= ELLIPSIS.Length;
445                 sb.Append(s.Substring(clipStart, clipLength));
446                 sb.Append(ELLIPSIS);
447             }
448             else if (clipStart > 0)
449                 sb.Append(s.Substring(clipStart));
450             else
451                 sb.Append(s);
452
453             return sb.ToString();
454         }
455
456         /// <summary>
457         /// Clip the expected and actual strings in a coordinated fashion, 
458         /// so that they may be displayed together.
459         /// </summary>
460         /// <param name="expected"></param>
461         /// <param name="actual"></param>
462         /// <param name="maxDisplayLength"></param>
463         /// <param name="mismatch"></param>
464         public static void ClipExpectedAndActual(ref string expected, ref string actual, int maxDisplayLength, int mismatch)
465         {
466             // Case 1: Both strings fit on line
467             int maxStringLength = Math.Max(expected.Length, actual.Length);
468             if (maxStringLength <= maxDisplayLength)
469                 return;
470
471             // Case 2: Assume that the tail of each string fits on line
472             int clipLength = maxDisplayLength - ELLIPSIS.Length;
473             int clipStart = maxStringLength - clipLength;
474
475             // Case 3: If it doesn't, center the mismatch position
476             if (clipStart > mismatch)
477                 clipStart = Math.Max(0, mismatch - clipLength / 2);
478
479             expected = ClipString(expected, maxDisplayLength, clipStart);
480             actual = ClipString(actual, maxDisplayLength, clipStart);
481         }
482
483         /// <summary>
484         /// Shows the position two strings start to differ.  Comparison 
485         /// starts at the start index.
486         /// </summary>
487         /// <param name="expected">The expected string</param>
488         /// <param name="actual">The actual string</param>
489         /// <param name="istart">The index in the strings at which comparison should start</param>
490         /// <param name="ignoreCase">Boolean indicating whether case should be ignored</param>
491         /// <returns>-1 if no mismatch found, or the index where mismatch found</returns>
492         static public int FindMismatchPosition(string expected, string actual, int istart, bool ignoreCase)
493         {
494             int length = Math.Min(expected.Length, actual.Length);
495
496             string s1 = ignoreCase ? expected.ToLower() : expected;
497             string s2 = ignoreCase ? actual.ToLower() : actual;
498
499             for (int i = istart; i < length; i++)
500             {
501                 if (s1[i] != s2[i])
502                     return i;
503             }
504
505             //
506             // Strings have same content up to the length of the shorter string.
507             // Mismatch occurs because string lengths are different, so show
508             // that they start differing where the shortest string ends
509             //
510             if (expected.Length != actual.Length)
511                 return length;
512
513             //
514             // Same strings : We shouldn't get here
515             //
516             return -1;
517         }
518     }
519 }