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