1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections.Generic;
6 using Xunit;
7 
8 namespace System.Text.RegularExpressions.Tests
9 {
10     public class RegexSplitTests
11     {
Split_NonCompiled_TestData()12         public static IEnumerable<object[]> Split_NonCompiled_TestData()
13         {
14             yield return new object[] { "    ", "word0    word1    word2    word3", RegexOptions.None, 32, 0, new string[] { "word0", "word1", "word2", "word3" } };
15 
16             yield return new object[] { ":", "kkk:lll:mmm:nnn:ooo", RegexOptions.None, 19, 0, new string[] { "kkk", "lll", "mmm", "nnn", "ooo" } };
17             yield return new object[] { ":", "kkk:lll:mmm:nnn:ooo", RegexOptions.None, 0, 0, new string[] { "kkk", "lll", "mmm", "nnn", "ooo" } };
18 
19             yield return new object[] { @"(\s)?(-)", "once -upon-a time", RegexOptions.None, 17, 0, new string[] { "once", " ", "-", "upon", "-", "a time" } };
20             yield return new object[] { @"(\s)?(-)", "once upon a time", RegexOptions.None, 16, 0, new string[] { "once upon a time" } };
21             yield return new object[] { @"(\s)?(-)", "once - -upon- a- time", RegexOptions.None, 21, 0, new string[] { "once", " ", "-", "", " ", "-", "upon", "-", " a", "-", " time" } };
22 
23             yield return new object[] { "a(.)c(.)e", "123abcde456aBCDe789", RegexOptions.None, 19, 0, new string[] { "123", "b", "d", "456aBCDe789" } };
24             yield return new object[] { "a(.)c(.)e", "123abcde456aBCDe789", RegexOptions.IgnoreCase, 19, 0, new string[] { "123", "b", "d", "456", "B", "D", "789" } };
25 
26             yield return new object[] { "a(?<dot1>.)c(.)e", "123abcde456aBCDe789", RegexOptions.None, 19, 0, new string[] { "123", "d", "b", "456aBCDe789" } };
27             yield return new object[] { "a(?<dot1>.)c(.)e", "123abcde456aBCDe789", RegexOptions.IgnoreCase, 19, 0, new string[] { "123", "d", "b", "456", "D", "B", "789" } };
28 
29             // RightToLeft
30             yield return new object[] { "a(.)c(.)e", "123abcde456aBCDe789", RegexOptions.RightToLeft, 19, 19, new string[] { "123", "d", "b", "456aBCDe789" } };
31             yield return new object[] { "a(.)c(.)e", "123abcde456aBCDe789", RegexOptions.RightToLeft | RegexOptions.IgnoreCase, 19, 19, new string[] { "123", "d", "b", "456", "D", "B", "789" } };
32 
33             yield return new object[] { "a(?<dot1>.)c(.)e", "123abcde456aBCDe789", RegexOptions.RightToLeft, 19, 19, new string[] { "123", "b", "d", "456aBCDe789" } };
34             yield return new object[] { "a(?<dot1>.)c(.)e", "123abcde456aBCDe789", RegexOptions.RightToLeft | RegexOptions.IgnoreCase, 19, 19, new string[] { "123", "b", "d", "456", "B", "D", "789" } };
35 
36             // IgnoreCase
37             yield return new object[] { "[abc]", "1A2B3C4", RegexOptions.IgnoreCase, 7, 0, new string[] { "1", "2", "3", "4" } };
38 
39             // Custom index
40             yield return new object[] { ":", "kkk:lll:mmm:nnn:ooo", RegexOptions.None, 2, 0, new string[] { "kkk", "lll:mmm:nnn:ooo" } };
41             yield return new object[] { ":", "kkk:lll:mmm:nnn:ooo", RegexOptions.None, 3, 6, new string[] { "kkk:lll", "mmm", "nnn:ooo" } };
42 
43             // RightToLeft
44             yield return new object[] { "foo", "0123456789foo4567890foo         ", RegexOptions.RightToLeft, 32, 32, new string[] { "0123456789", "4567890", "         " } };
45 
46             yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 20, 20, new string[] { "", "a", "b", "c", "d", "e", "f", "g", "h", "i", "k" } };
47             yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 10, 20, new string[] { "1a", "b", "c", "d", "e", "f", "g", "h", "i", "k" } };
48             yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 2, 20, new string[] { "1a2b3c4d5e6f7g8h9i", "k" } };
49             yield return new object[] { @"\d", "1a2b3c4d5e6f7g8h9i0k", RegexOptions.RightToLeft, 1, 20, new string[] { "1a2b3c4d5e6f7g8h9i0k" } };
50         }
51 
52         [Theory]
53         [MemberData(nameof(Split_NonCompiled_TestData))]
54         [MemberData(nameof(RegexCompilationHelper.TransformRegexOptions), nameof(Split_NonCompiled_TestData), 2, MemberType = typeof(RegexCompilationHelper))]
Split(string pattern, string input, RegexOptions options, int count, int start, string[] expected)55         public void Split(string pattern, string input, RegexOptions options, int count, int start, string[] expected)
56         {
57             bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
58             bool isDefaultCount = RegexHelpers.IsDefaultStart(input, options, count);
59             if (options == RegexOptions.None)
60             {
61                 // Use Split(string), Split(string, string), Split(string, int) or Split(string, int, int)
62                 if (isDefaultStart && isDefaultCount)
63                 {
64                     // Use Split(string) or Split(string, string)
65                     Assert.Equal(expected, new Regex(pattern).Split(input));
66                     Assert.Equal(expected, Regex.Split(input, pattern));
67                 }
68                 if (isDefaultStart)
69                 {
70                     // Use Split(string, int)
71                     Assert.Equal(expected, new Regex(pattern).Split(input, count));
72                 }
73                 // Use Split(string, int, int)
74                 Assert.Equal(expected, new Regex(pattern).Split(input, count, start));
75             }
76             if (isDefaultStart && isDefaultCount)
77             {
78                 // Use Split(string, string, RegexOptions)
79                 Assert.Equal(expected, Regex.Split(input, pattern, options));
80             }
81             if (isDefaultStart)
82             {
83                 // Use Split(string, int)
84                 Assert.Equal(expected, new Regex(pattern, options).Split(input, count));
85             }
86             // Use Split(string, int, int, int)
87             Assert.Equal(expected, new Regex(pattern, options).Split(input, count, start));
88         }
89 
90         [Fact]
Split_Invalid()91         public void Split_Invalid()
92         {
93             // Input is null
94             AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.Split(null, "pattern"));
95             AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.Split(null, "pattern", RegexOptions.None));
96             AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.Split(null, "pattern", RegexOptions.None, TimeSpan.FromMilliseconds(1)));
97             AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").Split(null));
98             AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").Split(null, 0));
99             AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").Split(null, 0, 0));
100 
101             // Pattern is null
102             AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.Split("input", null));
103             AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.Split("input", null, RegexOptions.None));
104             AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.Split("input", null, RegexOptions.None, TimeSpan.FromMilliseconds(1)));
105 
106             // Count is invalid
107             AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => new Regex("pattern").Split("input", -1));
108             AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => new Regex("pattern").Split("input", -1, 0));
109 
110             // Start is invalid
111             AssertExtensions.Throws<ArgumentOutOfRangeException>("startat", () => new Regex("pattern").Split("input", 0, -1));
112             AssertExtensions.Throws<ArgumentOutOfRangeException>("startat", () => new Regex("pattern").Split("input", 0, 6));
113         }
114     }
115 }
116