* RegexBugs.cs: No longer derive from deprecated Assertion class.
[mono.git] / mcs / class / System / Test / System.Text.RegularExpressions / RegexTest.cs
1 //
2 // assembly:    System_test
3 // namespace:   MonoTests.System.Text.RegularExpressions
4 // file:        RegexTest.cs
5 //
6 // Authors:     
7 //   Juraj Skripsky (juraj@hotfeet.ch)
8 //
9 // (c) 2003 Juraj Skripsky
10
11 using System;
12 using System.Text.RegularExpressions;
13
14 #if NET_2_0
15 using System.Collections.Generic;
16 #endif
17
18 using NUnit.Framework;
19
20 namespace MonoTests.System.Text.RegularExpressions
21 {
22         [TestFixture]
23         public class RegexTest
24         {
25 #if NET_2_0
26                 private int cache_initial_value;
27
28                 [TestFixtureSetUp]
29                 public void FixtureSetUp ()
30                 {
31                         cache_initial_value = Regex.CacheSize;
32                 }
33
34                 [TearDown]
35                 public void TearDown ()
36                 {
37                         Regex.CacheSize = cache_initial_value;
38                 }
39 #endif
40
41                 [Test]
42                 public void Simple ()
43                 {
44                         char[] c = { (char)32, (char)8212, (char)32 };
45                         string s = new String(c);
46                         Assert.IsTrue (Regex.IsMatch(s, s), "char");
47                 }
48                 
49                 [Test]
50                 public void Unescape ()
51                 {
52                         string inString = @"\a\b\t\r\v\f\n\e\02400\x231\cC\ufffff\*";
53                         char [] c = { (char)7, (char)8, (char)9, (char)13, 
54                                       (char)11, (char)12, (char)10, (char)27, (char) 20,
55                                       (char)48, (char)48, (char)35, (char)49, 
56                                       (char)3, (char)65535, (char)102, (char)42
57                         };
58                         string expectedString = new String(c);
59                         string outString = Regex.Unescape(inString);
60
61                         Assert.AreEqual (outString, expectedString, "unescape");
62                 }
63
64                 [Test]
65                 public void Match1 ()
66                 {
67                         Regex email = new Regex ("(?<user>[^@]+)@(?<domain>.+)");
68                         Match m;
69
70                         m = email.Match ("mono@go-mono.com");
71
72                         Assert.IsTrue (m.Success, "#m01");
73                         Assert.AreEqual ("mono", m.Groups ["user"].Value, "#m02");
74                         Assert.AreEqual ("go-mono.com", m.Groups ["domain"].Value, "#m03");
75
76                         m = email.Match ("mono.bugs@go-mono.com");
77                         Assert.IsTrue (m.Success, "m04");
78                         Assert.AreEqual ("mono.bugs", m.Groups ["user"].Value, "#m05");
79                         Assert.AreEqual ("go-mono.com", m.Groups ["domain"].Value, "#m06");
80                 }
81
82                 static string story =
83                         "Two little dragons lived in the forest\n" +
84                         "They spent their days collecting honey suckle,\n" +
85                         "And eating curds and whey\n" +
86                         "Until an evil sorcer came along\n" +
87                         "And chased my dragon friends away";
88
89                 struct MatchCollectionTrial {
90                         public readonly string name;
91                         public readonly string text;
92                         public readonly string regex;
93                         public readonly string [] matches;
94                         public MatchCollectionTrial (string name, string text, string regex, string [] matches)
95                         {
96                                 this.name = name;
97                                 this.text = text;
98                                 this.regex = regex;
99                                 this.matches = matches;
100                         }
101                 }
102
103                 static readonly MatchCollectionTrial [] trials = {
104                         new MatchCollectionTrial ("word", "the fat cat ate the rat", "(?<word>\\w+)", 
105                                 new string [] { "the", "fat", "cat", "ate", "the", "rat" }),
106                         new MatchCollectionTrial ("digit", "0 1 2 3 4 5 6a7b8c9d10", "(?<digit>\\d+)", 
107                                 new string [] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }),
108                         new MatchCollectionTrial ("line", story, "(?<line>.+)", 
109                                 new string [] { "Two little dragons lived in the forest",
110                                                 "They spent their days collecting honey suckle,",
111                                                 "And eating curds and whey",
112                                                 "Until an evil sorcer came along",
113                                                 "And chased my dragon friends away" }),
114                         new MatchCollectionTrial ("nonwhite", "ab 12 cde 456 fghi .,\niou", "(?<nonwhite>\\S+)",
115                                 new string [] { "ab", "12", "cde", "456", "fghi", ".,", "iou" }),
116                         new MatchCollectionTrial ("nondigit", "ab0cd1ef2", "(?<nondigit>\\D+)",
117                                 new string [] { "ab", "cd", "ef" })
118                 };
119
120                 static void runTrial (MatchCollectionTrial t)
121                 {
122                         runTrial (t, false);
123                         runTrial (t, true);
124                 }
125
126                 static void runTrial (MatchCollectionTrial t, bool rtl)
127                 {
128                         int i;
129                         MatchCollection mc;
130
131                         string name = t.name;
132                         if (rtl)
133                                 name += "-rtl";
134
135                         int len = t.matches.Length;
136                         Regex r = new Regex (t.regex, rtl ? RegexOptions.RightToLeft : RegexOptions.None);
137
138                         // Incremental mode -- this access
139                         mc = r.Matches (t.text);
140                         for (i = 0; i < len; ++i)
141                                 Assert.AreEqual (mc [i].Value, t.matches [rtl ? len - i - 1 : i], "{0}:this:{1}", name, i);
142                         Assert.AreEqual (i, mc.Count, "{0}:this:count", name);
143
144                         // Incremental mode -- enumerator
145                         mc = r.Matches (t.text);
146                         i = 0;
147                         foreach (Match m in mc) {
148                                 Assert.AreEqual (m.Value, t.matches [rtl ? len - i - 1 : i], "{0}:enum:{1}", name, i);
149                                 ++i;
150                         }
151                         Assert.AreEqual (i, len, "{0}:enum:count", name);
152
153                         // random mode
154                         Random rng = new Random ();
155                         for (int j = 0; j < len * 5; ++j) {
156                                 i = rng.Next (len);
157                                 Assert.AreEqual (mc [i].Value, t.matches [rtl ? len - i - 1 : i], "{0}:random{1}:{2}", name, j, i);
158                         }
159
160                         // Non-incremental mode
161                         mc = r.Matches (t.text);
162                         Assert.AreEqual (mc.Count, len);
163                         i = 0;
164                         foreach (Match m in mc) {
165                                 Assert.AreEqual (m.Value, t.matches [rtl ? len - i - 1 : i], "{0}:nienum:{1}", name, i);
166                                 ++i;
167                         }
168                         for (i = 0; i < len; ++i)
169                                 Assert.AreEqual (mc [i].Value, t.matches [rtl ? len - i - 1 : i], "{0}:nithis:{1}", name, i);
170                 }
171
172                 [Test]
173                 public void Matches ()
174                 {
175                         foreach (MatchCollectionTrial t in trials)
176                                 runTrial (t);
177                 }
178 #if NET_2_0
179                 [Test]
180                 public void CacheSize ()
181                 {
182                         Assert.AreEqual (15, Regex.CacheSize, "CacheSize");
183                         Regex.CacheSize = 0;
184                         Regex.CacheSize = Int32.MaxValue;
185                 }
186
187                 [Test]
188                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
189                 public void CacheSize_Negative ()
190                 {
191                         Regex.CacheSize = -1;
192                 }
193
194                 [Test]
195                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
196                 public void CacheSize_Min ()
197                 {
198                         Regex.CacheSize = Int32.MinValue;
199                 }
200
201                 static IEnumerable<uint> Primes (uint m)
202                 {
203                         if (m < 2)
204                                 yield break;
205
206                         yield return 2;
207
208                         Dictionary<uint, uint> w = new Dictionary<uint, uint> ();
209                         uint p2, n1;
210
211                         for (uint n = 3; n < m; n += 2) {
212                                 if (w.TryGetValue (n, out p2)) {
213                                         w.Remove (n);
214                                         n1 = n + p2;
215                                 } else {
216                                         yield return n;
217                                         n1 = n * n;
218                                         p2 = n + n;
219
220                                         // if there's an overflow, don't bother
221                                         if (n1 / n != n || n1 >= m)
222                                                 continue;
223                                 }
224
225                                 while (w.ContainsKey (n1))
226                                         n1 += p2;
227                                 w [n1] = p2;
228                         }
229                 }
230
231                 [Test]
232                 public void PrimeRegex ()
233                 {
234                         // Perl regex oneliner by: abigail@fnx.com (Abigail)
235                         // from: http://www.mit.edu:8008/bloom-picayune.mit.edu/perl/10138
236                         // perl -wle 'print "Prime" if (1 x shift) !~ /^1?$|^(11+?)\1+$/'
237
238                         // This is a backtracking torture test
239
240                         Regex composite = new Regex (@"^1?$|^(11+?)\1+$");
241
242                         uint i = 0;
243                         string x = "";
244
245                         foreach (uint p in Primes (3333)) {
246                                 while (i < p) {
247                                         Assert.IsTrue (composite.IsMatch (x));
248                                         ++i;
249                                         x += "1";
250                                 }
251                                 // i == p
252                                 Assert.IsFalse (composite.IsMatch (x));
253                                 ++i;
254                                 x += "1";
255                         }
256                 }
257 #endif
258         }
259 }